docs(exec-server): tighten Noise comments

Co-authored-by: Codex noreply@openai.com
This commit is contained in:
viyatb-oai
2026-06-10 10:26:18 -07:00
co-authored by Codex noreply@openai.com
parent b227892a48
commit 02820307b6
2 changed files with 10 additions and 51 deletions
+1 -15
View File
@@ -1,9 +1,4 @@
//! Bridges AWS-LC's ML-KEM-768 implementation into Clatter's `Kem` trait.
//!
//! Clatter owns the hybrid Noise state machine, while AWS-LC owns the concrete
//! post-quantum operations and their randomness. This module is intentionally
//! limited to converting between the two libraries' fixed-size key, ciphertext,
//! and shared-secret representations; it does not add protocol behavior.
//! Clatter's ML-KEM-768 adapter, backed by AWS-LC.
use aws_lc_rs::kem::Ciphertext;
use aws_lc_rs::kem::DecapsulationKey;
@@ -40,10 +35,6 @@ impl Kem for AwsLcMlKem768 {
type Ct = HeapArray<CIPHERTEXT_LEN>;
type Ss = SensitiveByteArray<[u8; SHARED_SECRET_LEN]>;
// Generate the long-lived static KEM keypair used by hybrid IK. AWS-LC
// returns serialized key bytes; copying them into Clatter's fixed-size
// containers gives the handshake implementation the exact lengths encoded
// by this suite and keeps the secret half in a zeroizing container.
fn genkey_rng<R: Rng>(_rng: &mut R) -> KemResult<KeyPair<Self::PubKey, Self::SecretKey>> {
// AWS-LC owns ML-KEM key-generation randomness internally, so
// Clatter's injectable RNG cannot be plumbed through this provider.
@@ -65,9 +56,6 @@ impl Kem for AwsLcMlKem768 {
})
}
// Parse the peer's serialized public key at the provider boundary, then
// return the ciphertext and shared secret in Clatter's fixed-size types.
// AWS-LC performs both public-key validation and encapsulation randomness.
fn encapsulate<R: Rng>(pk: &[u8], _rng: &mut R) -> KemResult<(Self::Ct, Self::Ss)> {
let encapsulation_key =
EncapsulationKey::new(&ML_KEM_768, pk).map_err(|_| KemError::Input)?;
@@ -81,8 +69,6 @@ impl Kem for AwsLcMlKem768 {
))
}
// Reconstruct the provider key from process-local secret bytes and recover
// the same shared secret the peer mixed into the hybrid handshake.
fn decapsulate(ct: &[u8], sk: &[u8]) -> KemResult<Self::Ss> {
// Reject the length before constructing AWS-LC's ciphertext wrapper.
// This keeps malformed wire input classified as an input error rather
+9 -36
View File
@@ -1,29 +1,14 @@
//! Narrow, misuse-resistant wrapper around the Clatter primitives used by the
//! remote exec-server relay.
//!
//! # Protocol overview
//! The harness initiates hybrid IK and pins the exec-server static key returned
//! by the registry. The first handshake message lets the exec-server authenticate
//! the harness static key; the exec-server then asks the registry whether that
//! key is authorized before completing the handshake.
//!
//! Noise is a framework for turning Diffie-Hellman operations into an
//! authenticated handshake and then an encrypted byte channel. This module uses
//! the `IK` handshake pattern: the harness is the initiator and already knows
//! the exec-server's static public key, while the exec-server learns and
//! authenticates the harness's static public key from the first handshake
//! message. That lets the harness reject the wrong executor immediately and
//! gives the executor a cryptographic identity it can authorize with the
//! environment registry.
//!
//! The suite is "hybrid" because the handshake combines classical X25519 with
//! post-quantum ML-KEM-768. Clatter runs the Noise state machine and mixes both
//! key-agreement results into the session keys; AWS-LC supplies the ML-KEM
//! operations. AES-GCM then protects ordered transport records after the two
//! handshake messages complete.
//!
//! The handshake authenticates keys, not product permissions. The first message
//! therefore carries a registry-issued harness authorization inside its
//! encrypted payload. The exec-server pauses after authenticating that message,
//! asks the registry whether the authenticated harness key is allowed, and only
//! then sends the second handshake message and exposes JSON-RPC. Application
//! data is never accepted before both checks pass.
//! "Hybrid" means the session keys include both X25519 and ML-KEM-768 key
//! agreement. Once the two-message handshake finishes, AES-GCM protects the
//! ordered transport records carrying JSON-RPC.
use base64::Engine;
use base64::engine::general_purpose::STANDARD;
@@ -37,10 +22,7 @@ use serde::Serialize;
use crate::aws_lc_ml_kem::AwsLcMlKem768;
/// Stable identifier for the complete handshake and transport algorithm suite.
///
/// This value travels with public keys so configuration cannot silently combine
/// key material generated for a different Noise pattern or algorithm set.
/// Identifies the handshake pattern and algorithms used by this channel.
pub const NOISE_CHANNEL_SUITE: &str = "Noise_hybridIK_X25519+MLKEM768_AESGCM_SHA256";
type DhKeyPair = KeyPair<<X25519 as Dh>::PubKey, <X25519 as Dh>::PrivateKey>;
@@ -61,9 +43,6 @@ pub struct NoiseChannelPublicKey {
impl std::fmt::Debug for NoiseChannelPublicKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// Public keys are not secrets, but logging complete identities makes
// correlation across environments unnecessarily easy. Keep only the
// suite visible in routine diagnostics.
f.debug_struct("NoiseChannelPublicKey")
.field("suite", &self.suite)
.field("x25519_public_key", &"<redacted>")
@@ -73,10 +52,7 @@ impl std::fmt::Debug for NoiseChannelPublicKey {
}
impl NoiseChannelPublicKey {
/// Serialize both public components as one suite-tagged registry value.
///
/// Keeping the components together prevents callers from accidentally
/// pairing an X25519 key from one identity with an ML-KEM key from another.
/// Serialize both public components as one suite-tagged value.
fn from_keypairs(dh: &DhKeyPair, kem: &KemKeyPair) -> Self {
Self {
suite: NOISE_CHANNEL_SUITE.to_string(),
@@ -98,9 +74,6 @@ pub struct NoiseChannelIdentity {
impl std::fmt::Debug for NoiseChannelIdentity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// Never delegate to the keypair debug implementations: this type owns
// both private keys. Its public projection is sufficient to identify
// which endpoint identity a log entry refers to.
f.debug_struct("NoiseChannelIdentity")
.field("public_key", &self.public_key())
.finish_non_exhaustive()