refactor(server::crypto): use fixed-size [u8; 32] and KeyCell throughout seal key API
Some checks failed
ci/woodpecker/pr/server-lint Pipeline failed
ci/woodpecker/pr/server-audit Pipeline was successful
ci/woodpecker/pr/server-vet Pipeline failed
ci/woodpecker/pr/server-test Pipeline was successful

This commit is contained in:
CleverWild
2026-06-12 21:15:07 +02:00
parent a3b98ca024
commit 0098c3c08a
12 changed files with 53 additions and 69 deletions

View File

@@ -162,13 +162,12 @@ impl Vault {
#[messages]
impl Vault {
#[message]
pub async fn bootstrap(&mut self, seal_key_raw: SafeCell<Vec<u8>>) -> Result<(), Error> {
pub async fn bootstrap(&mut self, mut seal_key: KeyCell) -> Result<(), Error> {
if !matches!(&self.state, State::Unbootstrapped) {
return Err(Error::AlreadyBootstrapped);
}
let mut root_key = KeyCell::new_secure_random();
let mut seal_key = KeyCell::try_from(seal_key_raw).map_err(|()| Error::InvalidKey)?;
// Zero nonces are fine because they are one-time
let root_key_nonce = Nonce::default();
@@ -227,7 +226,7 @@ impl Vault {
}
#[message]
pub async fn try_unseal(&mut self, seal_key_raw: SafeCell<Vec<u8>>) -> Result<(), Error> {
pub async fn try_unseal(&mut self, mut seal_key: KeyCell) -> Result<(), Error> {
let State::Sealed {
root_key_history_id,
} = &self.state
@@ -246,8 +245,6 @@ impl Vault {
.await?
};
let mut seal_key = KeyCell::try_from(seal_key_raw).map_err(|()| Error::InvalidKey)?;
let nonce =
Nonce::try_from(current_key.root_key_encryption_nonce.as_slice()).map_err(|()| {
error!("Broken database: invalid nonce for root key");
@@ -422,8 +419,7 @@ mod tests {
let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus())
.await
.unwrap();
let seal_key = SafeCell::new([0u8; 32].to_vec());
actor.bootstrap(seal_key).await.unwrap();
actor.bootstrap(KeyCell::from([0u8; 32])).await.unwrap();
actor
}

View File

@@ -9,7 +9,7 @@ use tracing::error;
use crate::{
actors::vault::{Bootstrap, TryUnseal, Vault},
crypto::{derive_key, encryption::v1::Nonce, shamir},
crypto::{KeyCell, derive_key, encryption::v1::Nonce, shamir},
db::{self, models, schema},
};
@@ -94,14 +94,14 @@ async fn finalize_bootstrap(
let threshold = shamir_threshold(total);
// Generate random 32-byte seal key
let mut seal_key_bytes = vec![0u8; 32];
let mut seal_key_bytes = [0u8; 32];
OsRng.fill_bytes(&mut seal_key_bytes);
// Split seal key into shares using Shamir (OsRng from rand_core 0.6, compatible with vsss-rs)
let shares = shamir::split_key(threshold, total, &seal_key_bytes, OsRng)
.map_err(|e| Error::Shamir(e.to_string()))?;
let seal_key = SafeCell::new(seal_key_bytes);
let seal_key = KeyCell::from(seal_key_bytes);
let mut conn = db.get().await?;
@@ -136,9 +136,7 @@ async fn finalize_bootstrap(
}
vault
.ask(Bootstrap {
seal_key_raw: seal_key,
})
.ask(Bootstrap { seal_key })
.await
.map_err(|err| {
error!(?err, "Vault bootstrap failed");
@@ -189,12 +187,10 @@ async fn finalize_unseal(
let seal_key_bytes =
shamir::combine_shares(&shares).map_err(|e| Error::Shamir(e.to_string()))?;
let seal_key = SafeCell::new(seal_key_bytes);
let seal_key = KeyCell::from(seal_key_bytes);
vault
.ask(TryUnseal {
seal_key_raw: seal_key,
})
.ask(TryUnseal { seal_key })
.await
.map_err(|err| {
error!(?err, "Vault unseal failed");