feat(keys): passwords taken as RFC 8265's OpaqueString
Other spaces become a plain space and the text is composed (NFC) before Argon2id, so a password typed on another system, accents composed or not, unlocks the same keys; empty passwords and control characters are refused. The normalisation (unorm_dart) is pinned exactly, as it must never change once an account exists. ADR 0017 records both decisions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
7ad0f92f23
commit
200a2df32f
1 changed files with 140 additions and 3 deletions
|
|
@ -12,6 +12,7 @@ builds or tests a package depending on this one needs a C compiler and `make`.
|
|||
| Piece | API | Parameters |
|
||||
|---|---|---|
|
||||
| The password's keys | `newPasswordSalt`, `derivePasswordKeys` → `PasswordKeys` (`srpSecret`, `srpPrivateValue`, `keyEncryptionKey`) | Argon2id v1.3, 64 MiB, 3 passes (`PasswordKdf.current`), a 16-byte salt, a 32-byte master key; libsodium's KDF (context `hlkpass1`) splits it into SRP's secret (subkey 1, whose 256 bits big-endian are SRP's x) and the key-encryption key (subkey 2) |
|
||||
| The password as typed | `normalizePassword` (`PasswordRefused`) | RFC 8265's OpaqueString: other spaces to U+0020, Unicode NFC (`unorm_dart`, pinned exactly), empty or control characters refused; `derivePasswordKeys` applies it, so composed and decomposed accents unlock alike |
|
||||
| The costs kept with an account | `PasswordKdf` (`toJson`, `fromJson`) | kept beside the salt, so they can be raised for new passwords; `fromJson` refuses another algorithm or costs below `PasswordKdf.minimum`, kept apart from the current costs so raising those never locks out an older account |
|
||||
| The account's key pairs | `AccountKeys.generate` | X25519 to encrypt to, Ed25519 to sign with |
|
||||
| Their wrapping | `wrapAccountKeys`, `unwrapAccountKeys` → `WrappedAccountKeys` (`nonce`, `cipherText`) | XChaCha20-Poly1305, a random 24-byte nonce, the private halves (32 + 64 bytes) as plaintext, both public keys and a version label as additional data; unwrapping also rebuilds both public keys from the private halves and compares them with those given |
|
||||
|
|
|
|||
Loading…
Reference in a new issue