Agentra LabsAgentra Labs DocsPublic Documentation

Get Started

File Format

Specification of the .aid identity file format

Version: 1 (aid-v1)

Overview

An .aid file stores an identity anchor's private key material encrypted at rest alongside the public identity document in plaintext. The file is JSON for human readability and tool compatibility. The encryption ensures that the private key cannot be recovered without the correct passphrase.

Structure

{
    "version": 1,
    "format": "aid-v1",
    "encryption": {
        "algorithm": "chacha20-poly1305",
        "kdf": "argon2id",
        "salt": "<base64-16-bytes>",
        "nonce": "<base64-12-bytes>"
    },
    "encrypted_anchor": "<base64-ciphertext>",
    "public_document": {
        "id": "aid_...",
        "public_key": "<base64-32-bytes>",
        "algorithm": "ed25519",
        "created_at": 1719840000000000,
        "name": "my-agent",
        "rotation_history": [],
        "attestations": [],
        "signature": "<base64-signature>"
    }
}

Fields

Top Level

FieldTypeDescription
versionu32Format version number. Currently 1.
formatstringFormat identifier. Must be "aid-v1".
encryptionobjectEncryption parameters needed for decryption.
encrypted_anchorstringBase64-encoded ciphertext of the encrypted private data.
public_documentobjectPublic identity document (no private key material).

encryption

FieldTypeDescription
algorithmstringSymmetric cipher. Must be "chacha20-poly1305".
kdfstringKey derivation function. Must be "argon2id".
saltstringBase64-encoded Argon2id salt (16 bytes).
noncestringBase64-encoded ChaCha20-Poly1305 nonce (12 bytes).

public_document

FieldTypeDescription
idstringIdentity ID (aid_ + base58 hash).
public_keystringBase64-encoded Ed25519 public key (32 bytes).
algorithmstringKey algorithm. Must be "ed25519".
created_atu64Creation timestamp in microseconds since Unix epoch.
namestring?Optional human-readable name.
rotation_historyarrayArray of PublicKeyRotation records.
attestationsarrayArray of Attestation records.
signaturestringBase64-encoded self-signature over the document payload.

PublicKeyRotation

FieldTypeDescription
previous_keystringBase64-encoded previous public key.
new_keystringBase64-encoded new public key.
rotated_atu64Rotation timestamp in microseconds.
reasonstringOne of: Scheduled, Compromised, DeviceLost, PolicyRequired, Manual.
authorization_signaturestringBase64-encoded signature of the old key authorizing the rotation.

Attestation

FieldTypeDescription
attesterstringAttester's identity ID.
attester_keystringAttester's public key (base64).
claimobjectAttestation claim (see below).
attested_atu64Attestation timestamp in microseconds.
signaturestringAttester's signature over the claim (base64).

Claim types: KeyOwnership, NameVerification { name }, OrganizationMembership { org }, Custom { claim_type, claim_value }.

Encryption Pipeline

The encryption pipeline transforms a passphrase into the symmetric key used to encrypt the private anchor data.

Save (Encryption)

passphrase (user input)
    |
    v
Argon2id(passphrase, salt)          salt = 16 random bytes
    |                               m_cost = 64 MiB
    |                               t_cost = 3 iterations
    v                               p_cost = 4 lanes
master_key (32 bytes)
    |
    v
HKDF-SHA256(master_key, "identity-encryption")
    |
    v
encryption_key (32 bytes)
    |
    v
ChaCha20-Poly1305(encryption_key, nonce, plaintext)
    |                               nonce = 12 random bytes
    v
ciphertext (variable length)
    |
    v
base64(ciphertext) -> encrypted_anchor field

Load (Decryption)

passphrase (user input) + salt (from file) + nonce (from file)
    |
    v
Argon2id(passphrase, salt)          same parameters as save
    |
    v
master_key (32 bytes)
    |
    v
HKDF-SHA256(master_key, "identity-encryption")
    |
    v
encryption_key (32 bytes)
    |
    v
ChaCha20-Poly1305_decrypt(encryption_key, nonce, ciphertext)
    |
    v
plaintext JSON -> AnchorPrivateData

If the passphrase is wrong, ChaCha20-Poly1305 authentication will fail and the error InvalidPassphrase is returned. The wrong key never produces valid plaintext.

Encrypted Private Data

The encrypted_anchor field, when decrypted, contains a JSON object with the following structure:

{
    "signing_key_b64": "<base64-32-bytes>",
    "created_at": 1719840000000000,
    "name": "my-agent",
    "rotation_history": [
        {
            "previous_key": "<base64>",
            "new_key": "<base64>",
            "rotated_at": 1719840100000000,
            "reason": "Scheduled",
            "authorization_signature": "<base64>"
        }
    ]
}
FieldTypeDescription
signing_key_b64stringBase64-encoded Ed25519 signing key (32 bytes).
created_atu64Creation timestamp (microseconds).
namestring?Optional identity name.
rotation_historyarrayFull rotation history including authorization signatures.

Security Properties

Key Zeroization

All intermediate key material is zeroized immediately after use:

  • The Argon2id master key is zeroized after HKDF expansion.
  • The HKDF-derived encryption key is zeroized after encrypt/decrypt.
  • The plaintext private data buffer is zeroized after deserialization.
  • The signing key bytes are zeroized after IdentityAnchor reconstruction.

Atomic Writes

File writes use a temporary sibling file (.aid.tmp) and rename() to prevent partial writes. A crash during write never leaves a corrupt .aid file visible to readers.

Tamper Detection

ChaCha20-Poly1305 is an AEAD cipher. If any byte of the ciphertext, nonce, or authentication tag is modified, decryption will fail with an authentication error. This prevents undetected tampering with the encrypted private key.

Passphrase Strength

Argon2id with 64 MiB memory cost, 3 iterations, and 4 parallel lanes provides strong resistance against:

  • GPU attacks -- high memory requirement makes GPU parallelism expensive.
  • ASIC attacks -- memory-hard design resists custom hardware.
  • Dictionary attacks -- each guess requires ~200-500 ms of computation.

Public Document Availability

The public identity document is intentionally stored in plaintext. This enables:

  • Identity inspection without the passphrase (read_public_document).
  • Signature verification by third parties.
  • Rotation history auditing.

No private key material is present in the public document.

Self-Signature

The public document includes a self-signature over the following payload (JSON-serialized):

{
    "id": "aid_...",
    "public_key": "<base64>",
    "algorithm": "ed25519",
    "created_at": 1719840000000000,
    "name": "my-agent"
}

The signature is an Ed25519 signature of this JSON string, encoded as base64. It proves that the document was created by the holder of the corresponding private key.

Version History

VersionFormatDescription
1aid-v1Initial release. ChaCha20-Poly1305 + Argon2id.