mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-05-12 02:59:29 +00:00
refactor: make SealingPublicKey a newtype wrapper
This commit is contained in:
parent
6e376900f7
commit
27e2850b5c
@ -102,7 +102,7 @@ async fn group_invite_join_key_agreement() -> Result<()> {
|
||||
.sealing_secret_key
|
||||
.context("Sealing key not found")?;
|
||||
let sealing_pk =
|
||||
nssa_core::encryption::shared_key_derivation::Secp256k1Point::from_scalar(sealing_sk);
|
||||
key_protocol::key_management::group_key_holder::SealingPublicKey::from_scalar(sealing_sk);
|
||||
|
||||
let holder = ctx
|
||||
.wallet()
|
||||
|
||||
@ -12,10 +12,30 @@ use super::secret_holders::{PrivateKeyHolder, SecretSpendingKey};
|
||||
|
||||
/// Public key used to seal a `GroupKeyHolder` for distribution to a recipient.
|
||||
///
|
||||
/// Structurally identical to `ViewingPublicKey` (both are secp256k1 points), but given
|
||||
/// a distinct alias to clarify intent: viewing keys encrypt account state, sealing keys
|
||||
/// encrypt the GMS for off-chain distribution.
|
||||
pub type SealingPublicKey = Secp256k1Point;
|
||||
/// Wraps a secp256k1 point but is a distinct type from `ViewingPublicKey` to enforce
|
||||
/// key separation: viewing keys encrypt account state, sealing keys encrypt the GMS
|
||||
/// for off-chain distribution.
|
||||
pub struct SealingPublicKey(Secp256k1Point);
|
||||
|
||||
impl SealingPublicKey {
|
||||
/// Derive the sealing public key from a secret scalar.
|
||||
#[must_use]
|
||||
pub fn from_scalar(scalar: Scalar) -> Self {
|
||||
Self(Secp256k1Point::from_scalar(scalar))
|
||||
}
|
||||
|
||||
/// Construct from raw serialized bytes (e.g. received from another wallet).
|
||||
#[must_use]
|
||||
pub const fn from_bytes(bytes: Vec<u8>) -> Self {
|
||||
Self(Secp256k1Point(bytes))
|
||||
}
|
||||
|
||||
/// Returns the raw bytes for display or transmission.
|
||||
#[must_use]
|
||||
pub fn to_bytes(&self) -> &[u8] {
|
||||
&self.0.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Secret key used to unseal a `GroupKeyHolder` received from another member.
|
||||
pub type SealingSecretKey = Scalar;
|
||||
@ -144,7 +164,7 @@ impl GroupKeyHolder {
|
||||
let mut ephemeral_scalar: Scalar = [0_u8; 32];
|
||||
OsRng.fill_bytes(&mut ephemeral_scalar);
|
||||
let ephemeral_pubkey = Secp256k1Point::from_scalar(ephemeral_scalar);
|
||||
let shared = SharedSecretKey::new(&ephemeral_scalar, recipient_key);
|
||||
let shared = SharedSecretKey::new(&ephemeral_scalar, &recipient_key.0);
|
||||
let aes_key = Self::seal_kdf(&shared);
|
||||
let cipher = Aes256Gcm::new(&aes_key.into());
|
||||
|
||||
@ -386,7 +406,7 @@ mod tests {
|
||||
let recipient_vpk = recipient_keys.generate_viewing_public_key();
|
||||
let recipient_vsk = recipient_keys.viewing_secret_key;
|
||||
|
||||
let sealed = holder.seal_for(&recipient_vpk);
|
||||
let sealed = holder.seal_for(&SealingPublicKey::from_bytes(recipient_vpk.0));
|
||||
let restored = GroupKeyHolder::unseal(&sealed, &recipient_vsk).expect("unseal");
|
||||
|
||||
assert_eq!(restored.dangerous_raw_gms(), holder.dangerous_raw_gms());
|
||||
@ -417,7 +437,7 @@ mod tests {
|
||||
.produce_private_key_holder(None)
|
||||
.viewing_secret_key;
|
||||
|
||||
let sealed = holder.seal_for(&recipient_vpk);
|
||||
let sealed = holder.seal_for(&SealingPublicKey::from_bytes(recipient_vpk.0));
|
||||
let result = GroupKeyHolder::unseal(&sealed, &wrong_vsk);
|
||||
assert!(matches!(result, Err(super::SealError::DecryptionFailed)));
|
||||
}
|
||||
@ -432,7 +452,7 @@ mod tests {
|
||||
let recipient_vpk = recipient_keys.generate_viewing_public_key();
|
||||
let recipient_vsk = recipient_keys.viewing_secret_key;
|
||||
|
||||
let mut sealed = holder.seal_for(&recipient_vpk);
|
||||
let mut sealed = holder.seal_for(&SealingPublicKey::from_bytes(recipient_vpk.0));
|
||||
// Flip a byte in the ciphertext portion (after ephemeral_pubkey + nonce)
|
||||
let last = sealed.len() - 1;
|
||||
sealed[last] ^= 0xFF;
|
||||
@ -451,8 +471,9 @@ mod tests {
|
||||
.produce_private_key_holder(None)
|
||||
.generate_viewing_public_key();
|
||||
|
||||
let sealed_a = holder.seal_for(&recipient_vpk);
|
||||
let sealed_b = holder.seal_for(&recipient_vpk);
|
||||
let sealing_key = SealingPublicKey::from_bytes(recipient_vpk.0);
|
||||
let sealed_a = holder.seal_for(&sealing_key);
|
||||
let sealed_b = holder.seal_for(&sealing_key);
|
||||
assert_ne!(sealed_a, sealed_b);
|
||||
}
|
||||
|
||||
@ -514,7 +535,7 @@ mod tests {
|
||||
let bob_vpk = bob_keys.generate_viewing_public_key();
|
||||
let bob_vsk = bob_keys.viewing_secret_key;
|
||||
|
||||
let sealed = alice_holder.seal_for(&bob_vpk);
|
||||
let sealed = alice_holder.seal_for(&SealingPublicKey::from_bytes(bob_vpk.0));
|
||||
let bob_holder =
|
||||
GroupKeyHolder::unseal(&sealed, &bob_vsk).expect("Bob should unseal the GMS");
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use anyhow::{Context as _, Result};
|
||||
use clap::Subcommand;
|
||||
use key_protocol::key_management::group_key_holder::GroupKeyHolder;
|
||||
use key_protocol::key_management::group_key_holder::{GroupKeyHolder, SealingPublicKey};
|
||||
|
||||
use crate::{
|
||||
WalletCore,
|
||||
@ -99,8 +99,10 @@ impl WalletSubcommand for GroupSubcommand {
|
||||
.context(format!("Group '{name}' not found"))?;
|
||||
|
||||
let key_bytes = hex::decode(&key).context("Invalid key hex")?;
|
||||
let recipient_key: key_protocol::key_management::group_key_holder::SealingPublicKey =
|
||||
nssa_core::encryption::shared_key_derivation::Secp256k1Point(key_bytes);
|
||||
let recipient_key =
|
||||
key_protocol::key_management::group_key_holder::SealingPublicKey::from_bytes(
|
||||
key_bytes,
|
||||
);
|
||||
|
||||
let sealed = holder.seal_for(&recipient_key);
|
||||
println!("{}", hex::encode(&sealed));
|
||||
@ -141,16 +143,13 @@ impl WalletSubcommand for GroupSubcommand {
|
||||
|
||||
let mut secret: nssa_core::encryption::Scalar = [0_u8; 32];
|
||||
rand::RngCore::fill_bytes(&mut rand::rngs::OsRng, &mut secret);
|
||||
let public_key =
|
||||
nssa_core::encryption::shared_key_derivation::Secp256k1Point::from_scalar(
|
||||
secret,
|
||||
);
|
||||
let public_key = SealingPublicKey::from_scalar(secret);
|
||||
|
||||
wallet_core.set_sealing_secret_key(secret);
|
||||
wallet_core.store_persistent_data().await?;
|
||||
|
||||
println!("Sealing key generated.");
|
||||
println!("Public key: {}", hex::encode(&public_key.0));
|
||||
println!("Public key: {}", hex::encode(public_key.to_bytes()));
|
||||
println!("Share this public key with group members so they can seal GMS for you.");
|
||||
Ok(SubcommandReturnValue::Empty)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user