跳转到内容

ak.schema.key_backup.v1

← Schemas

Arkret Encrypted Key Backup
ak.schema.key_backup.v1 · file: schemas/key-backup.schema.json
* $ · object
allOf · allOf[0] · ?
allOf · allOf[1] · ?
allOf · allOf[2] · ?
* backup_id · string
pattern: ^ak:backup:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
* actor_id · oneOf[2] · $ref ./common-ids.schema.json#/$defs/actor_id
Complete protocol identity for an Event author or Realm member: account carries the exact AccountId for every Station-hosted principal; service identifies a service acting as itself. The discriminator is validated against accepted registration and admission evidence; it never authorizes itself. Account and service are distinct, and no comparison may fall back to a bare principal_id. Agent and integration classification, provisioning, controller binding and credential authorization are independently verified facts, not identity variants. Account actors at different Stations MUST NOT share or inherit authority merely because their principal_id, DID controller or signing key matches, including membership, capability, RealmCommit-signing and recovery authority.
oneOf · oneOf[0] · object
* kind · const "account"
enum: "account"
* account_id · $ref #/$defs/account_id · $ref #/$defs/account_id
oneOf · oneOf[1] · object
* kind · const "service"
enum: "service"
* service_id · $ref #/$defs/did_core_id · $ref #/$defs/did_core_id
device_id · string
pattern: ^ak:device:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
* backup_kind · string (enum)
enum: "secret_storage"
mixed_secret_storage · boolean
True only for the personal_node exception where one encrypted backup envelope contains both identity-signing material and E2EE / MLS history material. Non-personal deployment profiles MUST reject this flag. When true and recipient_method=passphrase_kdf, the stricter Argon2id floor below applies.
example: false
* backup_version · string
pattern: ^kb_[A-Za-z0-9_-]+$
* series_id · string
Stable identifier for one immutable chain of backup envelopes belonging to a single (actor_id, backup_kind). A pair MAY have multiple series during compromise rotation or migration; active series selection is outside this envelope and MUST come from the signed active-series record in identity/key-management.md §7.6. Receivers use (actor_id, backup_kind, series_id) to detect server-side rollback / withholding within the selected series.
pattern: ^ak:backup_series:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
* series_seq · integer
0-based, strictly monotonically increasing sequence number within (actor_id, series_id). Genesis envelope of a series MUST set 0. Receivers MUST reject envelopes whose sequence does not strictly exceed the previously accepted sequence in the same series. This predecessor/CAS axis is independent of the optional source_commit_ref checkpoint.
supersedes_id · oneOf[2]
backup_id of the immediate predecessor in the same series_id. MUST be absent for series_seq=0; MUST be present, non-null, and reference an existing predecessor for series_seq>0.
oneOf · oneOf[0] · null
oneOf · oneOf[1] · string
pattern: ^ak:backup:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
supersedes_digest · string · $ref #/$defs/digest
Required when supersedes_id is non-null. Hash of the canonical_json of the predecessor envelope (excluding auth_data.signature). Receivers MUST recompute and reject mismatches as `series_chain_broken`.
pattern: ^(sha256|blake3):[0-9a-f]{64}$
source_commit_ref · object
The only canonical optional source checkpoint for genesis and successor authoring. Its exact wire and public builder shape is source_commit_ref{realm_commit_id: RealmCommitId, device_generation_ref: u64 >= 1}. Producers MUST authenticate this member under the envelope signature when present and MUST NOT accept or serialize source_ref, a nested/full CommittedEventRef, a string generation, Seal data, or a frontier digest. This checkpoint is independent of series_seq, supersedes_id, and supersedes_digest and never substitutes for the successor predecessor/CAS chain.
* realm_commit_id · string · $ref ./common-ids.schema.json#/$defs/realm_commit_id
Content-addressed identity of a closed unsigned RealmCommit body. The suffix uses the fixed v1 digest suite and the same canonical 33-octet token encoding as Event IDs.
pattern: ^ak:realm_commit:[A-Za-z0-9_-]{44}$
* device_generation_ref · integer · $ref ./recovery-session.schema.json#/$defs/pcr_generation_ref
PCR-local monotonic device generation. This is not a DID versionId and MUST equal the accepted current_device_generation_ref at the referenced checkpoint.
recovery_policy_ref · object
Required whenever encryption.recipient_method is recovery_public_key, and optional as a signed recovery-strand hint otherwise. Binds the backup envelope to the active recovery policy version under which it was produced. Receivers MUST compare this tuple to the currently accepted recovery policy before using such an envelope; mismatch fails as recovery_policy_mismatch, but the field does not replace active-series, checkpoint, Realm/MLS authorization, or device-state checks. This is intentionally separate from source_commit_ref: it binds the recovery authorization surface, not only the device trust generation or control-stream position.
* policy_id · string
pattern: ^ak:policy:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
* policy_version · integer
expires_at · oneOf[2] · $ref ./time.schema.json#/$defs/nullable_timestamp
oneOf · oneOf[0] · string (date-time) · format=date-time · $ref #/$defs/timestamp
Canonical Arkret-owned absolute instant. UTC Z form with exactly three millisecond digits. Whole seconds MUST use .000Z; offsets, missing/finer fractions, lowercase separators, leap seconds, and invalid Gregorian calendar dates are forbidden. Shape validation by this pattern is supplemented by semantic date validation.
pattern: ^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\.[0-9]{3}Z$
oneOf · oneOf[1] · null
* created_at · string (date-time) · format=date-time · $ref #/$defs/timestamp
Canonical Arkret-owned absolute instant. UTC Z form with exactly three millisecond digits. Whole seconds MUST use .000Z; offsets, missing/finer fractions, lowercase separators, leap seconds, and invalid Gregorian calendar dates are forbidden. Shape validation by this pattern is supplemented by semantic date validation.
pattern: ^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\.[0-9]{3}Z$
updated_at · string (date-time) · format=date-time · $ref #/$defs/timestamp
Canonical Arkret-owned absolute instant. UTC Z form with exactly three millisecond digits. Whole seconds MUST use .000Z; offsets, missing/finer fractions, lowercase separators, leap seconds, and invalid Gregorian calendar dates are forbidden. Shape validation by this pattern is supplemented by semantic date validation.
pattern: ^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\.[0-9]{3}Z$
* encryption · object
allOf · allOf[0] · ?
allOf · allOf[1] · ?
allOf · allOf[2] · ?
* recipient_method · string (enum)
enum: "passphrase_kdf" "recovery_public_key" "secret_storage_key"
recipient_key_ref · string
For recipient_method=recovery_public_key, this MUST resolve to the inline backup_hpke.key_agreement_ref of a non-revoked method signing entry in the envelope's referenced accepted recovery policy, and the selected hpke_suite MUST appear in that entry's hpke_suites. DID Document-only key agreements are not an authorization source. A method signing entry's verification_method is a signing-key ref and MUST be rejected here.
hpke_suite · string (enum)
Registered active HPKE suite (KEM x KDF x AEAD per RFC 9180) selector; the value space is the active rows of artifacts/registry/hpke-suite-registry.json. Applies only to recipient_method=recovery_public_key. When absent it denotes the default-MUST row ak.hpke_x25519_aead_chacha20poly1305.v1. aead.name MUST equal the selected suite's AEAD. An unregistered or inactive suite MUST be rejected (unsupported_hpke_suite). Absent / ignored for the symmetric methods (passphrase_kdf / secret_storage_key).
enum: "ak.hpke_x25519_aead_chacha20poly1305.v1" "ak.hpke_x25519_aead_aes256gcm.v1" "ak.hpke_p256_aead_aes256gcm.v1"
kdf · object
allOf · allOf[0] · ?
allOf · allOf[1] · ?
* name · string (enum)
enum: "argon2id" "pbkdf2"
* salt · string
Canonical unpadded base64url of exactly 16 KDF salt bytes; decoders MUST check the decoded length and canonical re-encoding.
pattern: ^[A-Za-z0-9_-]{22}$
params · object
memory_kib · integer
iterations · integer
parallelism · integer
digest_algorithm · string (enum)
enum: "sha256" "sha384" "sha512"
(^x_[a-z][a-z0-9_]{0,63}$) · any
degraded_profile_reason · string
(^x_[a-z][a-z0-9_]{0,63}$) · any
* aead · object
* name · string (enum)
enum: "xchacha20_poly1305" "aes_256_gcm" "chacha20_poly1305"
aead_profile · string
Optional AEAD profile id that binds algorithm version, nonce length, tag length, key length, and AAD construction. Receivers that do not support the profile MUST fail closed instead of inferring semantics from name alone.
pattern: ^ak\.aead\.[a-z0-9_]+\.v[0-9]+$
nonce · string
base64url AEAD nonce. Required for the symmetric methods (passphrase_kdf / secret_storage_key). For passphrase_kdf this is HMAC-SHA256(nonce_key, the exact §7.5.1 JCS nonce transcript)[0:24]; an absent aead_profile uses the effective XChaCha20-Poly1305 v1 profile in that transcript. Receivers recompute and reject mismatches. Absent for recovery_public_key (HPKE derives its nonce internally).
pattern: ^[A-Za-z0-9_-]+$
nonce_salt · string
Producer-generated base64url random salt (at least 128 bits before encoding) included in the passphrase_kdf nonce derivation transcript. Required when recipient_method=passphrase_kdf; not secret, signed as envelope metadata, and prevents nonce reuse from duplicate business metadata tuples.
pattern: ^[A-Za-z0-9_-]{16,128}$
enc · string
base64url HPKE KEM encapsulated key. Required for recipient_method=recovery_public_key; the KEM/KDF/AEAD are pinned by encryption.hpke_suite (default ak.hpke_x25519_aead_chacha20poly1305.v1) per artifacts/registry/hpke-suite-registry.json. Absent for the symmetric methods.
pattern: ^[A-Za-z0-9_-]+$
(^x_[a-z][a-z0-9_]{0,63}$) · any
key_commitment · string
pattern: ^(sha256|blake3):[0-9a-f]{64}$
(^x_[a-z][a-z0-9_]{0,63}$) · any
* domain_separation · object
Signed key-backup domain separation inputs. The HKDF info and fixed AEAD/HPKE AAD base are derived exactly from the envelope by key-management.md §7.2; only the subdomain and genuine x_* AAD extensions are carried on the wire.
* subdomain · string
pattern: ^[a-z][a-z0-9_]{0,63}$
aead_aad_extensions · object
Optional producer-chosen AEAD/HPKE AAD extensions. Every member name MUST be x_*; implementations merge these members into the fixed derived AAD base before RFC 8785 canonicalization and MUST reject collisions.
(^x_[a-z][a-z0-9_]{0,63}$) · any
* contents · array<object>
Signed, nonempty public index of every encrypted plaintext item. Each entry is matched by item_kind and secret_id after decryption; item_kinds for the §7.2 AEAD AAD are derived only from this closed index.
items · object
* item_kind · string (enum) · $ref ./key-backup-plaintext.schema.json#/$defs/secret_storage_item/properties/item_kind
enum: "recovery_key_share" "account_data_namespace_key" "mls_account_secret" "mls_private_plaintext" "mls_group_secrets_backup_key" "private_account_state"
* secret_id · string
pattern: ^[A-Za-z0-9_.-]+$
* ciphertext · string
pattern: ^[A-Za-z0-9_-]+$
* ciphertext_digest · string
pattern: ^(sha256|blake3):[0-9a-f]{64}$
plaintext_commitment · string
pattern: ^(sha256|blake3):[0-9a-f]{64}$
* auth_data · object
* device_id · string
pattern: ^ak:device:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
* verification_method · string · $ref ./common-ids.schema.json#/$defs/did_url
Arkret verification-method DID URL profile (identity/did-usage-and-verification.md section 2.2): lowercase method name, no query, required fragment, fragment limited to ASCII [A-Za-z0-9._:-]. Every verification_method-family field and every kid/key_ref a schema declares to be a DID URL MUST resolve to exactly this definition; values compare byte-for-byte with no URI normalization or percent-decoding.
pattern: ^did:[a-z0-9]+:[^\s#?]+#[A-Za-z0-9._:-]+$
* signature_algorithm · string (enum)
Current-v1 raw signature algorithm name. Reserved ML-DSA-65 is not admitted until a future negotiated schema/profile activation.
enum: "Ed25519"
* signature · string
base64url-encoded signature over RFC 8785 JCS(envelope without auth_data.signature). Every present closed envelope member, including optional and x_* members, is authenticated; no wire field list selects the projection.
pattern: ^[A-Za-z0-9_-]+$
* device_authorize_event_id · string
Accepted current-generation ak.device.authorize Event anchoring the device signing this backup.
pattern: ^ak:event:[A-Za-z0-9_-]{44}$
(^x_[a-z][a-z0-9_]{0,63}$) · any
retention · object
delete_after · oneOf[2] · $ref ./time.schema.json#/$defs/nullable_timestamp
oneOf · oneOf[0] · string (date-time) · format=date-time · $ref #/$defs/timestamp
Canonical Arkret-owned absolute instant. UTC Z form with exactly three millisecond digits. Whole seconds MUST use .000Z; offsets, missing/finer fractions, lowercase separators, leap seconds, and invalid Gregorian calendar dates are forbidden. Shape validation by this pattern is supplemented by semantic date validation.
pattern: ^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\.[0-9]{3}Z$
oneOf · oneOf[1] · null
legal_hold · boolean
(^x_[a-z][a-z0-9_]{0,63}$) · any

Source