auths_crypto/
ring_provider.rs1use async_trait::async_trait;
2
3use crate::provider::{CryptoError, CryptoProvider, ED25519_PUBLIC_KEY_LEN, SecureSeed};
4use ring::rand::SystemRandom;
5use ring::signature::{ED25519, Ed25519KeyPair, KeyPair, UnparsedPublicKey};
6
7pub struct RingCryptoProvider;
20
21#[async_trait]
22impl CryptoProvider for RingCryptoProvider {
23 async fn verify_ed25519(
24 &self,
25 pubkey: &[u8],
26 message: &[u8],
27 signature: &[u8],
28 ) -> Result<(), CryptoError> {
29 if pubkey.len() != ED25519_PUBLIC_KEY_LEN {
30 return Err(CryptoError::InvalidKeyLength {
31 expected: ED25519_PUBLIC_KEY_LEN,
32 actual: pubkey.len(),
33 });
34 }
35
36 let pubkey = pubkey.to_vec();
37 let message = message.to_vec();
38 let signature = signature.to_vec();
39
40 tokio::task::spawn_blocking(move || {
41 let peer_public_key = UnparsedPublicKey::new(&ED25519, &pubkey);
42 peer_public_key
43 .verify(&message, &signature)
44 .map_err(|_| CryptoError::InvalidSignature)
45 })
46 .await
47 .map_err(|_| CryptoError::OperationFailed("Verification task panicked".into()))?
48 }
49
50 async fn sign_ed25519(
51 &self,
52 seed: &SecureSeed,
53 message: &[u8],
54 ) -> Result<Vec<u8>, CryptoError> {
55 let seed_bytes = *seed.as_bytes();
56 let message = message.to_vec();
57
58 tokio::task::spawn_blocking(move || {
61 let keypair = Ed25519KeyPair::from_seed_unchecked(&seed_bytes)
62 .map_err(|e| CryptoError::InvalidPrivateKey(format!("{e}")))?;
63 Ok(keypair.sign(&message).as_ref().to_vec())
64 })
65 .await
66 .map_err(|_| CryptoError::OperationFailed("Signing task panicked".into()))?
67 }
68
69 async fn generate_ed25519_keypair(&self) -> Result<(SecureSeed, [u8; 32]), CryptoError> {
70 tokio::task::spawn_blocking(move || {
71 let rng = SystemRandom::new();
72 let pkcs8_doc = Ed25519KeyPair::generate_pkcs8(&rng)
73 .map_err(|_| CryptoError::OperationFailed("Key generation failed".into()))?;
74 let keypair = Ed25519KeyPair::from_pkcs8(pkcs8_doc.as_ref())
75 .map_err(|e| CryptoError::OperationFailed(format!("Parse generated key: {e}")))?;
76
77 let public_key: [u8; 32] = keypair
78 .public_key()
79 .as_ref()
80 .try_into()
81 .map_err(|_| CryptoError::OperationFailed("Public key not 32 bytes".into()))?;
82
83 let pkcs8_bytes = pkcs8_doc.as_ref();
86 let seed: [u8; 32] = pkcs8_bytes[16..48]
87 .try_into()
88 .map_err(|_| CryptoError::OperationFailed("Seed extraction failed".into()))?;
89
90 Ok((SecureSeed::new(seed), public_key))
91 })
92 .await
93 .map_err(|_| CryptoError::OperationFailed("Keygen task panicked".into()))?
94 }
95
96 async fn ed25519_public_key_from_seed(
97 &self,
98 seed: &SecureSeed,
99 ) -> Result<[u8; 32], CryptoError> {
100 let seed_bytes = *seed.as_bytes();
101
102 tokio::task::spawn_blocking(move || {
103 let keypair = Ed25519KeyPair::from_seed_unchecked(&seed_bytes)
104 .map_err(|e| CryptoError::InvalidPrivateKey(format!("{e}")))?;
105 keypair
106 .public_key()
107 .as_ref()
108 .try_into()
109 .map_err(|_| CryptoError::OperationFailed("Public key not 32 bytes".into()))
110 })
111 .await
112 .map_err(|_| CryptoError::OperationFailed("Public key extraction panicked".into()))?
113 }
114}