Support existing upstream-compatible password stores whose GPG entries use the GnuPG AEAD packet type 20 format.
Root cause
The affected entries correctly target encryption subkey 4D463BF6BA4D8A9C under primary key 3B98…5429, so key selection is not the failure. The real store's 547 entries use AES-256/OCB GnuPG AEAD packets (tag 20), while IronStorage's current compatibility fixtures and documented profile cover only SEIPD/MDC packet type 18. pgp 0.20 requires GnuPG AEAD support to be explicitly enabled, but crates/storage/src/crypto.rs currently uses default Message::decrypt behavior and rejects tag 20. The resulting decrypt error also causes a correctly prompted passphrase to be discarded rather than persisted.
Scope
Enable GnuPG AEAD decryption through crates/storage without weakening existing packet validation.
Add a checked-in type-20 compatibility fixture produced in the upstream password-store format, including its public/protected secret key material.
Prove the fixture decrypts with the matching encryption subkey and correct passphrase.
Preserve typed failures for wrong passphrases, corrupt AEAD data, missing keys, and unsupported packet modes.
Update cryptography compatibility documentation to describe both accepted formats.
Do not rewrite or re-encrypt existing password stores as a workaround.
Acceptance criteria
A real packet-tag-20 AES-256/OCB fixture decrypts through the normal crates/storage entry path.
Existing packet-tag-18/MDC fixtures and encryption behavior remain compatible.
Tampering and wrong-passphrase tests fail safely without persisting rejected credentials.
No CLI or application layer parses OpenPGP packets or owns this compatibility rule.
All repository gates pass.
## Objective
Support existing upstream-compatible password stores whose GPG entries use the GnuPG AEAD packet type 20 format.
## Root cause
The affected entries correctly target encryption subkey 4D463BF6BA4D8A9C under primary key 3B98…5429, so key selection is not the failure. The real store's 547 entries use AES-256/OCB GnuPG AEAD packets (tag 20), while IronStorage's current compatibility fixtures and documented profile cover only SEIPD/MDC packet type 18. pgp 0.20 requires GnuPG AEAD support to be explicitly enabled, but crates/storage/src/crypto.rs currently uses default Message::decrypt behavior and rejects tag 20. The resulting decrypt error also causes a correctly prompted passphrase to be discarded rather than persisted.
## Scope
- Enable GnuPG AEAD decryption through crates/storage without weakening existing packet validation.
- Add a checked-in type-20 compatibility fixture produced in the upstream password-store format, including its public/protected secret key material.
- Prove the fixture decrypts with the matching encryption subkey and correct passphrase.
- Preserve typed failures for wrong passphrases, corrupt AEAD data, missing keys, and unsupported packet modes.
- Update cryptography compatibility documentation to describe both accepted formats.
- Do not rewrite or re-encrypt existing password stores as a workaround.
## Acceptance criteria
- A real packet-tag-20 AES-256/OCB fixture decrypts through the normal crates/storage entry path.
- Existing packet-tag-18/MDC fixtures and encryption behavior remain compatible.
- Tampering and wrong-passphrase tests fail safely without persisting rejected credentials.
- No CLI or application layer parses OpenPGP packets or owns this compatibility rule.
- All repository gates pass.
hugo
added this to the 02 - Mutt-style terminal UI milestone 2026-08-10 08:12:50 +00:00
hugo
added the bug label 2026-08-10 08:12:50 +00:00
Storage now opts into pgp 0.20 GnuPG AEAD decryption through DecryptionOptions while keeping legacy unauthenticated packets disabled and preserving IronStorage encryption as packet type 18 SEIPDv1/MDC.
Compatibility evidence:
Added a genuine GnuPG 2.4.8-produced packet type 20 AES-256/OCB password-store fixture addressed to the synthetic Alice encryption subkey, with a protected secret key, expected plaintext, producer profile, and SHA-256 provenance.
Decrypted it through Repository and VaultReader, not a test-only packet shortcut.
Verified exact encryption-subkey matching, correct passphrase acceptance, wrong-passphrase rejection, corrupt AEAD authentication failure, missing-key handling, unsupported AEAD-mode rejection, and no persistence of rejected prompted passphrases.
Added an explicit regression assertion that IronStorage output remains packet type 18 SEIPDv1.
The upstream audit was also documented: pass 1.7.4 delegates gpg file reads/writes to GnuPG; current Homebrew pass depends on GnuPG 2.5.21; GnuPG chooses CFB+MDC or packet-20 OCB from recipient preferences. Default GnuPG rejects missing-MDC legacy data, so IronStorage keeps that unsafe mode disabled.
Implemented in commit 977eb23 and pushed to main.
Storage now opts into pgp 0.20 GnuPG AEAD decryption through DecryptionOptions while keeping legacy unauthenticated packets disabled and preserving IronStorage encryption as packet type 18 SEIPDv1/MDC.
Compatibility evidence:
- Added a genuine GnuPG 2.4.8-produced packet type 20 AES-256/OCB password-store fixture addressed to the synthetic Alice encryption subkey, with a protected secret key, expected plaintext, producer profile, and SHA-256 provenance.
- Decrypted it through Repository and VaultReader, not a test-only packet shortcut.
- Verified exact encryption-subkey matching, correct passphrase acceptance, wrong-passphrase rejection, corrupt AEAD authentication failure, missing-key handling, unsupported AEAD-mode rejection, and no persistence of rejected prompted passphrases.
- Added an explicit regression assertion that IronStorage output remains packet type 18 SEIPDv1.
The upstream audit was also documented: pass 1.7.4 delegates gpg file reads/writes to GnuPG; current Homebrew pass depends on GnuPG 2.5.21; GnuPG chooses CFB+MDC or packet-20 OCB from recipient preferences. Default GnuPG rejects missing-MDC legacy data, so IronStorage keeps that unsafe mode disabled.
Verification passed:
- cargo fmt --all -- --check
- RUSTFLAGS=-D warnings cargo check --workspace --all-targets
- cargo clippy --workspace --all-targets -- -D warnings
- cargo test --workspace
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Objective
Support existing upstream-compatible password stores whose GPG entries use the GnuPG AEAD packet type 20 format.
Root cause
The affected entries correctly target encryption subkey 4D463BF6BA4D8A9C under primary key 3B98…5429, so key selection is not the failure. The real store's 547 entries use AES-256/OCB GnuPG AEAD packets (tag 20), while IronStorage's current compatibility fixtures and documented profile cover only SEIPD/MDC packet type 18. pgp 0.20 requires GnuPG AEAD support to be explicitly enabled, but crates/storage/src/crypto.rs currently uses default Message::decrypt behavior and rejects tag 20. The resulting decrypt error also causes a correctly prompted passphrase to be discarded rather than persisted.
Scope
Acceptance criteria
Implemented in commit
977eb23and pushed to main.Storage now opts into pgp 0.20 GnuPG AEAD decryption through DecryptionOptions while keeping legacy unauthenticated packets disabled and preserving IronStorage encryption as packet type 18 SEIPDv1/MDC.
Compatibility evidence:
The upstream audit was also documented: pass 1.7.4 delegates gpg file reads/writes to GnuPG; current Homebrew pass depends on GnuPG 2.5.21; GnuPG chooses CFB+MDC or packet-20 OCB from recipient preferences. Default GnuPG rejects missing-MDC legacy data, so IronStorage keeps that unsafe mode disabled.
Verification passed: