ant_quic/crypto/
raw_keys.rs

1//! Raw Public Key Support
2//!
3//! This module implements support for Ed25519 keys in SubjectPublicKeyInfo format
4//! as specified in RFC 7250. It provides functionality for key generation, encoding,
5//! and verification with a focus on simplicity and performance.
6
7use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
8use rand::rngs::OsRng;
9use thiserror::Error;
10
11/// Errors that can occur during raw public key operations
12#[derive(Debug, Error)]
13pub enum RawKeyError {
14    #[error("Invalid key format: {0}")]
15    InvalidFormat(String),
16    
17    #[error("Verification failed")]
18    VerificationFailed,
19    
20    #[error("Encoding error: {0}")]
21    EncodingError(String),
22    
23    #[error("Decoding error: {0}")]
24    DecodingError(String),
25}
26
27/// Ed25519 key pair for authentication
28#[derive(Clone, Debug)]
29pub struct Ed25519KeyPair {
30    signing_key: SigningKey,
31    verifying_key: VerifyingKey,
32}
33
34impl Ed25519KeyPair {
35    /// Generate a new random Ed25519 key pair
36    pub fn generate() -> Self {
37        let signing_key = SigningKey::generate(&mut OsRng);
38        let verifying_key = VerifyingKey::from(&signing_key);
39        
40        Self {
41            signing_key,
42            verifying_key,
43        }
44    }
45    
46    /// Create a key pair from an existing signing key
47    pub fn from_signing_key(signing_key: SigningKey) -> Self {
48        let verifying_key = VerifyingKey::from(&signing_key);
49        Self {
50            signing_key,
51            verifying_key,
52        }
53    }
54    
55    /// Get the public key in SubjectPublicKeyInfo format
56    pub fn public_key_spki(&self) -> Vec<u8> {
57        create_ed25519_subject_public_key_info(&self.verifying_key)
58    }
59    
60    /// Get the raw public key bytes
61    pub fn public_key_bytes(&self) -> [u8; 32] {
62        *self.verifying_key.as_bytes()
63    }
64    
65    /// Get a reference to the verifying key
66    pub fn verifying_key(&self) -> &VerifyingKey {
67        &self.verifying_key
68    }
69    
70    /// Sign data with the private key
71    pub fn sign(&self, data: &[u8]) -> Signature {
72        self.signing_key.sign(data)
73    }
74    
75    /// Verify a signature with the public key
76    pub fn verify(&self, data: &[u8], signature: &Signature) -> Result<(), RawKeyError> {
77        self.verifying_key.verify(data, signature)
78            .map_err(|_| RawKeyError::VerificationFailed)
79    }
80}
81
82/// Create a SubjectPublicKeyInfo DER encoding for an Ed25519 public key
83///
84/// This function creates a minimal DER encoding of the SubjectPublicKeyInfo
85/// structure containing an Ed25519 public key as specified in RFC 5280 and RFC 8410.
86pub fn create_ed25519_subject_public_key_info(public_key: &VerifyingKey) -> Vec<u8> {
87    // Ed25519 SubjectPublicKeyInfo structure:
88    // SEQUENCE {
89    //   SEQUENCE {
90    //     OBJECT IDENTIFIER 1.3.101.112 (Ed25519)
91    //   }
92    //   BIT STRING (32 bytes of public key)
93    // }
94    
95    // Pre-allocate the exact size needed (44 bytes)
96    let mut spki = Vec::with_capacity(44);
97    
98    // SEQUENCE tag and length (total length will be 44 bytes)
99    spki.extend_from_slice(&[0x30, 0x2a]);
100    
101    // Algorithm identifier SEQUENCE
102    spki.extend_from_slice(&[0x30, 0x05]);
103    
104    // Ed25519 OID: 1.3.101.112
105    spki.extend_from_slice(&[0x06, 0x03, 0x2b, 0x65, 0x70]);
106    
107    // Subject public key BIT STRING
108    spki.extend_from_slice(&[0x03, 0x21, 0x00]); // BIT STRING, 33 bytes (32 + 1 unused bits byte)
109    
110    // The actual 32-byte Ed25519 public key
111    spki.extend_from_slice(public_key.as_bytes());
112    
113    spki
114}
115
116/// Extract an Ed25519 public key from SubjectPublicKeyInfo format
117///
118/// This function extracts the raw 32-byte Ed25519 public key from a
119/// SubjectPublicKeyInfo structure as specified in RFC 5280 and RFC 8410.
120pub fn extract_ed25519_key_from_spki(spki_der: &[u8]) -> Result<[u8; 32], RawKeyError> {
121    // Simple parsing for Ed25519 SubjectPublicKeyInfo
122    if spki_der.len() != 44 {
123        return Err(RawKeyError::InvalidFormat(format!(
124            "Invalid SPKI length: expected 44 bytes, got {}",
125            spki_der.len()
126        )));
127    }
128    
129    // Look for Ed25519 OID pattern in the DER encoding
130    let ed25519_oid = [0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70];
131    
132    if !spki_der.starts_with(&ed25519_oid) {
133        return Err(RawKeyError::InvalidFormat(
134            "Invalid SPKI format: Ed25519 OID not found".to_string()
135        ));
136    }
137    
138    // The public key should be at offset 12 and be 32 bytes long
139    let mut public_key = [0u8; 32];
140    public_key.copy_from_slice(&spki_der[12..44]);
141    
142    Ok(public_key)
143}
144
145/// Create a VerifyingKey from SubjectPublicKeyInfo format
146pub fn verifying_key_from_spki(spki_der: &[u8]) -> Result<VerifyingKey, RawKeyError> {
147    let key_bytes = extract_ed25519_key_from_spki(spki_der)?;
148    VerifyingKey::from_bytes(&key_bytes)
149        .map_err(|e| RawKeyError::InvalidFormat(format!("Invalid Ed25519 public key: {}", e)))
150}
151
152/// Derive a peer ID from a public key
153///
154/// This function creates a deterministic peer ID from an Ed25519 public key
155/// using a secure hash function to ensure uniform distribution and prevent
156/// direct key exposure.
157pub fn derive_peer_id_from_public_key(public_key: &VerifyingKey) -> [u8; 32] {
158    // Use SHA-256 to hash the public key with a domain separator
159    use ring::digest::{digest, SHA256};
160    
161    let key_bytes = public_key.as_bytes();
162    
163    // Create the input data with domain separator
164    let mut input = Vec::with_capacity(20 + 32); // "AUTONOMI_PEER_ID_V1:" + key_bytes
165    input.extend_from_slice(b"AUTONOMI_PEER_ID_V1:");
166    input.extend_from_slice(key_bytes);
167    
168    // Hash the input
169    let hash = digest(&SHA256, &input);
170    let hash_bytes = hash.as_ref();
171    
172    let mut peer_id_bytes = [0u8; 32];
173    peer_id_bytes.copy_from_slice(hash_bytes);
174    
175    peer_id_bytes
176}
177
178/// Verify that a peer ID was correctly derived from a public key
179pub fn verify_peer_id(peer_id: &[u8; 32], public_key: &VerifyingKey) -> bool {
180    let derived_id = derive_peer_id_from_public_key(public_key);
181    peer_id == &derived_id
182}
183
184/// Generate a new Ed25519 key pair (convenience function)
185pub fn generate_ed25519_keypair() -> Ed25519KeyPair {
186    Ed25519KeyPair::generate()
187}
188
189#[cfg(test)]
190mod tests {
191    use super::*;
192    
193    #[test]
194    fn test_keypair_generation() {
195        let keypair = Ed25519KeyPair::generate();
196        let signature = keypair.sign(b"test message");
197        assert!(keypair.verify(b"test message", &signature).is_ok());
198        assert!(keypair.verify(b"wrong message", &signature).is_err());
199    }
200    
201    #[test]
202    fn test_spki_encoding_decoding() {
203        let keypair = Ed25519KeyPair::generate();
204        let spki = keypair.public_key_spki();
205        
206        // Verify SPKI format
207        assert_eq!(spki.len(), 44);
208        assert_eq!(&spki[0..2], &[0x30, 0x2a]); // SEQUENCE tag and length
209        
210        // Extract key from SPKI
211        let extracted_key = extract_ed25519_key_from_spki(&spki).unwrap();
212        assert_eq!(extracted_key, keypair.public_key_bytes());
213        
214        // Create VerifyingKey from SPKI
215        let verifying_key = verifying_key_from_spki(&spki).unwrap();
216        assert_eq!(verifying_key.as_bytes(), keypair.verifying_key().as_bytes());
217    }
218    
219    #[test]
220    fn test_peer_id_derivation() {
221        let keypair1 = Ed25519KeyPair::generate();
222        let keypair2 = Ed25519KeyPair::generate();
223        
224        let peer_id1 = derive_peer_id_from_public_key(keypair1.verifying_key());
225        let peer_id2 = derive_peer_id_from_public_key(keypair1.verifying_key());
226        let peer_id3 = derive_peer_id_from_public_key(keypair2.verifying_key());
227        
228        // Same key should produce same peer ID
229        assert_eq!(peer_id1, peer_id2);
230        
231        // Different keys should produce different peer IDs
232        assert_ne!(peer_id1, peer_id3);
233        
234        // Verify peer ID
235        assert!(verify_peer_id(&peer_id1, keypair1.verifying_key()));
236        assert!(!verify_peer_id(&peer_id1, keypair2.verifying_key()));
237    }
238    
239    #[test]
240    fn test_invalid_spki() {
241        // Too short
242        let result = extract_ed25519_key_from_spki(&[0; 43]);
243        assert!(result.is_err());
244        
245        // Wrong OID
246        let mut invalid_spki = vec![0; 44];
247        invalid_spki[7] = 0xFF; // Corrupt the OID
248        let result = extract_ed25519_key_from_spki(&invalid_spki);
249        assert!(result.is_err());
250    }
251}