Commit Graph
10 Commits
Author SHA1 Message Date
nvrl fe42f6c972 fix(account): open address tokens with inactive account keys, skip a broken address
An address key's token was decrypted with the active account keys only.
A token encrypted to an account key that is now inactive never opened,
although that key still opens with the password, so the address failed
with "has no primary key". proton-drive-linux issue #40 shows this as a
mount that retries "missing key" forever. Tokens are now tried with
every account key that opens, active ones first; signing still uses
active keys only. The key report walks the same chain.

addresses() also failed as a whole when one address did not open. That
address is now left out with a warning and the rest work; the call fails
only when none opens. address_private_keys and the new address(id) name
the reason for a left-out address, and default_address fails with it
when the left-out address is the default rather than signing with
another one.
2026-10-31 13:07:09 +01:00
nvrl bd27f7862b feat(account,drive): report which keys open and which key each token is for
AccountClient::key_report walks the user and address keys like the
unlock path, but records each step instead of skipping what fails:
whether each user key opens (inactive ones included), and the
recipients of each address key token. ProtonDriveClient::
my_files_share_recipients names the keys the My Files share passphrase
is encrypted to without decrypting anything. Together they trace a
"missing key" to the key it was meant for (proton-drive-linux#40).

crypto::recipients and crypto::key_ids read OpenPGP identifiers from
messages and keys, so a recipient can be matched to a key.
2026-10-17 12:13:27 +02:00
nvrl 325c326c49 feat(account): hold key passphrases as wiped secrets and report a locked account as KeysLocked
A wrong mailbox password surfaced as InvalidOperation("no active user key could
be unlocked"), which a caller could only recognise by its text. It is now
ProtonError::KeysLocked, and AccountClient::unlock() checks a secret with a
single core/v4/users request instead of loading every address.

Derived passphrases, the mailbox password and the cache encryption key were
plain Vec<u8>s, cloned freely and never wiped. They are Zeroizing now, and the
passphrase map is KeyPassphrases: wiped on drop, redacted in Debug, with
derive_secret() for a client that wants a key only an unlocked account can
reproduce. with_key_passphrases takes it.

Breaking: ProtonError gains a variant, key_passphrases() and
with_key_passphrases() change type, and derive_key_passphrase returns
Zeroizing<Vec<u8>>.
2026-10-07 02:24:51 +02:00
nvrl 6eb8b206a7 feat(account,session): resume from derived key passphrases and report second-factor methods
`AccountClient::key_passphrases` is now public, and
`AccountClient::with_key_passphrases` / `ProtonDriveClient::with_key_passphrases`
build a client from the per-key passphrases alone. A client that persists a
session can store those instead of the mailbox password, which on a
single-password account is the login password itself.

`ProtonApiSession::second_factor_methods` exposes the login's 2FA bitmask
(TOTP, FIDO2), so a client without WebAuthn can tell an account that only has
a security key apart from a wrong code.
2026-10-06 13:59:10 +02:00
nvrl 64f977edb3 feature (devices+sharing) + upgraded rand and aeds 2026-07-15 19:34:40 +02:00
nvrl a24785d1a9 added persistent key salts 2026-07-13 10:26:12 +02:00
nvrl e2f5ab7ad6 fmt + Clippy 2026-06-26 20:47:06 +02:00
nvrl 8eb7b8f56f implemented missing drive endpoints 2026-06-26 16:01:35 +02:00
nvrl fdfab3df3f feat(sdk/account): support resolving public keys for authorship verification 2026-06-25 15:54:03 +02:00
nvrl 808a96cdd1 init 2026-06-25 09:42:34 +02:00