ave-identity 0.3.0

Generic cryptographic primitives with algorithm identification
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
//! Ed25519 signer backed by encrypted in-memory secret key storage.

use crate::error::CryptoError;
use ed25519_dalek::{Signer as Ed25519SignerTrait, SigningKey, VerifyingKey};
use memsecurity::EncryptedMem;
use std::{fmt, sync::Arc};
use zeroize::Zeroize;

use super::{DSA, DSAlgorithm, SignatureIdentifier};

/// 1-byte identifier for Ed25519 signature algorithm: 'E'
pub const ED25519_ID: u8 = b'E';

/// Ed25519 public key length in bytes
pub const ED25519_PUBLIC_KEY_LENGTH: usize = 32;

/// Ed25519 secret key length in bytes
pub const ED25519_SECRET_KEY_LENGTH: usize = 32;

/// Ed25519 signature length in bytes
pub const ED25519_SIGNATURE_LENGTH: usize = 64;

/// Ed25519 signer.
///
/// The public key is always available. The secret key, when present, is kept in
/// encrypted memory and is only decrypted for signing.
#[derive(Default, Clone)]
pub struct Ed25519Signer {
    /// Public verifying key.
    public_key: VerifyingKey,
    /// Encrypted secret key, or `None` for verification-only instances.
    secret_key: Option<Arc<EncryptedMem>>,
}

impl Ed25519Signer {
    /// Decrypt the secret key from encrypted memory
    fn decrypt_secret_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        match &self.secret_key {
            Some(encrypted) => {
                let bytes = encrypted.decrypt().map_err(|e| {
                    CryptoError::InvalidSecretKey(format!(
                        "Failed to decrypt secret key: {:?}",
                        e
                    ))
                })?;
                Ok(Vec::from(bytes.as_ref()))
            }
            None => Err(CryptoError::MissingSecretKey),
        }
    }

    /// Create an encrypted EncryptedMem from secret key bytes
    /// This is only called during construction, ensuring immutability
    fn create_encrypted_secret(
        secret_key: &[u8],
    ) -> Result<Arc<EncryptedMem>, CryptoError> {
        let mut encrypted = EncryptedMem::new();
        encrypted.encrypt(&secret_key.to_vec()).map_err(|e| {
            CryptoError::InvalidSecretKey(format!(
                "Failed to encrypt secret key: {:?}",
                e
            ))
        })?;
        Ok(Arc::new(encrypted))
    }

    /// Generates a random Ed25519 signer.
    pub fn generate() -> Result<Self, CryptoError> {
        let mut seed = [0u8; 32];
        getrandom::fill(&mut seed).map_err(|e| {
            CryptoError::InvalidSecretKey(format!(
                "Failed to generate random seed: {}",
                e
            ))
        })?;
        Self::from_seed(&seed)
    }

    /// Derives a deterministic signer from arbitrary bytes.
    ///
    /// The input is hashed with Blake3 and the resulting 32 bytes are used as
    /// the Ed25519 seed. This is useful for reproducible keys.
    ///
    /// This is not a password-hard KDF.
    pub fn derive_from_data(data: &[u8]) -> Result<Self, CryptoError> {
        // Reject empty data
        if data.is_empty() {
            return Err(CryptoError::InvalidSecretKey(
                "Cannot derive keys from empty data. Use generate() for random keys".to_string(),
            ));
        }

        use crate::hash::{Blake3Hasher, Hash as HashTrait};

        // Hash the data to get exactly 32 bytes
        let hasher = Blake3Hasher;
        let hash = hasher.hash(data);
        let seed_bytes = hash.hash_bytes();

        let key_array: [u8; 32] = seed_bytes
            .try_into()
            .expect("Blake3 always produces 32 bytes");

        Self::from_seed(&key_array)
    }

    /// Builds a signer from an exact 32-byte seed.
    ///
    /// Unlike [`Self::derive_from_data`], this method does not hash the input.
    pub fn from_seed(seed: &[u8; 32]) -> Result<Self, CryptoError> {
        // Seed length is guaranteed by type system (&[u8; 32])
        let signing_key = SigningKey::from_bytes(seed);
        let public_key = signing_key.verifying_key();

        // Encrypt the secret key (immutable after creation)
        let encrypted_secret = Self::create_encrypted_secret(seed)?;

        Ok(Self {
            public_key,
            secret_key: Some(encrypted_secret),
        })
    }

    /// Builds a signer from 32 secret key bytes.
    pub fn from_secret_key(secret_key: &[u8]) -> Result<Self, CryptoError> {
        let key_bytes: [u8; 32] = secret_key.try_into().map_err(|_| {
            CryptoError::InvalidSecretKey(format!(
                "Invalid secret key length: expected {} bytes, got {}",
                ED25519_SECRET_KEY_LENGTH,
                secret_key.len()
            ))
        })?;
        Self::from_seed(&key_bytes)
    }

    /// Builds a verification-only signer from a public key.
    pub fn from_public_key(public_key: &[u8]) -> Result<Self, CryptoError> {
        if public_key.len() != ED25519_PUBLIC_KEY_LENGTH {
            return Err(CryptoError::InvalidPublicKey(format!(
                "Invalid public key length: expected {} bytes, got {}",
                ED25519_PUBLIC_KEY_LENGTH,
                public_key.len()
            )));
        }

        let key_bytes: [u8; 32] = public_key.try_into().map_err(|_| {
            CryptoError::InvalidPublicKey("Invalid length".to_string())
        })?;
        let verifying_key = VerifyingKey::from_bytes(&key_bytes)
            .map_err(|e| CryptoError::InvalidPublicKey(e.to_string()))?;

        Ok(Self {
            public_key: verifying_key,
            secret_key: None,
        })
    }

    /// Returns the public key.
    pub const fn public_key(&self) -> VerifyingKey {
        self.public_key
    }

    /// Returns the decrypted secret key bytes.
    pub fn secret_key_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        self.decrypt_secret_bytes()
    }
}

impl fmt::Debug for Ed25519Signer {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use crate::common::base64_encoding;
        f.debug_struct("Ed25519Signer")
            .field(
                "public_key",
                &base64_encoding::encode(self.public_key().as_bytes()),
            )
            .finish_non_exhaustive()
    }
}

impl DSA for Ed25519Signer {
    fn algorithm_id(&self) -> u8 {
        ED25519_ID
    }

    fn signature_length(&self) -> usize {
        ED25519_SIGNATURE_LENGTH
    }

    fn sign(&self, message: &[u8]) -> Result<SignatureIdentifier, CryptoError> {
        // Decrypt the secret key from secure storage
        let mut secret_bytes = self.decrypt_secret_bytes()?;

        // Create signing key from decrypted bytes
        // Note: Length was already validated during key creation, so we can safely unwrap
        let key_array: [u8; 32] = secret_bytes
            .as_slice()
            .try_into()
            .expect("Secret key should always be 32 bytes");
        let signing_key = SigningKey::from_bytes(&key_array);

        // Sign the message
        let signature = signing_key.sign(message);
        let signature_bytes = signature.to_bytes();

        // Explicitly zeroize the secret bytes before dropping
        secret_bytes.zeroize();

        // Ed25519 always produces 64-byte signatures
        SignatureIdentifier::new(DSAlgorithm::Ed25519, signature_bytes.to_vec())
    }

    fn algorithm(&self) -> DSAlgorithm {
        DSAlgorithm::Ed25519
    }

    fn public_key_bytes(&self) -> Vec<u8> {
        self.public_key.as_bytes().to_vec()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_ed25519_sign_verify() {
        let signer = Ed25519Signer::generate().unwrap();
        let message = b"Hello, World!";

        let signature = signer.sign(message).unwrap();
        assert_eq!(signature.algorithm(), DSAlgorithm::Ed25519);

        let public_key = signer.public_key();
        assert!(signature.verify(message, public_key.as_bytes()).is_ok());
    }

    #[test]
    fn test_derive_from_data() {
        // Test with arbitrary-length data (will be hashed)
        let short_data = b"hello";
        let signer1 = Ed25519Signer::derive_from_data(short_data).unwrap();
        let signer2 = Ed25519Signer::derive_from_data(short_data).unwrap();

        // Same data should produce same keys
        assert_eq!(signer1.public_key_bytes(), signer2.public_key_bytes());

        // Different data should produce different keys
        let different_data = b"world";
        let signer3 = Ed25519Signer::derive_from_data(different_data).unwrap();
        assert_ne!(signer1.public_key_bytes(), signer3.public_key_bytes());

        // Long data should also work
        let long_data =
            b"this is a very long passphrase that is much longer than 32 bytes";
        let signer4 = Ed25519Signer::derive_from_data(long_data).unwrap();
        assert_ne!(signer1.public_key_bytes(), signer4.public_key_bytes());

        // Empty data should return an error
        let empty_data = b"";
        let result = Ed25519Signer::derive_from_data(empty_data);
        assert!(result.is_err());
    }

    #[test]
    fn test_from_seed() {
        // Test with exact 32-byte seeds (no hashing)
        let seed = [42u8; 32];
        let signer1 = Ed25519Signer::from_seed(&seed).unwrap();
        let signer2 = Ed25519Signer::from_seed(&seed).unwrap();

        // Same seed should produce same keys
        assert_eq!(signer1.public_key_bytes(), signer2.public_key_bytes());

        // derive_from_data with 32 bytes should produce DIFFERENT keys than from_seed
        // because derive_from_data hashes the input
        let signer3 = Ed25519Signer::derive_from_data(&seed).unwrap();
        assert_ne!(signer1.public_key_bytes(), signer3.public_key_bytes());
    }

    #[test]
    fn test_from_public_key() {
        let signer = Ed25519Signer::generate().unwrap();
        let message = b"Test message";

        // Sign with full signer
        let signature = signer.sign(message).unwrap();

        // Create verification-only signer from public key
        let verifier =
            Ed25519Signer::from_public_key(&signer.public_key_bytes()).unwrap();

        // Should be able to get public key
        assert_eq!(verifier.public_key_bytes(), signer.public_key_bytes());

        // Should not be able to sign (no secret key)
        assert!(verifier.sign(message).is_err());

        // But verification should still work
        assert!(
            signature
                .verify(message, verifier.public_key().as_bytes())
                .is_ok()
        );
    }

    #[test]
    fn test_encrypted_secret_key() {
        let seed = [42u8; 32];
        let signer = Ed25519Signer::from_seed(&seed).unwrap();

        // Should be able to get secret key bytes (will decrypt)
        let secret = signer.secret_key_bytes().unwrap();
        assert_eq!(secret.len(), 32);

        // Create new signer from same seed
        let signer2 = Ed25519Signer::from_seed(&seed).unwrap();
        let secret2 = signer2.secret_key_bytes().unwrap();

        // Should have same secret key
        assert_eq!(secret, secret2);
    }

    #[test]
    fn test_invalid_key_lengths() {
        // Test invalid secret key length
        let invalid_secret = vec![0u8; 16]; // Only 16 bytes instead of 32
        let result = Ed25519Signer::from_secret_key(&invalid_secret);
        assert!(result.is_err());

        // Test invalid public key length
        let invalid_public = vec![0u8; 16]; // Only 16 bytes instead of 32
        let result = Ed25519Signer::from_public_key(&invalid_public);
        assert!(result.is_err());
    }

    #[test]
    fn test_concurrent_signing() {
        use std::sync::Arc;
        use std::thread;

        // Create a signer
        let signer = Arc::new(Ed25519Signer::generate().unwrap());

        // Spawn multiple threads that sign concurrently
        let mut handles = vec![];
        for i in 0..10 {
            let signer_clone = Arc::clone(&signer);
            let msg = format!("message {}", i);

            let handle = thread::spawn(move || {
                let signature = signer_clone.sign(msg.as_bytes()).unwrap();
                // Verify the signature is valid
                let public_key = signer_clone.public_key();
                assert!(
                    signature
                        .verify(msg.as_bytes(), public_key.as_bytes())
                        .is_ok()
                );
                signature
            });
            handles.push(handle);
        }

        // Collect all results
        let signatures: Vec<_> =
            handles.into_iter().map(|h| h.join().unwrap()).collect();

        // All signatures should be valid
        assert_eq!(signatures.len(), 10);

        // Each signature should be different (different messages)
        for i in 0..signatures.len() {
            for j in i + 1..signatures.len() {
                assert_ne!(
                    signatures[i], signatures[j],
                    "Signatures for different messages should be different"
                );
            }
        }
    }

    #[test]
    fn test_send_sync_traits() {
        // This test verifies that Ed25519Signer implements Send + Sync
        // which is required for thread safety
        fn assert_send<T: Send>() {}
        fn assert_sync<T: Sync>() {}

        assert_send::<Ed25519Signer>();
        assert_sync::<Ed25519Signer>();
    }

    #[test]
    fn test_concurrent_key_generation() {
        use std::sync::Arc;
        use std::sync::atomic::{AtomicUsize, Ordering};
        use std::thread;

        let counter = Arc::new(AtomicUsize::new(0));
        let mut handles = vec![];

        // Generate keys concurrently from multiple threads
        for _ in 0..5 {
            let counter_clone = Arc::clone(&counter);

            let handle = thread::spawn(move || {
                let signer = Ed25519Signer::generate().unwrap();

                // Test that the key works
                let message = b"test";
                let signature = signer.sign(message).unwrap();
                let public_key = signer.public_key();
                assert!(
                    signature.verify(message, public_key.as_bytes()).is_ok()
                );

                counter_clone.fetch_add(1, Ordering::SeqCst);
            });
            handles.push(handle);
        }

        // Wait for all threads
        for handle in handles {
            handle.join().unwrap();
        }

        assert_eq!(counter.load(Ordering::SeqCst), 5);
    }

    #[test]
    fn test_clone_shares_arc() {
        // Test that cloning shares the Arc, not duplicating encrypted data
        let signer = Ed25519Signer::generate().unwrap();
        let signer_clone = signer.clone();

        // Both should have the same public key
        assert_eq!(signer.public_key_bytes(), signer_clone.public_key_bytes());

        // Both should be able to sign
        let message = b"test message";
        let sig1 = signer.sign(message).unwrap();
        let sig2 = signer_clone.sign(message).unwrap();

        // Signatures should be identical (same key, same message, deterministic)
        assert_eq!(sig1, sig2);

        // Verify Arc is shared (strong count should be 2)
        if let Some(ref secret) = signer.secret_key {
            assert_eq!(Arc::strong_count(secret), 2);
        }
    }

    #[test]
    fn test_clone_verification_only() {
        // Test cloning a verification-only instance (no secret key)
        let full_signer = Ed25519Signer::generate().unwrap();
        let verifier =
            Ed25519Signer::from_public_key(&full_signer.public_key_bytes())
                .unwrap();

        // Clone the verification-only instance
        let verifier_clone = verifier.clone();

        // Both should have the same public key
        assert_eq!(
            verifier.public_key_bytes(),
            verifier_clone.public_key_bytes()
        );

        // Neither should be able to sign
        let message = b"test";
        assert!(verifier.sign(message).is_err());
        assert!(verifier_clone.sign(message).is_err());

        // Both should have None for secret_key
        assert!(verifier.secret_key.is_none());
        assert!(verifier_clone.secret_key.is_none());
    }
}