Fix Secret Key decode rejecting valid keys; verify build

The first base32 symbol carries 3 data bits (26 symbols = 130 bits, 2 spare),
but decode only accepted values 0-3, so ~half of generated keys failed to parse.
Adds an edge-case test, rustfmt config, Cargo.lock, and on-demand cross targets
instead of installing all seven in rust-toolchain.toml.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-15 21:14:15 +09:00
co-authored by Claude Opus 5.5
parent 462fbbc523
commit 4a152bde11
14 changed files with 1947 additions and 59 deletions
+26 -7
View File
@@ -74,7 +74,12 @@ impl AccountKeyset {
let mut pt = Zeroizing::new(Vec::with_capacity(48));
pt.extend_from_slice(vk.id.as_bytes());
pt.extend_from_slice(vk.expose());
seal_to(self.enc.id, &self.enc.public_bytes(), &pt, &Aad::build(ObjectType::VaultKey, self.account_id, Some(vault_id), None))
seal_to(
self.enc.id,
&self.enc.public_bytes(),
&pt,
&Aad::build(ObjectType::VaultKey, self.account_id, Some(vault_id), None),
)
}
pub fn open_vault_key(&self, vault_id: Uuid, env: &Envelope) -> Result<SymKey> {
@@ -100,26 +105,40 @@ pub struct SealedItem {
}
/// Encrypts an item's plaintext (already serialized) with a fresh per-item key.
pub fn seal_item(account_id: Uuid, vault_id: Uuid, item_id: Uuid, vault_key: &SymKey, plaintext: &[u8]) -> Result<SealedItem> {
pub fn seal_item(
account_id: Uuid,
vault_id: Uuid,
item_id: Uuid,
vault_key: &SymKey,
plaintext: &[u8],
) -> Result<SealedItem> {
let item_key = SymKey::generate();
let mut key_pt = Zeroizing::new(Vec::with_capacity(48));
key_pt.extend_from_slice(item_key.id.as_bytes());
key_pt.extend_from_slice(item_key.expose());
let wrapped_item_key =
vault_key.seal(&key_pt, &Aad::build(ObjectType::ItemKey, account_id, Some(vault_id), Some(item_id)))?;
let payload = item_key.seal(&pad(plaintext), &Aad::build(ObjectType::Item, account_id, Some(vault_id), Some(item_id)))?;
let payload =
item_key.seal(&pad(plaintext), &Aad::build(ObjectType::Item, account_id, Some(vault_id), Some(item_id)))?;
Ok(SealedItem { wrapped_item_key, payload })
}
pub fn open_item(account_id: Uuid, vault_id: Uuid, item_id: Uuid, vault_key: &SymKey, sealed: &SealedItem) -> Result<Zeroizing<Vec<u8>>> {
let key_pt =
vault_key.open(&sealed.wrapped_item_key, &Aad::build(ObjectType::ItemKey, account_id, Some(vault_id), Some(item_id)))?;
pub fn open_item(
account_id: Uuid,
vault_id: Uuid,
item_id: Uuid,
vault_key: &SymKey,
sealed: &SealedItem,
) -> Result<Zeroizing<Vec<u8>>> {
let key_pt = vault_key
.open(&sealed.wrapped_item_key, &Aad::build(ObjectType::ItemKey, account_id, Some(vault_id), Some(item_id)))?;
if key_pt.len() != 48 {
return Err(CryptoError::Malformed);
}
let id = Uuid::from_slice(&key_pt[..16]).map_err(|_| CryptoError::Malformed)?;
let item_key = SymKey::from_bytes(id, key_pt[16..].try_into().map_err(|_| CryptoError::Malformed)?);
let padded = item_key.open(&sealed.payload, &Aad::build(ObjectType::Item, account_id, Some(vault_id), Some(item_id)))?;
let padded =
item_key.open(&sealed.payload, &Aad::build(ObjectType::Item, account_id, Some(vault_id), Some(item_id)))?;
unpad(&padded)
}