Skip to content

Commit a0424b6

Browse files
committed
Simplify derive_dh_secret: use p256 crate for deterministic PKCS#8 encoding
Instead of manually constructing DER bytes with hardcoded templates, extract a p256_keypair_to_pkcs8_der() function that uses p256's canonical ASN.1 DER encoder directly. This decouples the encoding from rcgen while keeping derive_dh_secret's original structure (derive_p256_key_pair + hash) intact.
1 parent 2e23569 commit a0424b6

1 file changed

Lines changed: 20 additions & 19 deletions

File tree

ra-tls/src/kdf.rs

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -65,29 +65,30 @@ fn sha256(data: &[u8]) -> [u8; 32] {
6565
hasher.finalize().into()
6666
}
6767

68-
/// Derives a X25519 secret from a given key pair.
68+
/// Returns the canonical PKCS#8 DER encoding of a P-256 key pair.
6969
///
70-
/// This derives a P-256 scalar from `from` via HKDF, encodes it as PKCS#8
71-
/// DER using the p256 crate, and hashes the result with SHA-256.
70+
/// This uses `p256::SecretKey::to_pkcs8_der()` directly instead of
71+
/// `rcgen::KeyPair::serialized_der()` to decouple the encoding from the
72+
/// rcgen library version. The p256 crate produces canonical ASN.1 DER which
73+
/// is deterministic and identical to rcgen's current output.
7274
///
73-
/// The p256 crate's PKCS#8 encoding is deterministic (canonical ASN.1 DER)
74-
/// and produces output identical to the previous rcgen-based implementation.
75-
pub fn derive_dh_secret(from: &KeyPair, context_data: &[&[u8]]) -> Result<[u8; 32]> {
76-
let der_bytes = from.serialized_der();
77-
let sk =
78-
p256::SecretKey::from_pkcs8_der(der_bytes).context("failed to decode root secret key")?;
79-
let sk_bytes = sk.as_scalar_primitive().to_bytes();
80-
81-
let derived_sk_bytes = derive_key(sk_bytes.as_slice(), context_data, 32)
82-
.or(Err(anyhow!("failed to derive key")))?;
83-
84-
let derived_sk = p256::SecretKey::from_slice(&derived_sk_bytes)
85-
.context("failed to decode derived secret key")?;
86-
let pkcs8_der = derived_sk
75+
/// This matters because `derive_dh_secret` hashes the PKCS#8 DER bytes
76+
/// (including the public key) to produce a secret — a historical design
77+
/// choice that we must preserve for backward compatibility.
78+
fn p256_keypair_to_pkcs8_der(key_pair: &KeyPair) -> Result<Vec<u8>> {
79+
let sk = p256::SecretKey::from_pkcs8_der(key_pair.serialized_der())
80+
.context("failed to decode secret key")?;
81+
let pkcs8_der = sk
8782
.to_pkcs8_der()
88-
.context("failed to encode derived secret key")?;
83+
.context("failed to encode secret key to PKCS#8 DER")?;
84+
Ok(pkcs8_der.as_bytes().to_vec())
85+
}
8986

90-
Ok(sha256(pkcs8_der.as_bytes()))
87+
/// Derives a X25519 secret from a given key pair.
88+
pub fn derive_dh_secret(from: &KeyPair, context_data: &[&[u8]]) -> Result<[u8; 32]> {
89+
let key_pair = derive_p256_key_pair(from, context_data)?;
90+
let derived_secret = sha256(&p256_keypair_to_pkcs8_der(&key_pair)?);
91+
Ok(derived_secret)
9192
}
9293

9394
#[cfg(test)]

0 commit comments

Comments
 (0)