synology_apm_repo.sdk.dedup.keys module¶
Key material: parsing an administrator-provided key string, and resolving the wrapped VaultKey from whichever of the two on-disk locations this repository’s layout uses.
“Is this key correct” is answered by ``KeyMaterial.verify`` alone,
via AES-256-GCM’s own authentication tag — never by also decrypting a
real chunk. GCM tag success is already cryptographic proof the
(userKeyID, userKey) pair correctly unwraps the stored
wrapped-VaultKey record (FORMAT-SPEC.md: vaultkey-custody); given the repository-wide
invariant that the DEK (vaultKey) itself never changes
after first initialization (also vaultkey-custody), that same VaultKey is, by
construction, the one used for every real chunk this repository has —
not merely “probably” so. Per-chunk fingerprint verification (decrypting
a real chunk and comparing its SHA-256 against its stored .fgp) is a
separate, data-integrity concern this module has no part in — see
Pool.read_chunk’s own verify_fingerprint option for that.
- class synology_apm_repo.sdk.dedup.keys.KeyVerification(gcm_ok, vault_key)¶
Bases:
objectResult of
KeyMaterial.verify.vault_keyholds the resolved DEK only whengcm_okand encryption is actually in use; it’sNoneboth for an unencrypted repository and for a failed unwrap.
- class synology_apm_repo.sdk.dedup.keys.KeyMaterial(user_key_id, user_key)¶
Bases:
objectA parsed
"<userKeyID>@<base64(userKey)>"key string.user_key_id == "NoEncryption"(NO_ENCRYPTION_USER_KEY_ID) marks an unencrypted repository — no VaultKey exists to resolve.- classmethod from_key_string(key_string)¶
- async resolve_vault_key(store, layout)¶
Fetch this repository’s wrapped VaultKey (from whichever of the two on-disk locations
layout.kindimplies) and AES-256-GCM unwrap it.Returns
Noneif no wrapped key is on record at all (e.g. the lookup row/file is simply absent) — as distinct fromKeyMismatchError, which means a wrapped key was found but this(userKeyID, userKey)pair does not open it.
- async verify(store, layout)¶
The whole answer to “is this key correct” — no separate per-chunk check follows this. Never raises for an ordinary “wrong key” outcome — that is reported via the returned
KeyVerification, not an exception; the caller decides what a failed verification means for its flow (CLI/TUI report it,Repository.set_keymay choose to reject it). Touches only the wrapped-VaultKey record itself (one sqlite row or one small key file) — never the Pool.
- async synology_apm_repo.sdk.dedup.keys.probe_encrypted(store, layout)¶
Cheaply determine whether this repository is vault-encrypted by reading its own encryption-key record directly — VAULT layout reads
db/vault_encryption_key’s latest row, OBJECT_STORE layout reads the key-dir marker under<key_root>/userKey/. No bucket file opened, no Pool scan, no key required — the repository’s own encryption-key record is trusted as the single source of truth here, the same wayKeyMaterial.resolve_vault_keytrusts it to find one specific candidate key’s wrapped VaultKey, just reading the record’s latest entry instead of looking one up by id.VAULT layout:
db/vault_encryption_keyis an append-only key-rotation log, never updated in place. Its last-inserted row’suser_key_uuidis the currently-active key,"NoEncryption"iff this vault has never been encrypted (Encryption↔NoEncryption cannot toggle after first initialization — the DEK/vaultKeyitself never changes once set, per FORMAT-SPEC.md: vaultkey-custody).OBJECT_STORE layout: the equivalent record lives as individual objects named by
userKeyIDunder<key_root>/userKey/rather than db rows, with the same"NoEncryption"sentinel written at bucket-creation time for an unencrypted bucket.Returns
Noneonly if the record itself is entirely absent — should not happen for a properly initialized repository — as distinct from a confirmed-unencrypted repository (False).