lssa/key_protocol/src/key_management/ephemeral_key_holder.rs

62 lines
2.2 KiB
Rust
Raw Normal View History

2025-09-15 14:04:49 +03:00
use nssa_core::{
2026-05-13 20:43:12 -04:00
SharedSecretKey,
encryption::{EphemeralPublicKey, ViewingPublicKey},
2025-09-15 14:04:49 +03:00
};
2024-10-30 12:32:36 +02:00
2026-05-13 20:43:12 -04:00
/// Ephemeral key holder for the sender side of a KEM-based shared-secret exchange.
///
/// Non-clonable as intended for one-time use: construction encapsulates once and
2026-05-20 16:00:57 -04:00
/// stores both the shared secret and the ciphertext (`EphemeralPublicKey`) that must
2026-05-13 20:43:12 -04:00
/// be sent to the receiver.
2024-10-30 12:32:36 +02:00
pub struct EphemeralKeyHolder {
2026-05-13 20:43:12 -04:00
shared_secret: SharedSecretKey,
ephemeral_public_key: EphemeralPublicKey,
}
2026-05-20 17:40:02 -04:00
// SharedSecretKey does not implement Debug (intentional — leaking key material via
2026-05-13 20:43:12 -04:00
// debug output would be a security risk). We implement Debug manually here, redacting the
// shared secret while still allowing the ephemeral public key (KEM ciphertext) to be inspected.
impl std::fmt::Debug for EphemeralKeyHolder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EphemeralKeyHolder")
.field("shared_secret", &"<redacted>")
.field("ephemeral_public_key", &self.ephemeral_public_key)
.finish()
}
2024-10-30 12:32:36 +02:00
}
impl EphemeralKeyHolder {
2026-03-03 23:21:08 +03:00
#[must_use]
2026-05-13 20:43:12 -04:00
pub fn new(receiver_viewing_public_key: &ViewingPublicKey) -> Self {
let (shared_secret, ephemeral_public_key) =
SharedSecretKey::encapsulate(receiver_viewing_public_key);
2024-10-30 12:32:36 +02:00
Self {
2026-05-13 20:43:12 -04:00
shared_secret,
ephemeral_public_key,
2024-10-30 12:32:36 +02:00
}
}
2026-05-20 16:00:57 -04:00
/// Returns the KEM ciphertext to be transmitted to the receiver as the `EphemeralPublicKey`.
2026-03-03 23:21:08 +03:00
#[must_use]
2026-05-20 16:00:57 -04:00
pub const fn ephemeral_public_key(&self) -> &EphemeralPublicKey {
2026-05-13 20:43:12 -04:00
&self.ephemeral_public_key
2024-10-30 12:32:36 +02:00
}
2026-05-13 20:43:12 -04:00
/// Returns the sender-side shared secret (established at construction time).
2026-03-03 23:21:08 +03:00
#[must_use]
2026-05-20 16:00:57 -04:00
pub const fn calculate_shared_secret_sender(&self) -> SharedSecretKey {
2026-05-13 20:43:12 -04:00
self.shared_secret
2024-10-30 12:32:36 +02:00
}
}
2026-03-04 18:42:33 +03:00
2026-05-13 20:43:12 -04:00
/// Encapsulates a fresh shared secret toward `vpk` and returns `(shared_secret, ciphertext)`.
///
/// Used when the local side is acting as an "ephemeral receiver" — i.e. generating a
/// one-sided encryption that only the holder of the VSK can decrypt.
2026-03-04 18:42:33 +03:00
#[must_use]
pub fn produce_one_sided_shared_secret_receiver(
2026-05-13 20:43:12 -04:00
vpk: &ViewingPublicKey,
2026-03-04 18:42:33 +03:00
) -> (SharedSecretKey, EphemeralPublicKey) {
2026-05-13 20:43:12 -04:00
SharedSecretKey::encapsulate(vpk)
2026-03-04 18:42:33 +03:00
}