age pakai ChaCha20-Poly1305 untuk mengenkripsi data dan mendeteksi perubahan pada data itu. Algoritma ini punya dua tugas di contoh passphrase. Algoritma ini mengenkripsi file key di header. Algoritma yang sama juga mengenkripsi isi file di payload.
Post scrypt memperkenalkan wrapping key. Key itu mendekripsi file key. Lalu age menurunkan payload key yang terpisah untuk isi file.
Enkripsi dan autentikasi
Cipher adalah algoritma untuk enkripsi dan dekripsi. ChaCha20-Poly1305 menggabungkan sebuah cipher dengan sebuah algoritma autentikasi:
| Bagian | Tugas |
|---|---|
ChaCha20 | Mengubah plaintext jadi ciphertext dengan sebuah key dan sebuah nonce |
Poly1305 | Membuat data autentikasi untuk message terenkripsi |
Plaintext adalah data awal yang bisa dibaca. Ciphertext adalah data terenkripsi. Nonce adalah nilai yang dipakai sekali dengan key tertentu.
Algoritma gabungan ini menghasilkan ciphertext dan authentication tag 16 byte. Selama dekripsi, tag itu memungkinkan age mendeteksi key yang salah atau perubahan pada message terenkripsi.
Nama teknis lengkapnya adalah authenticated encryption with associated data, atau AEAD. Associated data adalah informasi yang diautentikasi oleh algoritma tanpa dienkripsi. Dua operasi age yang dijelaskan di sini memakai associated data yang kosong.
Autentikasi mendeteksi perubahan. Autentikasi nggak mencegah seseorang mengubah atau menghapus file. Autentikasi itu sendiri juga nggak membuktikan identitas pengirimnya.
Tugas pertama: mengenkripsi file key
File key adalah rahasia acak berukuran 16 byte. Di mode passphrase, age mengenkripsinya dengan wrapping key dari scrypt. Operasi ini menghasilkan 16 byte ciphertext dan tag 16 byte.
Ke-32 byte itu membentuk stanza body di header. Post header menunjukkan representasi base64-nya.
Nonce untuk operasi ini adalah dua belas byte nol. Nonce yang tetap ini bergantung pada wrapping key yang baru untuk setiap enkripsi. Di mode passphrase, salt acak memberikan pemisahan ini dengan probabilitas yang sangat tinggi.
Passphrase yang salah menghasilkan wrapping key yang salah. Pengecekan autentikasi gagal di operasi pertama ini. age melaporkan incorrect passphrase sebelum mendekripsi data payload apa pun.
Tugas kedua: mengenkripsi isi file
age menurunkan payload key dari file key dan sebuah nilai acak baru berukuran 16 byte. Nilai acak itu adalah payload nonce. age menyimpannya di awal payload.
Penurunan ini pakai HKDF-SHA-256. HKDF adalah key derivation function yang membuat key terpisah untuk pemakaian tertentu. Di sini, label payload mengidentifikasi pemakaian itu.
Rumus di bawah ini adalah pseudocode:
payload key = HKDF-SHA-256(
input key material = file key,
salt = payload nonce,
info = "payload",
output length = 32 bytes
)
age membagi plaintext jadi beberapa chunk. Chunk adalah satu bagian dari data. Setiap chunk penuh berisi 64 KiB, atau 65.536 byte, sebelum enkripsi. Chunk terakhir bisa lebih kecil.
age mengenkripsi setiap chunk secara terpisah dengan payload key. Setiap chunk mendapat authentication tag-nya sendiri dan nonce 12 byte.
| Field chunk nonce | Ukuran | Arti |
|---|---|---|
| Chunk counter | 11 byte | Mulai dari nol dan bertambah untuk setiap chunk |
| Final flag | 1 byte | 0x01 untuk chunk terakhir, 0x00 untuk chunk sebelumnya |
Counter-nya pakai urutan big endian, yang menyimpan byte paling signifikan lebih dulu. Flag itu menandai akhir data yang benar. Kalau chunk terakhir hilang, dekripsi lengkapnya gagal.
Payload nonce dan chunk nonce adalah nilai yang berbeda. Payload nonce membantu menurunkan key. Chunk nonce mengidentifikasi satu operasi enkripsi dengan key itu. Spesifikasi format age mendefinisikan kedua nilai itu.
Merinci 255 byte itu
Post pertama memakai file plaintext berukuran 73 byte. File itu muat dalam satu chunk. File age binernya punya ukuran-ukuran ini:
| Bagian | Byte |
|---|---|
| Header | 150 |
| Payload nonce | 16 |
| Isi file terenkripsi | 73 |
| Authentication tag chunk | 16 |
| Total | 255 |
Payload berisi 105 byte: 16 ditambah 73 ditambah 16. Ciphertext punya panjang yang sama dengan plaintext. Byte payload tambahannya berasal dari nonce dan tag.
Mengubah satu byte di contoh
Prosedur ini pakai secret.txt.age dari post pertama. Prosedur ini membuat file terpisah bernama tampered.age. Kode Python-nya menolak menimpa file yang udah ada.
Bit adalah satu digit biner, 0 atau 1. Satu byte berisi delapan bit. Contoh ini mengubah satu bit di byte terakhir.
-
Bikin salinan yang diubah:
python3 - <<'PYTHON' from pathlib import Path data = bytearray(Path("secret.txt.age").read_bytes()) # Change one bit in the final authentication tag. data[-1] ^= 1 with open("tampered.age", "xb") as output: output.write(data) PYTHON -
Coba dekripsi salinan yang diubah itu:
age -d tampered.age -
Masukkan passphrase yang benar.
Error-nya berisi:
failed to decrypt and authenticate payload chunk
Passphrase-nya tetap mendekripsi file key. Error-nya terjadi belakangan, waktu age mengautentikasi chunk payload. Di contoh kecil ini, age nggak mengembalikan plaintext apa pun karena satu-satunya chunk gagal autentikasi.
Dekripsi bisa meninggalkan file yang nggak lengkap
age mendekripsi file besar satu chunk demi satu chunk. age bisa menulis chunk-chunk awal yang valid sebelum menemukan chunk yang rusak di bagian file yang lebih belakang. Jadi, error dekripsi bisa meninggalkan output yang nggak lengkap.
Setelah dekripsi, pastikan command-nya berhasil sebelum kamu memakai output-nya. Kalau age melaporkan error, jangan pakai output itu sebagai file yang lengkap. Sebuah tag mengautentikasi setiap chunk. Dekripsi yang berhasil untuk seluruh file juga mengautentikasi akhir file itu.
Ukuran key cipher juga bukan tingkat keamanan seluruh file. Payload key punya 256 bit, tapi age meng-generate file key dengan 128 bit. Passphrase yang lemah bisa menurunkan keamanan jauh lebih banyak.
Post waktu serangan membahas percobaan passphrase. Post berikutnya menunjukkan gimana public key dan secret key menggantikan passphrase bersama.

Memuat komentar...