Skip to main content

aura_core/effects/
crypto.rs

1//! Cryptographic effects trait definitions
2//!
3//! This module defines the trait interfaces for cryptographic operations.
4//! Actual cryptographic implementations are provided by aura-crypto crate.
5//! Effect handlers that integrate aura-crypto are provided by aura-protocol handlers.
6//!
7//! # Effect Classification
8//!
9//! - **Category**: Infrastructure Effect
10//! - **Implementation**: `aura-effects` (Layer 3)
11//! - **Usage**: All crates needing cryptographic operations (signing, hashing, key derivation)
12//!
13//! This is an infrastructure effect that must be implemented in `aura-effects`
14//! with stateless handlers. Domain crates should not implement this trait directly
15//! but rather use it via dependency injection.
16
17use crate::effects::random::RandomCoreEffects;
18use crate::types::identifiers::DeviceId;
19use crate::{AccountId, AuraError};
20use async_trait::async_trait;
21use serde::{Deserialize, Serialize};
22
23pub const MAX_KEY_PACKAGE_BYTES: usize = 65_536;
24pub const MAX_PUBLIC_KEY_PACKAGE_BYTES: usize = 65_536;
25pub const MAX_SIGNING_MESSAGE_BYTES: usize = 65_536;
26pub const MAX_SIGNING_PACKAGE_BYTES: usize = 65_536;
27
28/// Cryptographic operation error
29pub type CryptoError = AuraError;
30
31/// Key derivation context for deterministic key generation
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct KeyDerivationContext {
34    /// Application identifier
35    pub app_id: String,
36    /// Context string for key derivation
37    pub context: String,
38    /// Derivation path components
39    pub derivation_path: Vec<u32>,
40    /// Account identifier
41    pub account_id: AccountId,
42    /// Device identifier
43    pub device_id: DeviceId,
44}
45
46/// FROST key generation result containing both individual key packages and the group public key
47#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct FrostKeyGenResult {
49    /// Individual key packages for each participant
50    pub key_packages: Vec<Vec<u8>>,
51    /// Group public key package needed for signature aggregation and verification
52    pub public_key_package: Vec<u8>,
53}
54
55/// FROST signing package for threshold signatures
56#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct FrostSigningPackage {
58    /// Message to be signed
59    pub message: Vec<u8>,
60    /// Signing package data
61    pub package: Vec<u8>,
62    /// Participant identifiers
63    pub participants: Vec<u16>,
64    /// Public key package needed for aggregation
65    pub public_key_package: Vec<u8>,
66}
67
68// Re-export SigningMode from crypto module for convenience
69pub use crate::crypto::single_signer::SigningMode;
70
71/// Result of signing key generation (unified for single-signer and threshold).
72///
73/// This type is returned by `generate_signing_keys()` and contains everything
74/// needed to store and use the generated keys.
75#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct SigningKeyGenResult {
77    /// Key packages (one per participant).
78    ///
79    /// For single-signer: contains one `SingleSignerKeyPackage` serialized.
80    /// For threshold: contains FROST `KeyPackage` for each participant.
81    pub key_packages: Vec<Vec<u8>>,
82
83    /// Public key package for verification.
84    ///
85    /// For single-signer: contains `SingleSignerPublicKeyPackage` serialized.
86    /// For threshold: contains FROST `PublicKeyPackage` serialized.
87    pub public_key_package: Vec<u8>,
88
89    /// Which signing mode was used.
90    ///
91    /// This determines which signing/verification algorithm to use.
92    pub mode: SigningMode,
93}
94
95/// Supported key generation methods for threshold signing.
96#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
97pub enum KeyGenerationMethod {
98    /// Single-signer Ed25519 (K1).
99    SingleSigner,
100    /// Dealer-based FROST key generation (K2).
101    DealerBased,
102}
103
104/// Core cryptographic effects interface
105///
106/// This trait defines cryptographic operations for the Aura effects system.
107/// The actual cryptographic primitives are implemented in aura-crypto crate.
108/// Effect handlers are implemented in aura-protocol handlers for different environments:
109/// - Production: Real cryptographic operations using aura-crypto
110/// - Testing: Deterministic mock operations
111/// - Simulation: Controlled cryptographic scenarios
112///
113/// CryptoCoreEffects inherits from RandomCoreEffects to ensure all randomness is deterministic
114/// and controllable for simulation purposes.
115///
116/// # Stability: STABLE
117/// This is a core stable API with semver guarantees. Breaking changes require major version bump.
118#[async_trait]
119pub trait CryptoCoreEffects: RandomCoreEffects + Send + Sync {
120    // Note: Hashing is NOT an algebraic effect - it's a pure operation.
121    // Use aura_core::hash::hash() for synchronous hashing instead.
122    // See docs/002_system_architecture.md for design rationale.
123
124    // Note: Random methods (random_bytes, random_bytes_32, random_range)
125    // are inherited from RandomEffects trait
126
127    // ====== Key Derivation ======
128
129    /// Deterministic key derivation with explicit salt and info inputs.
130    async fn kdf_derive(
131        &self,
132        ikm: &[u8],
133        salt: &[u8],
134        info: &[u8],
135        output_len: u32,
136    ) -> Result<Vec<u8>, CryptoError>;
137
138    /// Derive key using context for deterministic derivation
139    async fn derive_key(
140        &self,
141        master_key: &[u8],
142        context: &KeyDerivationContext,
143    ) -> Result<Vec<u8>, CryptoError>;
144
145    // ====== Ed25519 Signatures ======
146
147    /// Generate Ed25519 keypair
148    async fn ed25519_generate_keypair(&self) -> Result<(Vec<u8>, Vec<u8>), CryptoError>;
149
150    /// Sign with Ed25519 private key
151    async fn ed25519_sign(
152        &self,
153        message: &[u8],
154        private_key: &[u8],
155    ) -> Result<Vec<u8>, CryptoError>;
156
157    /// Verify Ed25519 signature
158    async fn ed25519_verify(
159        &self,
160        message: &[u8],
161        signature: &[u8],
162        public_key: &[u8],
163    ) -> Result<bool, CryptoError>;
164
165    /// Check if this crypto handler supports simulation mode
166    fn is_simulated(&self) -> bool;
167
168    /// Get crypto implementation capabilities
169    fn crypto_capabilities(&self) -> Vec<String>;
170
171    /// Constant-time comparison for cryptographic values
172    fn constant_time_eq(&self, a: &[u8], b: &[u8]) -> bool;
173
174    /// Securely zero memory
175    fn secure_zero(&self, data: &mut [u8]);
176}
177
178/// Optional cryptographic effects that build on the core interface.
179#[async_trait]
180pub trait CryptoExtendedEffects: CryptoCoreEffects + Send + Sync {
181    // ====== Unified Signing Key Generation ======
182
183    async fn generate_signing_keys(
184        &self,
185        threshold: u16,
186        max_signers: u16,
187    ) -> Result<SigningKeyGenResult, CryptoError> {
188        let _ = (threshold, max_signers);
189        Err(AuraError::crypto("generate_signing_keys not supported"))
190    }
191
192    /// Generate signing keys with an explicit method.
193    ///
194    /// - `SingleSigner` uses Ed25519 directly.
195    /// - `DealerBased` uses dealer-based FROST key generation.
196    ///
197    /// Consensus-finalized DKG (K3) is not a CryptoExtendedEffects operation
198    /// and is orchestrated in `aura-consensus`.
199    async fn generate_signing_keys_with(
200        &self,
201        method: KeyGenerationMethod,
202        threshold: u16,
203        max_signers: u16,
204    ) -> Result<SigningKeyGenResult, CryptoError> {
205        let _ = method;
206        self.generate_signing_keys(threshold, max_signers).await
207    }
208
209    async fn sign_with_key(
210        &self,
211        message: &[u8],
212        key_package: &[u8],
213        mode: SigningMode,
214    ) -> Result<Vec<u8>, CryptoError> {
215        let _ = (message, key_package, mode);
216        Err(AuraError::crypto("sign_with_key not supported"))
217    }
218
219    async fn verify_signature(
220        &self,
221        message: &[u8],
222        signature: &[u8],
223        public_key_package: &[u8],
224        mode: SigningMode,
225    ) -> Result<bool, CryptoError> {
226        let _ = (message, signature, public_key_package, mode);
227        Err(AuraError::crypto("verify_signature not supported"))
228    }
229
230    // ====== FROST Threshold Signatures ======
231
232    async fn frost_generate_keys(
233        &self,
234        threshold: u16,
235        max_signers: u16,
236    ) -> Result<FrostKeyGenResult, CryptoError> {
237        let _ = (threshold, max_signers);
238        Err(AuraError::crypto("frost_generate_keys not supported"))
239    }
240
241    async fn frost_generate_nonces(&self, key_package: &[u8]) -> Result<Vec<u8>, CryptoError> {
242        let _ = key_package;
243        Err(AuraError::crypto("frost_generate_nonces not supported"))
244    }
245
246    async fn frost_create_signing_package(
247        &self,
248        message: &[u8],
249        nonces: &[Vec<u8>],
250        participants: &[u16],
251        public_key_package: &[u8],
252    ) -> Result<FrostSigningPackage, CryptoError> {
253        let _ = (message, nonces, participants, public_key_package);
254        Err(AuraError::crypto(
255            "frost_create_signing_package not supported",
256        ))
257    }
258
259    async fn frost_sign_share(
260        &self,
261        signing_package: &FrostSigningPackage,
262        key_share: &[u8],
263        nonces: &[u8],
264    ) -> Result<Vec<u8>, CryptoError> {
265        let _ = (signing_package, key_share, nonces);
266        Err(AuraError::crypto("frost_sign_share not supported"))
267    }
268
269    async fn frost_aggregate_signatures(
270        &self,
271        signing_package: &FrostSigningPackage,
272        signature_shares: &[Vec<u8>],
273    ) -> Result<Vec<u8>, CryptoError> {
274        let _ = (signing_package, signature_shares);
275        Err(AuraError::crypto(
276            "frost_aggregate_signatures not supported",
277        ))
278    }
279
280    async fn frost_verify(
281        &self,
282        message: &[u8],
283        signature: &[u8],
284        group_public_key: &[u8],
285    ) -> Result<bool, CryptoError> {
286        let _ = (message, signature, group_public_key);
287        Err(AuraError::crypto("frost_verify not supported"))
288    }
289
290    /// Extract public key from Ed25519 private key
291    async fn ed25519_public_key(&self, private_key: &[u8]) -> Result<Vec<u8>, CryptoError> {
292        let _ = private_key;
293        Err(AuraError::crypto("ed25519_public_key not supported"))
294    }
295
296    // ====== Symmetric Encryption ======
297
298    async fn chacha20_encrypt(
299        &self,
300        plaintext: &[u8],
301        key: &[u8; 32],
302        nonce: &[u8; 12],
303    ) -> Result<Vec<u8>, CryptoError> {
304        let _ = (plaintext, key, nonce);
305        Err(AuraError::crypto("chacha20_encrypt not supported"))
306    }
307
308    async fn chacha20_decrypt(
309        &self,
310        ciphertext: &[u8],
311        key: &[u8; 32],
312        nonce: &[u8; 12],
313    ) -> Result<Vec<u8>, CryptoError> {
314        let _ = (ciphertext, key, nonce);
315        Err(AuraError::crypto("chacha20_decrypt not supported"))
316    }
317
318    async fn aes_gcm_encrypt(
319        &self,
320        plaintext: &[u8],
321        key: &[u8; 32],
322        nonce: &[u8; 12],
323    ) -> Result<Vec<u8>, CryptoError> {
324        let _ = (plaintext, key, nonce);
325        Err(AuraError::crypto("aes_gcm_encrypt not supported"))
326    }
327
328    async fn aes_gcm_decrypt(
329        &self,
330        ciphertext: &[u8],
331        key: &[u8; 32],
332        nonce: &[u8; 12],
333    ) -> Result<Vec<u8>, CryptoError> {
334        let _ = (ciphertext, key, nonce);
335        Err(AuraError::crypto("aes_gcm_decrypt not supported"))
336    }
337
338    // ====== Key Rotation & Resharing ======
339
340    async fn frost_rotate_keys(
341        &self,
342        old_shares: &[Vec<u8>],
343        old_threshold: u16,
344        new_threshold: u16,
345        new_max_signers: u16,
346    ) -> Result<FrostKeyGenResult, CryptoError> {
347        let _ = (old_shares, old_threshold, new_threshold, new_max_signers);
348        Err(AuraError::crypto("frost_rotate_keys not supported"))
349    }
350
351    // ====== Key Conversion ======
352
353    /// Convert Ed25519 public key to X25519 (Curve25519) public key for Diffie-Hellman.
354    async fn convert_ed25519_to_x25519_public(
355        &self,
356        ed25519_public_key: &[u8],
357    ) -> Result<[u8; 32], CryptoError> {
358        let _ = ed25519_public_key;
359        Err(AuraError::crypto(
360            "convert_ed25519_to_x25519_public not supported",
361        ))
362    }
363
364    /// Convert Ed25519 private key (seed) to X25519 (Curve25519) private key for Diffie-Hellman.
365    async fn convert_ed25519_to_x25519_private(
366        &self,
367        ed25519_private_key: &[u8],
368    ) -> Result<[u8; 32], CryptoError> {
369        let _ = ed25519_private_key;
370        Err(AuraError::crypto(
371            "convert_ed25519_to_x25519_private not supported",
372        ))
373    }
374}
375
376/// Combined cryptographic effects surface (core + extended).
377pub trait CryptoEffects: CryptoCoreEffects + CryptoExtendedEffects {}
378
379impl<T: CryptoCoreEffects + CryptoExtendedEffects + ?Sized> CryptoEffects for T {}
380
381/// Blanket implementation for Arc<T> where T: CryptoCoreEffects
382/// Note: CryptoCoreEffects inherits RandomCoreEffects, and Arc<T> gets RandomCoreEffects from the blanket impl in random.rs
383#[async_trait]
384impl<T: CryptoCoreEffects + ?Sized> CryptoCoreEffects for std::sync::Arc<T> {
385    async fn kdf_derive(
386        &self,
387        ikm: &[u8],
388        salt: &[u8],
389        info: &[u8],
390        output_len: u32,
391    ) -> Result<Vec<u8>, CryptoError> {
392        (**self).kdf_derive(ikm, salt, info, output_len).await
393    }
394
395    async fn derive_key(
396        &self,
397        master_key: &[u8],
398        context: &KeyDerivationContext,
399    ) -> Result<Vec<u8>, CryptoError> {
400        (**self).derive_key(master_key, context).await
401    }
402
403    async fn ed25519_generate_keypair(&self) -> Result<(Vec<u8>, Vec<u8>), CryptoError> {
404        (**self).ed25519_generate_keypair().await
405    }
406
407    async fn ed25519_sign(
408        &self,
409        message: &[u8],
410        private_key: &[u8],
411    ) -> Result<Vec<u8>, CryptoError> {
412        (**self).ed25519_sign(message, private_key).await
413    }
414
415    async fn ed25519_verify(
416        &self,
417        message: &[u8],
418        signature: &[u8],
419        public_key: &[u8],
420    ) -> Result<bool, CryptoError> {
421        (**self)
422            .ed25519_verify(message, signature, public_key)
423            .await
424    }
425    fn is_simulated(&self) -> bool {
426        (**self).is_simulated()
427    }
428
429    fn crypto_capabilities(&self) -> Vec<String> {
430        (**self).crypto_capabilities()
431    }
432
433    fn constant_time_eq(&self, a: &[u8], b: &[u8]) -> bool {
434        (**self).constant_time_eq(a, b)
435    }
436
437    fn secure_zero(&self, data: &mut [u8]) {
438        (**self).secure_zero(data);
439    }
440}