Skip to content

Latest commit

 

History

History
50 lines (40 loc) · 2.45 KB

FORMAT.md

File metadata and controls

50 lines (40 loc) · 2.45 KB

Vault G01 format

All sizes below are bytes. Integers use unsigned big-endian encoding.

Offset Size Meaning
0 8 ASCII VAULTG01: format and algorithm suite identifier
8 16 Random password-derivation salt and vault identity
24 12 Random AES-GCM nonce, regenerated on every write
36 8 Plaintext/ciphertext length, at most 67,108,864
44 length AES-256-GCM ciphertext
44 + length 16 GCM authentication tag

The entire 44-byte header is GCM additional authenticated data. Trailing bytes, truncation, unsupported identifiers, and inconsistent lengths are rejected. No padding, compression, optional fields, or host-endian structures are used.

Derive the 32-byte AES key using OpenSSL scrypt with the exact password bytes, the 16-byte salt, and N=131072, r=8, p=1. The implementation supplies a 256 MiB memory ceiling. Passwords are not normalized or NUL-terminated for derivation. These parameters are fixed by G01; changing them requires a new suite identifier.

Token T01 format

Offset Size Meaning
0 8 ASCII VAULTT01
8 16 Vault salt
24 32 Raw derived AES key

Tokens are exactly 56 bytes. They are unencrypted bearer credentials, not signatures or password hashes. Salt equality is an early binding check; successful GCM verification is the actual key-authentication check. Updates authenticate the existing ciphertext before writing and retain the salt/key while refreshing the nonce. There is no nonce in the token, allowing it to remain valid across updates.

Random 96-bit nonces have a birthday collision bound. Applications must not perform billions of writes under one key; recreate under a fresh salt/key well before that scale. Recreating also changes token identity. This format has no replay/rollback counter: an older authentic copy of a file remains authentic.

Independent regression fixture

test/fixture.h contains a deterministic file generated through Node.js's crypto API, independently of the C++ implementation. It uses password fixture password, salt bytes 00..0f, nonce bytes 10..1b, and plaintext 00 01 ff 00 2a 80. Reproduce it using crypto.scryptSync with the G01 parameters and a 256 MiB maxmem, then crypto.createCipheriv('aes-256-gcm', key, nonce) with the header passed to setAAD. Concatenate header, ciphertext, and getAuthTag(). The fixed salt and nonce are test-only values; production always generates them.