aWallet Next keeps your whole vault in one encrypted file, data.crypt2. The same file is used on iPhone, iPad and Android, and it is the file that cloud sync stores in your iCloud Drive, Dropbox, Google Drive or WebDAV. This page describes it precisely enough to open your vault with your own program, so your data is never locked in.
Everything below happens on your device. Your master password and the keys derived from it never leave it.
Encrypted on your device. The file is encrypted with keys derived from your master password. Your cloud provider, and we, only ever see encrypted data.
Tampering is detected. Every part is protected by authenticated encryption: a wrong password or a changed byte is refused, never silently decrypted into garbage.
One file, both platforms. iOS and Android use the same cryptography (libsodium) and the same byte layout.
Ready for the future. The header names its algorithms. A newer algorithm gets a new identifier, and an older app refuses such a file with "created by a newer version" instead of guessing.
Argon2id key derivation (parallelism 1, 256-bit key). New vaults use 3 passes and 64 MiB of memory; the values are stored in each file, so they can be raised later without breaking older files.
XChaCha20-Poly1305 authenticated encryption (IETF variant) with a fresh random 24-byte nonce for every seal and a 16-byte authentication tag.
Both come from libsodium: crypto_pwhash with ALG_ARGON2ID13, and crypto_aead_xchacha20poly1305_ietf_encrypt / _decrypt.
All integers are big-endian.
magic (offset 0, 4 bytes): the bytes 41 57 43 32 = "AWC2"
version (offset 4, 2 bytes): 1
kdfId (offset 6, 1 byte): 1 = Argon2id
aeadId (offset 7, 1 byte): 1 = XChaCha20-Poly1305
kdfParam1 (offset 8, 4 bytes): Argon2id passes (new vaults: 3)
kdfParam2 (offset 12, 4 bytes): Argon2id memory in bytes (new vaults: 67,108,864 = 64 MiB)
salt (offset 16, 16 bytes): random Argon2id salt
wrappedDEK (offset 32, 4 + 72 bytes): 4-byte length, then nonce (24) ‖ encrypted data key (32) ‖ tag (16)
recoveryWrappedDEK (right after the previous field, 4 + n bytes): 4-byte length, then the same shape; length 0 when no Recovery Key is set
payload (right after the previous field, the rest): nonce (24) ‖ encrypted vault ‖ tag (16)
Password key. Argon2id of your master password with the file's salt, passes and memory. Deliberately slow and memory-hard, so guessing passwords against a stolen file is expensive.
Data key. 32 random bytes created once with the vault. It encrypts the vault and is stored only in wrapped (encrypted) form, sealed under the password key in wrappedDEK.
Recovery Key (optional). 32 random bytes shown to you once. It wraps the same data key in recoveryWrappedDEK, so it opens the vault without the master password.
The data key never changes for the life of a vault. Changing your master password only re-wraps the data key, so it is instant and the vault itself is not re-encrypted. A normal save re-encrypts only the payload, with a fresh nonce.
The three seals in the file (wrappedDEK, recoveryWrappedDEK and the payload) all authenticate the same 8 bytes as associated data: magic (4) ‖ version (2, big-endian) ‖ kdfId (1) ‖ aeadId (1). A file therefore cannot be reinterpreted under a different scheme by editing its header.
Check that the file starts with "AWC2", and that version, kdfId and aeadId are values you know. If not, stop.
Read the Argon2id passes, memory and salt, and derive the 32-byte password key from the master password.
Decrypt wrappedDEK with the password key and the 8 bytes of associated data. If it fails, the password is wrong (or the file was changed). The result is the 32-byte data key.
Decrypt the payload with the data key and the same associated data.
The result is the vault, compressed with xz (LZMA2, standard .xz container). Decompress it and you have the vault's contents as JSON text.
With a Recovery Key instead of the master password, step 3 decrypts recoveryWrappedDEK with the Recovery Key.
The 256-bit Recovery Key is shown in Crockford Base32 (no I, L, O or U), in groups of four characters. On entry it is case-insensitive and tolerant of look-alike characters. It can also be split into N Recovery Shares, any K of which rebuild it (Shamir secret sharing over GF(2⁸) with the AES polynomial 0x11b; a share is x ‖ y₁…y₃₂, interpolated at 0). A single Recovery Key is the case K = 1.
Photos, documents and videos are not inside data.crypt2. Each is a separate encrypted file with its own random key; those keys are stored in the vault, so the attachments open only together with it.