1use x25519_dalek::{StaticSecret, PublicKey};
2use ed25519_dalek::{SigningKey, VerifyingKey, Signature, Signer, Verifier};
3use rand::rngs::OsRng;
4
5#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
6pub struct KeyPair {
7 pub priv_key: Vec<u8>,
8 pub pub_key: Vec<u8>,
9}
10
11#[allow(dead_code)]
12const PUBLIC_KEY_DER_PREFIX: &[u8] = &[
13 48, 42, 48, 5, 6, 3, 43, 101, 110, 3, 33, 0
14];
15
16#[allow(dead_code)]
17const PRIVATE_KEY_DER_PREFIX: &[u8] = &[
18 48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 110, 4, 34, 4, 32
19];
20
21fn validate_priv_key(priv_key: &[u8]) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
22 if priv_key.len() != 32 {
23 return Err(format!("Incorrect private key length: {}", priv_key.len()).into());
24 }
25 Ok(())
26}
27
28fn scrub_pub_key_format(pub_key: &[u8]) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>> {
29 match pub_key.len() {
30 33 => {
31 if pub_key[0] == 0x05 {
34 Ok(pub_key[1..].to_vec())
35 } else {
36 Err(format!("Invalid public key version byte: expected 0x05, got 0x{:02x}", pub_key[0]).into())
37 }
38 }
39 32 => {
40 Ok(pub_key.to_vec())
44 }
45 len => {
46 Err(format!("Invalid public key length: expected 32 or 33 bytes, got {} bytes", len).into())
47 }
48 }
49}
50
51pub fn generate_key_pair() -> KeyPair {
53 let private = StaticSecret::random_from_rng(OsRng);
54 let public = PublicKey::from(&private);
55
56 let mut pub_key = vec![5u8];
57 pub_key.extend_from_slice(public.as_bytes());
58
59 KeyPair {
60 priv_key: private.to_bytes().to_vec(),
61 pub_key,
62 }
63}
64
65pub fn generate_signing_key_pair() -> KeyPair {
67 let signing_key = SigningKey::generate(&mut OsRng);
68 let verifying_key = signing_key.verifying_key();
69
70 let mut pub_key = vec![5u8];
71 pub_key.extend_from_slice(verifying_key.as_bytes());
72
73 KeyPair {
74 priv_key: signing_key.to_bytes().to_vec(),
75 pub_key,
76 }
77}
78
79pub fn calculate_agreement(pub_key: &[u8], priv_key: &[u8]) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>> {
81 let pub_key_scrubbed = scrub_pub_key_format(pub_key)?;
82 validate_priv_key(priv_key)?;
83
84 if pub_key_scrubbed.len() != 32 {
85 return Err("Invalid public key".into());
86 }
87
88 let private_key_array: [u8; 32] = priv_key.try_into()
89 .map_err(|_| "Private key must be exactly 32 bytes")?;
90 let public_key_array: [u8; 32] = pub_key_scrubbed.try_into()
91 .map_err(|_| "Public key must be exactly 32 bytes")?;
92
93 let secret = StaticSecret::from(private_key_array);
94 let public = PublicKey::from(public_key_array);
95
96 let shared_secret = secret.diffie_hellman(&public);
97 Ok(shared_secret.to_bytes().to_vec())
98}
99
100pub fn calculate_signature(priv_key: &[u8], message: &[u8]) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>> {
102 validate_priv_key(priv_key)?;
103
104 if message.is_empty() {
105 return Err("Invalid message".into());
106 }
107
108 let private_key_array: [u8; 32] = priv_key.try_into()
109 .map_err(|_| "Private key must be exactly 32 bytes")?;
110
111 let signing_key = SigningKey::from_bytes(&private_key_array);
112 let signature: Signature = signing_key.sign(message);
113
114 Ok(signature.to_bytes().to_vec())
115}
116
117pub fn verify_signature(pub_key: &[u8], message: &[u8], signature: &[u8]) -> Result<bool, Box<dyn std::error::Error + Send + Sync>> {
119 let pub_key_scrubbed = scrub_pub_key_format(pub_key)?;
120
121 if pub_key_scrubbed.len() != 32 {
122 return Err("Invalid public key".into());
123 }
124
125 if message.is_empty() {
126 return Err("Invalid message".into());
127 }
128
129 if signature.len() != 64 {
130 return Err("Invalid signature".into());
131 }
132
133 let public_key_array: [u8; 32] = pub_key_scrubbed.try_into()
134 .map_err(|_| "Public key must be exactly 32 bytes")?;
135 let signature_array: [u8; 64] = signature.try_into()
136 .map_err(|_| "Signature must be exactly 64 bytes")?;
137
138 let verifying_key = VerifyingKey::from_bytes(&public_key_array)
139 .map_err(|e| format!("Invalid public key: {}", e))?;
140 let sig = Signature::from_bytes(&signature_array);
141
142 match verifying_key.verify(message, &sig) {
143 Ok(()) => Ok(true),
144 Err(_) => Ok(false),
145 }
146}