1use super::AuraEffectSystem;
2use async_trait::async_trait;
3use aura_core::crypto::single_signer::SigningMode;
4use aura_core::effects::crypto::{
5 FrostKeyGenResult, FrostSigningPackage, KeyDerivationContext, KeyGenerationMethod,
6 SigningKeyGenResult,
7};
8use aura_core::effects::{
9 CryptoCoreEffects, CryptoError, CryptoExtendedEffects, RandomCoreEffects,
10 SecureStorageCapability, SecureStorageEffects, SecureStorageLocation,
11};
12use aura_core::{AuraError, AuthorityId};
13
14#[async_trait]
16impl RandomCoreEffects for AuraEffectSystem {
17 #[allow(clippy::disallowed_methods)]
18 async fn random_bytes(&self, len: usize) -> Vec<u8> {
19 self.crypto.random_bytes(len)
20 }
21
22 #[allow(clippy::disallowed_methods)]
23 async fn random_bytes_32(&self) -> [u8; 32] {
24 self.crypto.random_32_bytes()
25 }
26
27 #[allow(clippy::disallowed_methods)]
28 async fn random_u64(&self) -> u64 {
29 self.crypto.random_u64()
30 }
31}
32
33#[async_trait]
35impl CryptoCoreEffects for AuraEffectSystem {
36 async fn kdf_derive(
37 &self,
38 ikm: &[u8],
39 salt: &[u8],
40 info: &[u8],
41 output_len: u32,
42 ) -> Result<Vec<u8>, CryptoError> {
43 self.crypto
44 .handler()
45 .kdf_derive(ikm, salt, info, output_len)
46 .await
47 }
48
49 async fn derive_key(
50 &self,
51 master_key: &[u8],
52 context: &KeyDerivationContext,
53 ) -> Result<Vec<u8>, CryptoError> {
54 self.crypto.handler().derive_key(master_key, context).await
55 }
56
57 async fn ed25519_generate_keypair(&self) -> Result<(Vec<u8>, Vec<u8>), CryptoError> {
58 self.crypto.handler().ed25519_generate_keypair().await
59 }
60
61 async fn ed25519_sign(
62 &self,
63 message: &[u8],
64 private_key: &[u8],
65 ) -> Result<Vec<u8>, CryptoError> {
66 self.crypto
67 .handler()
68 .ed25519_sign(message, private_key)
69 .await
70 }
71
72 async fn ed25519_verify(
73 &self,
74 message: &[u8],
75 signature: &[u8],
76 public_key: &[u8],
77 ) -> Result<bool, CryptoError> {
78 self.crypto
79 .handler()
80 .ed25519_verify(message, signature, public_key)
81 .await
82 }
83
84 fn is_simulated(&self) -> bool {
85 self.crypto.handler().is_simulated()
86 }
87
88 fn crypto_capabilities(&self) -> Vec<String> {
89 self.crypto.handler().crypto_capabilities()
90 }
91
92 fn constant_time_eq(&self, a: &[u8], b: &[u8]) -> bool {
93 self.crypto.handler().constant_time_eq(a, b)
94 }
95
96 fn secure_zero(&self, data: &mut [u8]) {
97 self.crypto.handler().secure_zero(data);
98 }
99}
100
101#[async_trait]
103impl CryptoExtendedEffects for AuraEffectSystem {
104 async fn frost_generate_keys(
105 &self,
106 threshold: u16,
107 max_signers: u16,
108 ) -> Result<FrostKeyGenResult, CryptoError> {
109 self.crypto
110 .handler()
111 .frost_generate_keys(threshold, max_signers)
112 .await
113 }
114
115 async fn frost_generate_nonces(&self, key_package: &[u8]) -> Result<Vec<u8>, CryptoError> {
116 self.crypto
117 .handler()
118 .frost_generate_nonces(key_package)
119 .await
120 }
121
122 async fn frost_create_signing_package(
123 &self,
124 message: &[u8],
125 nonces: &[Vec<u8>],
126 participants: &[u16],
127 public_key_package: &[u8],
128 ) -> Result<FrostSigningPackage, CryptoError> {
129 self.crypto
130 .handler()
131 .frost_create_signing_package(message, nonces, participants, public_key_package)
132 .await
133 }
134
135 async fn frost_sign_share(
136 &self,
137 signing_package: &FrostSigningPackage,
138 key_share: &[u8],
139 nonces: &[u8],
140 ) -> Result<Vec<u8>, CryptoError> {
141 self.crypto
142 .handler()
143 .frost_sign_share(signing_package, key_share, nonces)
144 .await
145 }
146
147 async fn frost_aggregate_signatures(
148 &self,
149 signing_package: &FrostSigningPackage,
150 signature_shares: &[Vec<u8>],
151 ) -> Result<Vec<u8>, CryptoError> {
152 self.crypto
153 .handler()
154 .frost_aggregate_signatures(signing_package, signature_shares)
155 .await
156 }
157
158 async fn frost_verify(
159 &self,
160 message: &[u8],
161 signature: &[u8],
162 public_key: &[u8],
163 ) -> Result<bool, CryptoError> {
164 self.crypto
165 .handler()
166 .frost_verify(message, signature, public_key)
167 .await
168 }
169
170 async fn ed25519_public_key(&self, private_key: &[u8]) -> Result<Vec<u8>, CryptoError> {
171 self.crypto.handler().ed25519_public_key(private_key).await
172 }
173
174 async fn convert_ed25519_to_x25519_public(
175 &self,
176 ed25519_public_key: &[u8],
177 ) -> Result<[u8; 32], CryptoError> {
178 self.crypto
179 .handler()
180 .convert_ed25519_to_x25519_public(ed25519_public_key)
181 .await
182 }
183
184 async fn convert_ed25519_to_x25519_private(
185 &self,
186 ed25519_private_key: &[u8],
187 ) -> Result<[u8; 32], CryptoError> {
188 self.crypto
189 .handler()
190 .convert_ed25519_to_x25519_private(ed25519_private_key)
191 .await
192 }
193
194 async fn chacha20_encrypt(
195 &self,
196 plaintext: &[u8],
197 key: &[u8; 32],
198 nonce: &[u8; 12],
199 ) -> Result<Vec<u8>, CryptoError> {
200 self.crypto
201 .handler()
202 .chacha20_encrypt(plaintext, key, nonce)
203 .await
204 }
205
206 async fn chacha20_decrypt(
207 &self,
208 ciphertext: &[u8],
209 key: &[u8; 32],
210 nonce: &[u8; 12],
211 ) -> Result<Vec<u8>, CryptoError> {
212 self.crypto
213 .handler()
214 .chacha20_decrypt(ciphertext, key, nonce)
215 .await
216 }
217
218 async fn aes_gcm_encrypt(
219 &self,
220 plaintext: &[u8],
221 key: &[u8; 32],
222 nonce: &[u8; 12],
223 ) -> Result<Vec<u8>, CryptoError> {
224 self.crypto
225 .handler()
226 .aes_gcm_encrypt(plaintext, key, nonce)
227 .await
228 }
229
230 async fn aes_gcm_decrypt(
231 &self,
232 ciphertext: &[u8],
233 key: &[u8; 32],
234 nonce: &[u8; 12],
235 ) -> Result<Vec<u8>, CryptoError> {
236 self.crypto
237 .handler()
238 .aes_gcm_decrypt(ciphertext, key, nonce)
239 .await
240 }
241
242 async fn frost_rotate_keys(
243 &self,
244 old_shares: &[Vec<u8>],
245 old_threshold: u16,
246 new_threshold: u16,
247 new_max_signers: u16,
248 ) -> Result<FrostKeyGenResult, CryptoError> {
249 self.crypto
250 .handler()
251 .frost_rotate_keys(old_shares, old_threshold, new_threshold, new_max_signers)
252 .await
253 }
254
255 async fn generate_signing_keys(
256 &self,
257 threshold: u16,
258 max_signers: u16,
259 ) -> Result<SigningKeyGenResult, CryptoError> {
260 self.crypto
261 .handler()
262 .generate_signing_keys(threshold, max_signers)
263 .await
264 }
265
266 async fn generate_signing_keys_with(
267 &self,
268 method: KeyGenerationMethod,
269 threshold: u16,
270 max_signers: u16,
271 ) -> Result<SigningKeyGenResult, CryptoError> {
272 self.crypto
273 .handler()
274 .generate_signing_keys_with(method, threshold, max_signers)
275 .await
276 }
277
278 async fn sign_with_key(
279 &self,
280 message: &[u8],
281 key_package: &[u8],
282 mode: SigningMode,
283 ) -> Result<Vec<u8>, CryptoError> {
284 self.crypto
285 .handler()
286 .sign_with_key(message, key_package, mode)
287 .await
288 }
289
290 async fn verify_signature(
291 &self,
292 message: &[u8],
293 signature: &[u8],
294 public_key_package: &[u8],
295 mode: SigningMode,
296 ) -> Result<bool, CryptoError> {
297 self.crypto
298 .handler()
299 .verify_signature(message, signature, public_key_package, mode)
300 .await
301 }
302}
303
304#[async_trait]
306impl aura_core::effects::ThresholdSigningEffects for AuraEffectSystem {
307 async fn bootstrap_authority(&self, authority: &AuthorityId) -> Result<Vec<u8>, AuraError> {
308 let signing_keys = self.crypto.handler().generate_signing_keys(1, 1).await?;
310
311 let key_prefix = match signing_keys.mode {
314 SigningMode::SingleSigner => "signing_keys",
315 SigningMode::Threshold => "frost_keys",
316 };
317 let location = SecureStorageLocation::with_sub_key(
318 key_prefix,
319 format!("{}/0", authority), "1", );
322 let caps = vec![SecureStorageCapability::Write];
323 self.crypto
324 .secure_storage()
325 .secure_store(&location, &signing_keys.key_packages[0], &caps)
326 .await?;
327
328 let pub_location = SecureStorageLocation::new(
330 format!("{}_public", key_prefix),
331 format!("{}/0", authority),
332 );
333 self.crypto
334 .secure_storage()
335 .secure_store(&pub_location, &signing_keys.public_key_package, &caps)
336 .await?;
337
338 self.store_threshold_config_metadata(
340 authority,
341 0, 1, 1, &[], aura_core::threshold::AgreementMode::Provisional,
346 )
347 .await?;
348
349 self.bootstrap_biscuit_tokens(authority).await?;
351
352 Ok(signing_keys.public_key_package)
353 }
354
355 async fn sign(
356 &self,
357 context: aura_core::threshold::SigningContext,
358 ) -> Result<aura_core::threshold::ThresholdSignature, AuraError> {
359 let message = serde_json::to_vec(&context.operation)
361 .map_err(|e| AuraError::internal(format!("Failed to serialize operation: {}", e)))?;
362
363 let current_epoch = self.get_current_epoch(&context.authority).await;
365 let location = SecureStorageLocation::with_sub_key(
366 "frost_keys",
367 format!("{}/{}", context.authority, current_epoch),
368 "1",
369 );
370 let caps = vec![SecureStorageCapability::Read];
371 let key_package = self
372 .crypto
373 .secure_storage()
374 .secure_retrieve(&location, &caps)
375 .await?;
376
377 let pub_location = SecureStorageLocation::new(
379 "frost_public_keys",
380 format!("{}/{}", context.authority, current_epoch),
381 );
382 let public_key_package = self
383 .crypto
384 .secure_storage()
385 .secure_retrieve(&pub_location, &caps)
386 .await
387 .unwrap_or_else(|_| vec![0u8; 32]); let nonces = self
391 .crypto
392 .handler()
393 .frost_generate_nonces(&key_package)
394 .await
395 .map_err(|e| AuraError::internal(format!("Nonce generation failed: {}", e)))?;
396
397 let participants = vec![1u16];
399 let signing_package = self
400 .crypto
401 .handler()
402 .frost_create_signing_package(
403 &message,
404 std::slice::from_ref(&nonces),
405 &participants,
406 &public_key_package,
407 )
408 .await
409 .map_err(|e| AuraError::internal(format!("Signing package creation failed: {}", e)))?;
410
411 let share = self
413 .crypto
414 .handler()
415 .frost_sign_share(&signing_package, &key_package, &nonces)
416 .await
417 .map_err(|e| AuraError::internal(format!("Signature share creation failed: {}", e)))?;
418
419 let signature = self
421 .crypto
422 .handler()
423 .frost_aggregate_signatures(&signing_package, &[share])
424 .await
425 .map_err(|e| AuraError::internal(format!("Signature aggregation failed: {}", e)))?;
426
427 Ok(aura_core::threshold::ThresholdSignature::single_signer(
428 signature,
429 public_key_package,
430 current_epoch,
431 ))
432 }
433
434 async fn threshold_config(
435 &self,
436 authority: &AuthorityId,
437 ) -> Option<aura_core::threshold::ThresholdConfig> {
438 let current_epoch = self.get_current_epoch(authority).await;
440
441 self.get_threshold_config_metadata(authority, current_epoch)
443 .await
444 .map(|metadata| aura_core::threshold::ThresholdConfig {
445 threshold: metadata.threshold_k,
446 total_participants: metadata.total_n,
447 })
448 }
449
450 async fn threshold_state(
451 &self,
452 authority: &AuthorityId,
453 ) -> Option<aura_core::threshold::ThresholdState> {
454 let current_epoch = self.get_current_epoch(authority).await;
456
457 self.get_threshold_config_metadata(authority, current_epoch)
459 .await
460 .map(|metadata| aura_core::threshold::ThresholdState {
461 epoch: current_epoch,
462 threshold: metadata.threshold_k,
463 total_participants: metadata.total_n,
464 participants: metadata.resolved_participants(),
465 agreement_mode: metadata.agreement_mode,
466 })
467 }
468
469 async fn has_signing_capability(&self, authority: &AuthorityId) -> bool {
470 let current_epoch = self.get_current_epoch(authority).await;
471 let location = SecureStorageLocation::with_sub_key(
472 "frost_keys",
473 format!("{}/{}", authority, current_epoch),
474 "1",
475 );
476 self.crypto
477 .secure_storage()
478 .secure_exists(&location)
479 .await
480 .unwrap_or(false)
481 }
482
483 async fn public_key_package(&self, authority: &AuthorityId) -> Option<Vec<u8>> {
484 let location = SecureStorageLocation::new("frost_public_keys", format!("{}/0", authority));
485 let caps = vec![SecureStorageCapability::Read];
486 self.crypto
487 .secure_storage()
488 .secure_retrieve(&location, &caps)
489 .await
490 .ok()
491 }
492
493 async fn rotate_keys(
494 &self,
495 authority: &AuthorityId,
496 new_threshold: u16,
497 new_total_participants: u16,
498 participants: &[aura_core::threshold::ParticipantIdentity],
499 ) -> Result<(u64, Vec<Vec<u8>>, Vec<u8>), AuraError> {
500 tracing::info!(
501 ?authority,
502 new_threshold,
503 new_total_participants,
504 num_participants = participants.len(),
505 "Rotating threshold keys via AuraEffectSystem"
506 );
507
508 if participants.len() != new_total_participants as usize {
510 return Err(AuraError::invalid(format!(
511 "Participant count ({}) must match total_participants ({})",
512 participants.len(),
513 new_total_participants
514 )));
515 }
516
517 let current_epoch = self.get_current_epoch(authority).await;
519 let new_epoch = current_epoch + 1;
520 tracing::debug!(
521 ?authority,
522 current_epoch,
523 new_epoch,
524 "Rotating keys from epoch {} to {}",
525 current_epoch,
526 new_epoch
527 );
528
529 let key_result = if new_threshold >= 2 {
531 self.crypto
532 .handler()
533 .frost_rotate_keys(&[], 0, new_threshold, new_total_participants)
534 .await?
535 } else {
536 let result = self
537 .crypto
538 .handler()
539 .generate_signing_keys(new_threshold, new_total_participants)
540 .await?;
541 FrostKeyGenResult {
542 key_packages: result.key_packages,
543 public_key_package: result.public_key_package,
544 }
545 };
546
547 let caps = vec![
549 SecureStorageCapability::Read,
550 SecureStorageCapability::Write,
551 ];
552 for (participant, key_package) in participants.iter().zip(key_result.key_packages.iter()) {
553 let location = SecureStorageLocation::with_sub_key(
554 "participant_shares",
555 format!("{}/{}", authority, new_epoch),
556 participant.storage_key(),
557 );
558 self.crypto
559 .secure_storage()
560 .secure_store(&location, key_package, &caps)
561 .await?;
562 }
563
564 let pub_location = SecureStorageLocation::with_sub_key(
566 "threshold_pubkey",
567 format!("{}", authority),
568 format!("{}", new_epoch),
569 );
570 self.crypto
571 .secure_storage()
572 .secure_store(&pub_location, &key_result.public_key_package, &caps)
573 .await?;
574
575 self.store_threshold_config_metadata(
577 authority,
578 new_epoch,
579 new_threshold,
580 new_total_participants,
581 participants,
582 aura_core::threshold::AgreementMode::CoordinatorSoftSafe,
583 )
584 .await?;
585
586 Ok((
587 new_epoch,
588 key_result.key_packages,
589 key_result.public_key_package,
590 ))
591 }
592
593 async fn commit_key_rotation(
594 &self,
595 authority: &AuthorityId,
596 new_epoch: u64,
597 ) -> Result<(), AuraError> {
598 tracing::info!(
599 ?authority,
600 new_epoch,
601 "Committing key rotation via AuraEffectSystem"
602 );
603 self.set_current_epoch(authority, new_epoch).await?;
605 tracing::debug!(
606 ?authority,
607 new_epoch,
608 "Epoch state updated - new keys are now active"
609 );
610 Ok(())
611 }
612
613 async fn rollback_key_rotation(
614 &self,
615 authority: &AuthorityId,
616 failed_epoch: u64,
617 ) -> Result<(), AuraError> {
618 tracing::warn!(
619 ?authority,
620 failed_epoch,
621 "Rolling back key rotation via AuraEffectSystem"
622 );
623 self.delete_epoch_keys(authority, failed_epoch).await?;
625 tracing::info!(
626 ?authority,
627 failed_epoch,
628 "Successfully deleted orphaned keys from failed rotation"
629 );
630 Ok(())
631 }
632}