User Wallet Data Format Encryption Extension
Ty Everett ([email protected])
Abstract
This specification defines the canonical encrypted wrapper for BRC-38 user wallet data exports.
It standardizes a downloadable binary file format, conventionally named wallet.brc39, for password-protected wallet export and import. The design is intended for strong user data portability, backups, archival export, GDPR-style data access, and migration between wallet implementations and storage providers.
BRC-39 uses:
the BRC-38 payload as its canonical plaintext inner document
the AES-256-GCM symmetric encryption primitive used by BRC-2
a portable, versioned binary envelope in the spirit of BRC-78
Argon2id as the mandatory password key-derivation function for new exports
Motivation
BRC-38 defines what wallet data must be portable. It does not define how that data should be safely delivered to a user as a single downloadable file.
For real-world portability, the default export artifact must be:
encrypted
password protected
self-describing
suitable for offline storage
stable enough to move between implementations
This document defines that artifact.
Specification
1. Scope
This specification defines:
the canonical encrypted file format for a single-user BRC-38 export
password normalization rules
key derivation rules
authenticated encryption rules
file parsing, validation, export, and import behavior
It does not define:
secret-sharing or recovery-key workflows
multi-file backup sets
multi-user containers
wallet-runtime key snapshots unrelated to BRC-38
2. Conformance
An implementation conforms to BRC-39 if it can:
serialize a valid BRC-38 payload
encrypt that payload into a valid BRC-39 file
decrypt and validate a valid BRC-39 file
recover the original BRC-38 payload without loss
3. Canonical Export Artifact
The canonical encrypted export artifact:
MUST be a binary file
SHOULD be named
wallet.brc39SHOULD use media type
application/vnd.brc39.wallet
The inner plaintext payload MUST be a complete BRC-38 document serialized as canonical UTF-8 JSON.
4. Cryptographic Profile
4.1 Plaintext
The plaintext to be encrypted is:
the exact UTF-8 byte sequence of a valid canonical BRC-38 JSON document
4.2 Password Encoding
Before key derivation, the user password MUST be:
interpreted as a Unicode string
normalized to NFC
encoded as UTF-8 bytes
No additional trimming, case folding, or whitespace normalization is permitted.
4.3 Key Derivation
New BRC-39 exports MUST use Argon2id.
The canonical derived-key length is:
32 bytes
The canonical default Argon2id parameters are:
iterations:
7memoryKiB:
131072parallelism:
1hashLength:
32saltLength:
32
These defaults align with the Wallet Toolbox Argon2id defaults this specification is intended to standardize.
Implementations MAY use stronger Argon2id parameters, but they MUST encode the exact parameters used in the file header.
4.4 Authenticated Encryption
The content-encryption algorithm is AES-256-GCM.
The content-encryption key is the 32-byte Argon2id-derived key.
The file nonce length is:
32 bytes
The nonce MUST be generated randomly for each export.
The GCM authentication tag length MUST be 16 bytes.
4.5 Header Validation
Header fields are validated before decryption as specified below. BRC-39 encrypts only the BRC-38 plaintext payload.
5. File Layout
All integers in the binary file MUST be unsigned and encoded in big-endian byte order.
The canonical BRC-39 file layout is:
Magic
4 bytes
ASCII WDAT
Format Version
1 byte
Currently 0x01
Protector Type
1 byte
Currently 0x01 for password-protected export
Inner Format
1 byte
Currently 0x26 (decimal 38) for BRC-38
KDF Type
1 byte
Currently 0x01 = Argon2id
Flags
1 byte
Currently 0x00; all bits reserved and MUST be zero
Salt Length
1 byte
Currently 0x20 (32)
Nonce Length
1 byte
Currently 0x20 (32)
Argon2id Iterations
4 bytes
Work factor
Argon2id Memory KiB
4 bytes
Memory cost
Argon2id Parallelism
1 byte
Parallelism
Argon2id Hash Length
1 byte
Derived key length; currently 32
Reserved
12 bytes
MUST be all zero
Salt
variable
Salt Length bytes
Nonce
variable
Nonce Length bytes
CiphertextAndTag
variable
AES-256-GCM ciphertext followed by 16-byte tag
6. Header Field Requirements
6.1 Magic
The file MUST begin with the ASCII bytes:
which spell WDAT.
6.2 Format Version
The current format version is 1.
Files with unsupported versions MUST be rejected.
6.3 Protector Type
The following protector types are defined:
0x01: password-based encryption
The following values are reserved for future extension:
0x02to0xff
This version of BRC-39 standardizes only password-based encryption.
6.4 Inner Format
The Inner Format field identifies the plaintext payload.
For BRC-39 wallet exports:
Inner FormatMUST be38
Meaning the decrypted plaintext MUST be a valid BRC-38 document.
6.5 KDF Type
The following KDF type is defined:
0x01: Argon2id
All other KDF type values are reserved for future specifications. This version of BRC-39 defines no alternate KDF import mode.
6.6 Flags
All flag bits are reserved for future specifications.
For this specification:
FlagsMUST be0x00
6.7 Reserved Bytes
All reserved bytes MUST be zero on export and MUST be ignored only if zero on import. Non-zero reserved bytes MUST cause rejection.
7. Export Procedure
To create a BRC-39 file, an exporter MUST:
construct a valid BRC-38 document
serialize it as canonical UTF-8 JSON
normalize the user password to NFC and encode it as UTF-8
generate a random 32-byte salt
derive a 32-byte key using Argon2id and the encoded password
generate a random 32-byte nonce
construct the BRC-39 header
encrypt the BRC-38 plaintext using AES-256-GCM with:
key = derived key
nonce = header nonce
append
CiphertextAndTagemit the resulting bytes as
wallet.brc39
8. Import Procedure
To import a BRC-39 file, an importer MUST:
parse and validate the binary header
verify
Magic,Format Version,Protector Type,Inner Format,KDF Type,Flags, and reserved bytesobtain the user password
normalize the password to NFC and encode it as UTF-8
derive the decryption key using the encoded KDF parameters from the file
decrypt
CiphertextAndTagwith AES-256-GCM using:key = derived key
nonce = header nonce
reject the file if GCM authentication fails
parse the plaintext as UTF-8 JSON
validate that the plaintext is a valid BRC-38 document
Only after successful BRC-38 validation may the importer proceed to import wallet data into local storage.
9. KDF Compatibility
BRC-39 standardizes only Argon2id for password-based wallet export encryption.
Implementations MUST reject files whose KDF Type is not 0x01. Compatibility with pre-standard password-derived wallet internals is outside the BRC-39 file format.
10. Relationship to BRC-2 and BRC-78
10.1 BRC-2
BRC-39 uses the same symmetric encryption primitive family as BRC-2:
AES-256-GCM
Unlike BRC-2 application messages, BRC-39 stores the nonce explicitly in the binary file header instead of prepending it to a message payload.
10.2 BRC-78
BRC-39 follows the same general design philosophy as BRC-78:
binary, versioned, self-describing encrypted envelopes
BRC-78 is oriented toward portable encrypted inter-party messages using BRC-2/BRC-42/BRC-43 derivation. BRC-39 instead targets password-protected at-rest wallet export. This version does not standardize recipient-encrypted wallet exports, but future protector types MAY define such a mode.
11. Validation Rules
A BRC-39 file MUST be rejected if:
Magicis notWDATFormat Versionis unsupportedProtector Typeis unsupportedInner Formatis not38KDF Typeis not0x01Flagsis not0x00Salt Lengthis zeroNonce Lengthis zeroreserved bytes are non-zero
any Argon2id parameter is invalid, including:
iterations is zero
memoryKiB is zero
parallelism is zero
hashLength is not
32
AES-GCM authentication fails
the decrypted payload is not valid UTF-8 JSON
the decrypted payload is not a valid BRC-38 document
12. Privacy and Operational Requirements
BRC-39 files contain the complete user wallet export, protected only by the chosen password and KDF parameters.
Wallet implementations:
MUST warn users that weak passwords materially weaken the file
SHOULD encourage long passwords or passphrases
SHOULD avoid embedding password hints in the file
SHOULD default to Argon2id parameters at least as strong as the canonical defaults
13. Canonical Example Header Semantics
An example canonical new-export header therefore means:
file type:
wallet.brc39payload type: BRC-38
protection mode: password
KDF: Argon2id
salt: 32 random bytes
nonce: 32 random bytes
plaintext: canonical UTF-8 BRC-38 JSON
Implementation
An implementation based on Wallet Toolbox can produce a BRC-39 file by:
exporting a full BRC-38 payload for the selected user
deriving a password key with Argon2id using the standardized Toolbox-compatible default parameters
encrypting the payload with AES-256-GCM
writing the standardized binary envelope described above
References
Last updated
Was this helpful?

