actr_platform_native/
crypto.rs1use async_trait::async_trait;
4use ed25519_dalek::{PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH, Signature, VerifyingKey};
5use sha2::{Digest, Sha256};
6
7use actr_platform_traits::{CryptoProvider, PlatformError};
8
9pub struct NativeCryptoProvider;
11
12#[async_trait]
13impl CryptoProvider for NativeCryptoProvider {
14 async fn ed25519_verify(
15 &self,
16 public_key: &[u8],
17 message: &[u8],
18 signature: &[u8],
19 ) -> Result<(), PlatformError> {
20 let pubkey_bytes: [u8; PUBLIC_KEY_LENGTH] = public_key.try_into().map_err(|_| {
21 PlatformError::Crypto(format!(
22 "Ed25519 public key must be {PUBLIC_KEY_LENGTH} bytes"
23 ))
24 })?;
25
26 let verifying_key = VerifyingKey::from_bytes(&pubkey_bytes)
27 .map_err(|e| PlatformError::Crypto(format!("invalid Ed25519 public key: {e}")))?;
28
29 let sig_bytes: [u8; SIGNATURE_LENGTH] = signature.try_into().map_err(|_| {
30 PlatformError::Crypto(format!(
31 "Ed25519 signature must be {SIGNATURE_LENGTH} bytes"
32 ))
33 })?;
34 let sig = Signature::from_bytes(&sig_bytes);
35
36 verifying_key
37 .verify_strict(message, &sig)
38 .map_err(|e| PlatformError::Crypto(format!("Ed25519 verification failed: {e}")))
39 }
40
41 async fn sha256(&self, data: &[u8]) -> Result<[u8; 32], PlatformError> {
42 let mut hasher = Sha256::new();
43 hasher.update(data);
44 Ok(hasher.finalize().into())
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use ed25519_dalek::{Signer, SigningKey};
52 use rand::rngs::OsRng;
53
54 #[tokio::test]
55 async fn sha256_produces_correct_hash() {
56 let provider = NativeCryptoProvider;
57 let hash = provider.sha256(b"hello").await.unwrap();
58 let expected = [
60 0x2c, 0xf2, 0x4d, 0xba, 0x5f, 0xb0, 0xa3, 0x0e, 0x26, 0xe8, 0x3b, 0x2a, 0xc5, 0xb9,
61 0xe2, 0x9e, 0x1b, 0x16, 0x1e, 0x5c, 0x1f, 0xa7, 0x42, 0x5e, 0x73, 0x04, 0x33, 0x62,
62 0x93, 0x8b, 0x98, 0x24,
63 ];
64 assert_eq!(hash, expected);
65 }
66
67 #[tokio::test]
68 async fn ed25519_verify_valid_signature() {
69 let provider = NativeCryptoProvider;
70 let signing_key = SigningKey::generate(&mut OsRng);
71 let verifying_key = signing_key.verifying_key();
72
73 let message = b"test message";
74 let signature = signing_key.sign(message);
75
76 let result = provider
77 .ed25519_verify(verifying_key.as_bytes(), message, &signature.to_bytes())
78 .await;
79 assert!(result.is_ok());
80 }
81
82 #[tokio::test]
83 async fn ed25519_verify_rejects_bad_signature() {
84 let provider = NativeCryptoProvider;
85 let signing_key = SigningKey::generate(&mut OsRng);
86 let verifying_key = signing_key.verifying_key();
87
88 let message = b"test message";
89 let bad_sig = [0u8; 64];
90
91 let result = provider
92 .ed25519_verify(verifying_key.as_bytes(), message, &bad_sig)
93 .await;
94 assert!(result.is_err());
95 }
96}