age pakai scrypt untuk menurunkan key dari passphrase. Key derivation function adalah algoritma yang menghitung key dari nilai-nilai input lain. Setiap operasi scrypt memakai waktu dan memory.
Post header menunjukkan sebuah salt dan sebuah work factor. Bersama passphrase, nilai-nilai itu memungkinkan scrypt menghasilkan wrapping key yang sama saat enkripsi dan dekripsi.
Key yang lebih panjang nggak bikin passphrase lebih sulit ditebak
Algoritma enkripsi memakai key dengan ukuran tetap. Passphrase bisa punya panjang yang berbeda-beda. scrypt mengubah passphrase jadi key dengan ukuran tersebut.
Konversi ini nggak menambahkan pilihan acak ke passphrase. Kalau penyerang mencoba passphrase yang benar, scrypt menghasilkan key yang benar. Password yang umum tetap mudah ditebak walaupun key hasil turunannya berukuran 32 byte.
Biaya yang berguna adalah kerja untuk setiap percobaan. Pemiliknya biasanya menurunkan key sekali untuk mendekripsi file. Penyerang harus mengulang kalkulasi itu untuk setiap kandidat passphrase.
Parameter di file age
Untuk header contoh, work factor yang tersimpan adalah 18. age menginterpretasikannya sebagai N = 2^18, atau 262.144.
Pseudocode ini menunjukkan input-nya. Ini rumus, bukan command:
wrapping key = scrypt(
passphrase = user input,
salt = "age-encryption.org/v1/scrypt" followed by the 16 salt bytes,
N = 262144,
r = 8,
p = 1,
output length = 32 bytes
)
| Parameter | Arti di contoh ini |
|---|---|
N | Cost parameter utama |
r | Parameter block size, tetap di 8 |
p | Parameter paralelisasi, tetap di 1 |
| Salt | Label age yang tetap, diikuti salt acak dari header |
| Panjang output | 32 byte untuk wrapping key |
Label yang tetap ini memisahkan pemakaian scrypt di sini dari pemakaian dengan label yang berbeda. Salt acak juga membuat kalkulasinya spesifik untuk file ini. Kedua nilai itu bukan rahasia.
Implementasi age 1.3.1 memakai parameter-parameter ini dan default-nya work factor 18. Format-nya mengizinkan work factor lain. Jadi, nilai di header penting waktu age mendekripsi file.
Kenapa satu percobaan memakai sekitar 256 MiB
scrypt memakai area memory yang besar selama kalkulasinya. Area memory utamanya berukuran kira-kira 128 × N × r byte.
Untuk contoh ini:
128 × 262144 × 8 = 268435456 bytes = 256 MiB
MiB artinya mebibyte. Satu MiB adalah 1.048.576 byte. GiB artinya gibibyte. Satu GiB adalah 1.024 MiB. Program ini juga memakai sebagian memory di luar area utama ini.
Sepuluh percobaan dalam waktu bersamaan memakai sekitar 2,5 GiB untuk area memory utamanya. Kebutuhan ini bikin serangan paralel berskala besar jadi lebih mahal. Kapasitas memory membatasi berapa banyak percobaan yang muat sekaligus. Memory bandwidth membatasi seberapa cepat hardware bisa memindahkan data.
Batasan-batasan ini nggak mencegah serangan. Pilihan hardware dan implementasi memengaruhi lajunya. Beberapa implementasi mengorbankan lebih banyak kerja kalkulasi demi memory yang lebih sedikit. Spesifikasi scrypt menjelaskan algoritma dan parameternya.
Mengukur scrypt di komputer kamu
Pengukuran awal memakai Apple M5 dan hashlib.scrypt dari Python. Pengukuran itu mencatat sekitar 0,3701 detik untuk setiap kalkulasi, atau 2,70 kalkulasi per detik. Angka-angka itu berlaku untuk pengukuran tersebut. Komputer lain bisa memberikan hasil yang berbeda.
Contoh Python ini cuma mengukur scrypt. Contoh ini nggak mendekripsi file age atau menguji authentication tag. Salt-nya menyertakan label age yang dipakai di format file.
Pakai Python 3 yang mendukung hashlib.scrypt. Pastikan memory yang tersedia lebih dari 256 MiB. Dokumentasi Python menjelaskan parameter function-nya.
-
Simpan kode ini di file baru bernama
measure_scrypt.py:import hashlib import os import time cost = 1 << 18 block_size = 8 parallelism = 1 main_memory = 128 * cost * block_size salt = b"age-encryption.org/v1/scrypt" + os.urandom(16) def derive_key(passphrase): return hashlib.scrypt( passphrase, salt=salt, n=cost, r=block_size, p=parallelism, dklen=32, # Permit memory for internal work outside the main area. maxmem=main_memory + (64 << 20), ) # Exclude the initial call from the measured calls. derive_key(b"warmup") attempts = 8 start = time.perf_counter() for index in range(attempts): derive_key(f"guess{index}".encode("ascii")) elapsed = time.perf_counter() - start print("seconds per calculation:", round(elapsed / attempts, 4)) print("calculations per second:", round(attempts / elapsed, 2)) -
Jalankan file-nya:
python3 measure_scrypt.py
Angka output pertama adalah rata-rata waktu untuk satu kalkulasi. Angka kedua adalah jumlah kalkulasi per detik. Hasil kamu bisa berbeda tergantung kecepatan prosesor, memory, versi Python, dan program lain yang sedang jalan.
Apa yang berubah dengan work factor yang lebih tinggi
Kenaikan dari 18 ke 19 bikin N jadi dua kali lipat. Area memory utama naik dari 256 MiB jadi 512 MiB. Di work factor 20, ukurannya naik jadi 1 GiB.
Waktunya biasanya ikut naik juga, tapi kamu harus mengukurnya untuk mendapat hasil yang akurat. Work factor yang lebih besar juga menaikkan biaya dekripsi yang sah.
Kalkulasi yang lambat nggak bisa menutupi passphrase yang mudah ditebak. Kalau passphrase yang benar adalah kandidat pertama, cuma butuh satu percobaan. Pemilihan acak dari kumpulan yang besar menaikkan jumlah percobaan yang diharapkan dalam exhaustive search.
Post waktu serangan menghitung perbedaan ini. Sebelum itu, post berikutnya mengikuti wrapping key sampai ke file key terenkripsi dan payload.

Memuat komentar...