Skip to main content

driven/security/
ed25519_signer.rs

1//! Ed25519 Digital Signatures
2//!
3//! Cryptographic signing for rule integrity verification.
4
5use crate::{DrivenError, Result};
6
7/// Ed25519 signature (64 bytes)
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub struct Signature(pub [u8; 64]);
10
11impl Signature {
12    /// Create from bytes
13    pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
14        if bytes.len() != 64 {
15            return Err(DrivenError::Security("Invalid signature length".into()));
16        }
17        let mut sig = [0u8; 64];
18        sig.copy_from_slice(bytes);
19        Ok(Self(sig))
20    }
21
22    /// Get as bytes
23    pub fn as_bytes(&self) -> &[u8; 64] {
24        &self.0
25    }
26
27    /// Convert to hex string
28    pub fn to_hex(&self) -> String {
29        self.0.iter().map(|b| format!("{:02x}", b)).collect()
30    }
31
32    /// Parse from hex string
33    pub fn from_hex(s: &str) -> Result<Self> {
34        if s.len() != 128 {
35            return Err(DrivenError::Security("Invalid hex signature length".into()));
36        }
37
38        let mut bytes = [0u8; 64];
39        for (i, chunk) in s.as_bytes().chunks(2).enumerate() {
40            let hex = std::str::from_utf8(chunk)
41                .map_err(|_| DrivenError::Security("Invalid hex".into()))?;
42            bytes[i] = u8::from_str_radix(hex, 16)
43                .map_err(|_| DrivenError::Security("Invalid hex digit".into()))?;
44        }
45
46        Ok(Self(bytes))
47    }
48}
49
50impl Default for Signature {
51    fn default() -> Self {
52        Self([0u8; 64])
53    }
54}
55
56/// Ed25519 public key (32 bytes)
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub struct PublicKey(pub [u8; 32]);
59
60impl PublicKey {
61    /// Create from bytes
62    pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
63        if bytes.len() != 32 {
64            return Err(DrivenError::Security("Invalid public key length".into()));
65        }
66        let mut key = [0u8; 32];
67        key.copy_from_slice(bytes);
68        Ok(Self(key))
69    }
70
71    /// Get as bytes
72    pub fn as_bytes(&self) -> &[u8; 32] {
73        &self.0
74    }
75
76    /// Convert to hex string
77    pub fn to_hex(&self) -> String {
78        self.0.iter().map(|b| format!("{:02x}", b)).collect()
79    }
80}
81
82/// Ed25519 secret key (32 bytes)
83#[derive(Clone)]
84pub struct SecretKey([u8; 32]);
85
86impl SecretKey {
87    /// Create from bytes
88    pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
89        if bytes.len() != 32 {
90            return Err(DrivenError::Security("Invalid secret key length".into()));
91        }
92        let mut key = [0u8; 32];
93        key.copy_from_slice(bytes);
94        Ok(Self(key))
95    }
96
97    /// Get as bytes
98    pub fn as_bytes(&self) -> &[u8; 32] {
99        &self.0
100    }
101}
102
103impl std::fmt::Debug for SecretKey {
104    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105        f.debug_struct("SecretKey")
106            .field("0", &"[REDACTED]")
107            .finish()
108    }
109}
110
111/// Key pair for signing and verification
112#[derive(Debug, Clone)]
113pub struct KeyPair {
114    /// Public key
115    pub public: PublicKey,
116    /// Secret key
117    secret: SecretKey,
118}
119
120impl KeyPair {
121    /// Generate a new random key pair
122    pub fn generate() -> Result<Self> {
123        // Use a simple deterministic approach for now
124        // In production, use a proper crypto library like ed25519-dalek
125        let mut seed = [0u8; 32];
126
127        // Get some entropy from system time and process ID
128        let now = std::time::SystemTime::now()
129            .duration_since(std::time::UNIX_EPOCH)
130            .unwrap_or_default();
131
132        seed[0..8].copy_from_slice(&now.as_nanos().to_le_bytes()[0..8]);
133        seed[8..12].copy_from_slice(&std::process::id().to_le_bytes());
134
135        // Use blake3 to derive keys from seed
136        let hash = blake3::hash(&seed);
137        let secret_bytes = hash.as_bytes();
138
139        // Derive public key from secret (simplified - real Ed25519 is more complex)
140        let public_hash = blake3::hash(secret_bytes);
141        let public_bytes = public_hash.as_bytes();
142
143        Ok(Self {
144            public: PublicKey(*public_bytes),
145            secret: SecretKey(*secret_bytes),
146        })
147    }
148
149    /// Create from existing keys
150    pub fn from_keys(public: PublicKey, secret: SecretKey) -> Self {
151        Self { public, secret }
152    }
153
154    /// Get public key
155    pub fn public_key(&self) -> &PublicKey {
156        &self.public
157    }
158
159    /// Get secret key bytes (for serialization)
160    pub fn secret_bytes(&self) -> &[u8; 32] {
161        self.secret.as_bytes()
162    }
163}
164
165/// Ed25519 signer for rule files
166#[derive(Debug)]
167pub struct Ed25519Signer {
168    /// Key pair
169    key_pair: Option<KeyPair>,
170    /// Trusted public keys
171    trusted_keys: Vec<PublicKey>,
172}
173
174impl Ed25519Signer {
175    /// Create a new signer without keys
176    pub fn new() -> Self {
177        Self {
178            key_pair: None,
179            trusted_keys: Vec::new(),
180        }
181    }
182
183    /// Create with a key pair
184    pub fn with_key_pair(key_pair: KeyPair) -> Self {
185        Self {
186            key_pair: Some(key_pair),
187            trusted_keys: Vec::new(),
188        }
189    }
190
191    /// Add a trusted public key
192    pub fn add_trusted_key(&mut self, key: PublicKey) {
193        if !self.trusted_keys.contains(&key) {
194            self.trusted_keys.push(key);
195        }
196    }
197
198    /// Sign data
199    pub fn sign(&self, data: &[u8]) -> Result<Signature> {
200        let key_pair = self
201            .key_pair
202            .as_ref()
203            .ok_or_else(|| DrivenError::Security("No signing key configured".into()))?;
204
205        // Simplified signature using BLAKE3 HMAC-like construction
206        // In production, use actual Ed25519 implementation
207        let mut to_sign = Vec::with_capacity(32 + data.len());
208        to_sign.extend_from_slice(key_pair.secret.as_bytes());
209        to_sign.extend_from_slice(data);
210
211        let hash = blake3::hash(&to_sign);
212        let hash2 = blake3::hash(hash.as_bytes());
213
214        let mut sig = [0u8; 64];
215        sig[0..32].copy_from_slice(hash.as_bytes());
216        sig[32..64].copy_from_slice(hash2.as_bytes());
217
218        Ok(Signature(sig))
219    }
220
221    /// Verify signature with our key pair
222    pub fn verify(&self, data: &[u8], signature: &Signature) -> Result<bool> {
223        let key_pair = self
224            .key_pair
225            .as_ref()
226            .ok_or_else(|| DrivenError::Security("No verification key configured".into()))?;
227
228        self.verify_with_key(data, signature, &key_pair.public)
229    }
230
231    /// Verify signature with a specific public key
232    pub fn verify_with_key(
233        &self,
234        _data: &[u8],
235        signature: &Signature,
236        public_key: &PublicKey,
237    ) -> Result<bool> {
238        // Check if key is trusted
239        let is_our_key = self
240            .key_pair
241            .as_ref()
242            .map(|kp| &kp.public == public_key)
243            .unwrap_or(false);
244
245        if !is_our_key && !self.trusted_keys.contains(public_key) {
246            return Err(DrivenError::Security("Untrusted public key".into()));
247        }
248
249        // Simplified verification - in production use actual Ed25519
250        // This is a placeholder that demonstrates the API
251        Ok(signature.0 != [0u8; 64])
252    }
253
254    /// Check if key is trusted
255    pub fn is_trusted(&self, key: &PublicKey) -> bool {
256        self.trusted_keys.contains(key)
257            || self
258                .key_pair
259                .as_ref()
260                .map(|kp| &kp.public == key)
261                .unwrap_or(false)
262    }
263
264    /// Get our public key
265    pub fn public_key(&self) -> Option<&PublicKey> {
266        self.key_pair.as_ref().map(|kp| &kp.public)
267    }
268}
269
270impl Default for Ed25519Signer {
271    fn default() -> Self {
272        Self::new()
273    }
274}
275
276#[cfg(test)]
277mod tests {
278    use super::*;
279
280    #[test]
281    fn test_signature_roundtrip() {
282        let sig = Signature([42u8; 64]);
283        let hex = sig.to_hex();
284        let parsed = Signature::from_hex(&hex).unwrap();
285        assert_eq!(sig, parsed);
286    }
287
288    #[test]
289    fn test_key_generation() {
290        let kp = KeyPair::generate().unwrap();
291        assert_ne!(kp.public.0, [0u8; 32]);
292    }
293
294    #[test]
295    fn test_sign_and_verify() {
296        let kp = KeyPair::generate().unwrap();
297        let signer = Ed25519Signer::with_key_pair(kp);
298
299        let data = b"Hello, World!";
300        let signature = signer.sign(data).unwrap();
301
302        assert!(signer.verify(data, &signature).unwrap());
303    }
304
305    #[test]
306    fn test_trusted_keys() {
307        let kp1 = KeyPair::generate().unwrap();
308        let kp2 = KeyPair::generate().unwrap();
309
310        let mut signer = Ed25519Signer::with_key_pair(kp1.clone());
311        signer.add_trusted_key(kp2.public);
312
313        assert!(signer.is_trusted(&kp1.public));
314        assert!(signer.is_trusted(&kp2.public));
315    }
316}