1use baseid_core::error::CryptoError;
4use baseid_core::types::{KeyType, SignatureAlgorithm};
5use serde::{Deserialize, Serialize};
6use zeroize::Zeroize;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct PublicKey {
11 pub key_type: KeyType,
12 pub bytes: Vec<u8>,
13}
14
15pub struct KeyPair {
19 pub public: PublicKey,
20 secret: SecretKey,
21}
22
23struct SecretKey {
25 bytes: Vec<u8>,
26}
27
28impl Drop for SecretKey {
29 fn drop(&mut self) {
30 self.bytes.zeroize();
31 }
32}
33
34impl std::fmt::Debug for KeyPair {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 f.debug_struct("KeyPair")
37 .field("public", &self.public)
38 .field("secret", &"[REDACTED]")
39 .finish()
40 }
41}
42
43impl KeyPair {
44 pub fn generate(key_type: KeyType) -> baseid_core::Result<Self> {
46 use rand::rngs::OsRng;
47
48 match key_type {
49 KeyType::Bls12381G2 => Err(CryptoError::UnsupportedAlgorithm.into()),
50 KeyType::Ed25519 => {
51 let signing_key = ed25519_dalek::SigningKey::generate(&mut OsRng);
52 let verifying_key = signing_key.verifying_key();
53 Ok(Self {
54 public: PublicKey {
55 key_type,
56 bytes: verifying_key.as_bytes().to_vec(),
57 },
58 secret: SecretKey {
59 bytes: signing_key.to_bytes().to_vec(),
60 },
61 })
62 }
63 KeyType::P256 => {
64 let signing_key = p256::ecdsa::SigningKey::random(&mut OsRng);
65 let verifying_key = signing_key.verifying_key();
66 let public_bytes = verifying_key.to_encoded_point(true).as_bytes().to_vec();
67 let secret_bytes = signing_key.to_bytes().to_vec();
68 Ok(Self {
69 public: PublicKey {
70 key_type,
71 bytes: public_bytes,
72 },
73 secret: SecretKey {
74 bytes: secret_bytes,
75 },
76 })
77 }
78 KeyType::P384 => {
79 let signing_key = p384::ecdsa::SigningKey::random(&mut OsRng);
80 let verifying_key = signing_key.verifying_key();
81 let public_bytes = verifying_key.to_encoded_point(true).as_bytes().to_vec();
82 let secret_bytes = signing_key.to_bytes().to_vec();
83 Ok(Self {
84 public: PublicKey {
85 key_type,
86 bytes: public_bytes,
87 },
88 secret: SecretKey {
89 bytes: secret_bytes,
90 },
91 })
92 }
93 KeyType::Secp256k1 => {
94 let signing_key = k256::ecdsa::SigningKey::random(&mut OsRng);
95 let verifying_key = signing_key.verifying_key();
96 let public_bytes = verifying_key.to_encoded_point(true).as_bytes().to_vec();
97 let secret_bytes = signing_key.to_bytes().to_vec();
98 Ok(Self {
99 public: PublicKey {
100 key_type,
101 bytes: public_bytes,
102 },
103 secret: SecretKey {
104 bytes: secret_bytes,
105 },
106 })
107 }
108 }
109 }
110
111 pub fn algorithm(&self) -> SignatureAlgorithm {
113 self.public.algorithm()
114 }
115
116 pub fn secret_bytes(&self) -> &[u8] {
118 &self.secret.bytes
119 }
120
121 pub fn from_bytes(key_type: KeyType, secret_bytes: &[u8]) -> baseid_core::Result<Self> {
123 match key_type {
124 KeyType::Bls12381G2 => Err(CryptoError::UnsupportedAlgorithm.into()),
125 KeyType::Ed25519 => {
126 let bytes: [u8; 32] = secret_bytes
127 .try_into()
128 .map_err(|_| CryptoError::InvalidKeyMaterial)?;
129 let signing_key = ed25519_dalek::SigningKey::from_bytes(&bytes);
130 let verifying_key = signing_key.verifying_key();
131 Ok(Self {
132 public: PublicKey {
133 key_type,
134 bytes: verifying_key.as_bytes().to_vec(),
135 },
136 secret: SecretKey {
137 bytes: secret_bytes.to_vec(),
138 },
139 })
140 }
141 KeyType::P256 => {
142 if secret_bytes.len() != 32 {
143 return Err(CryptoError::InvalidKeyMaterial.into());
144 }
145 let signing_key = p256::ecdsa::SigningKey::from_bytes(secret_bytes.into())
146 .map_err(|_| CryptoError::InvalidKeyMaterial)?;
147 let verifying_key = signing_key.verifying_key();
148 let public_bytes = verifying_key.to_encoded_point(true).as_bytes().to_vec();
149 Ok(Self {
150 public: PublicKey {
151 key_type,
152 bytes: public_bytes,
153 },
154 secret: SecretKey {
155 bytes: secret_bytes.to_vec(),
156 },
157 })
158 }
159 KeyType::P384 => {
160 if secret_bytes.len() != 48 {
161 return Err(CryptoError::InvalidKeyMaterial.into());
162 }
163 let signing_key = p384::ecdsa::SigningKey::from_bytes(secret_bytes.into())
164 .map_err(|_| CryptoError::InvalidKeyMaterial)?;
165 let verifying_key = signing_key.verifying_key();
166 let public_bytes = verifying_key.to_encoded_point(true).as_bytes().to_vec();
167 Ok(Self {
168 public: PublicKey {
169 key_type,
170 bytes: public_bytes,
171 },
172 secret: SecretKey {
173 bytes: secret_bytes.to_vec(),
174 },
175 })
176 }
177 KeyType::Secp256k1 => {
178 if secret_bytes.len() != 32 {
179 return Err(CryptoError::InvalidKeyMaterial.into());
180 }
181 let signing_key = k256::ecdsa::SigningKey::from_bytes(secret_bytes.into())
182 .map_err(|_| CryptoError::InvalidKeyMaterial)?;
183 let verifying_key = signing_key.verifying_key();
184 let public_bytes = verifying_key.to_encoded_point(true).as_bytes().to_vec();
185 Ok(Self {
186 public: PublicKey {
187 key_type,
188 bytes: public_bytes,
189 },
190 secret: SecretKey {
191 bytes: secret_bytes.to_vec(),
192 },
193 })
194 }
195 }
196 }
197}
198
199impl PublicKey {
200 pub fn from_bytes(key_type: KeyType, public_bytes: &[u8]) -> baseid_core::Result<Self> {
202 if key_type == KeyType::Bls12381G2 {
203 return Err(CryptoError::UnsupportedAlgorithm.into());
204 }
205 match key_type {
207 KeyType::Bls12381G2 => unreachable!(),
208 KeyType::Ed25519 => {
209 let bytes: [u8; 32] = public_bytes
210 .try_into()
211 .map_err(|_| CryptoError::InvalidKeyMaterial)?;
212 ed25519_dalek::VerifyingKey::from_bytes(&bytes)
213 .map_err(|_| CryptoError::InvalidKeyMaterial)?;
214 }
215 KeyType::P256 => {
216 use p256::elliptic_curve::sec1::FromEncodedPoint;
217 let point = p256::EncodedPoint::from_bytes(public_bytes)
218 .map_err(|_| CryptoError::InvalidKeyMaterial)?;
219 let maybe = p256::PublicKey::from_encoded_point(&point);
220 if maybe.is_none().into() {
221 return Err(CryptoError::InvalidKeyMaterial.into());
222 }
223 }
224 KeyType::P384 => {
225 use p384::elliptic_curve::sec1::FromEncodedPoint;
226 let point = p384::EncodedPoint::from_bytes(public_bytes)
227 .map_err(|_| CryptoError::InvalidKeyMaterial)?;
228 let maybe = p384::PublicKey::from_encoded_point(&point);
229 if maybe.is_none().into() {
230 return Err(CryptoError::InvalidKeyMaterial.into());
231 }
232 }
233 KeyType::Secp256k1 => {
234 use k256::elliptic_curve::sec1::FromEncodedPoint;
235 let point = k256::EncodedPoint::from_bytes(public_bytes)
236 .map_err(|_| CryptoError::InvalidKeyMaterial)?;
237 let maybe = k256::PublicKey::from_encoded_point(&point);
238 if maybe.is_none().into() {
239 return Err(CryptoError::InvalidKeyMaterial.into());
240 }
241 }
242 }
243 Ok(Self {
244 key_type,
245 bytes: public_bytes.to_vec(),
246 })
247 }
248
249 pub fn algorithm(&self) -> SignatureAlgorithm {
251 match self.key_type {
252 KeyType::Ed25519 => SignatureAlgorithm::EdDsa,
253 KeyType::P256 => SignatureAlgorithm::Es256,
254 KeyType::P384 => SignatureAlgorithm::Es384,
255 KeyType::Secp256k1 => SignatureAlgorithm::Es256k,
256 KeyType::Bls12381G2 => SignatureAlgorithm::BbsPlus,
257 }
258 }
259}
260
261#[cfg(test)]
262mod tests {
263 use super::*;
264
265 #[test]
266 fn generate_ed25519() {
267 let kp = KeyPair::generate(KeyType::Ed25519).unwrap();
268 assert_eq!(kp.public.key_type, KeyType::Ed25519);
269 assert_eq!(kp.public.bytes.len(), 32);
270 assert_eq!(kp.secret_bytes().len(), 32);
271 }
272
273 #[test]
274 fn generate_p256() {
275 let kp = KeyPair::generate(KeyType::P256).unwrap();
276 assert_eq!(kp.public.key_type, KeyType::P256);
277 assert_eq!(kp.public.bytes.len(), 33); assert_eq!(kp.secret_bytes().len(), 32);
279 }
280
281 #[test]
282 fn generate_p384() {
283 let kp = KeyPair::generate(KeyType::P384).unwrap();
284 assert_eq!(kp.public.key_type, KeyType::P384);
285 assert_eq!(kp.public.bytes.len(), 49); assert_eq!(kp.secret_bytes().len(), 48);
287 }
288
289 #[test]
290 fn generate_secp256k1() {
291 let kp = KeyPair::generate(KeyType::Secp256k1).unwrap();
292 assert_eq!(kp.public.key_type, KeyType::Secp256k1);
293 assert_eq!(kp.public.bytes.len(), 33); assert_eq!(kp.secret_bytes().len(), 32);
295 }
296
297 #[test]
298 fn roundtrip_from_bytes_ed25519() {
299 let kp = KeyPair::generate(KeyType::Ed25519).unwrap();
300 let restored = KeyPair::from_bytes(KeyType::Ed25519, kp.secret_bytes()).unwrap();
301 assert_eq!(kp.public.bytes, restored.public.bytes);
302 }
303
304 #[test]
305 fn roundtrip_from_bytes_p256() {
306 let kp = KeyPair::generate(KeyType::P256).unwrap();
307 let restored = KeyPair::from_bytes(KeyType::P256, kp.secret_bytes()).unwrap();
308 assert_eq!(kp.public.bytes, restored.public.bytes);
309 }
310
311 #[test]
312 fn roundtrip_from_bytes_p384() {
313 let kp = KeyPair::generate(KeyType::P384).unwrap();
314 let restored = KeyPair::from_bytes(KeyType::P384, kp.secret_bytes()).unwrap();
315 assert_eq!(kp.public.bytes, restored.public.bytes);
316 }
317
318 #[test]
319 fn roundtrip_from_bytes_secp256k1() {
320 let kp = KeyPair::generate(KeyType::Secp256k1).unwrap();
321 let restored = KeyPair::from_bytes(KeyType::Secp256k1, kp.secret_bytes()).unwrap();
322 assert_eq!(kp.public.bytes, restored.public.bytes);
323 }
324
325 #[test]
326 fn public_key_from_bytes_validates() {
327 let kp = KeyPair::generate(KeyType::Ed25519).unwrap();
328 let pk = PublicKey::from_bytes(KeyType::Ed25519, &kp.public.bytes).unwrap();
329 assert_eq!(pk.bytes, kp.public.bytes);
330 }
331
332 #[test]
333 fn public_key_rejects_invalid_bytes() {
334 assert!(PublicKey::from_bytes(KeyType::Ed25519, &[0u8; 31]).is_err());
335 assert!(PublicKey::from_bytes(KeyType::P256, &[0u8; 10]).is_err());
336 assert!(PublicKey::from_bytes(KeyType::P384, &[0u8; 10]).is_err());
337 assert!(PublicKey::from_bytes(KeyType::Secp256k1, &[0u8; 10]).is_err());
338 }
339
340 #[test]
341 fn keypair_from_bytes_rejects_invalid() {
342 assert!(KeyPair::from_bytes(KeyType::Ed25519, &[0u8; 10]).is_err());
343 assert!(KeyPair::from_bytes(KeyType::P256, &[0u8; 10]).is_err());
344 assert!(KeyPair::from_bytes(KeyType::P384, &[0u8; 10]).is_err());
345 assert!(KeyPair::from_bytes(KeyType::Secp256k1, &[0u8; 10]).is_err());
346 }
347
348 #[test]
349 fn algorithm_mapping() {
350 assert_eq!(
351 KeyPair::generate(KeyType::Ed25519).unwrap().algorithm(),
352 SignatureAlgorithm::EdDsa
353 );
354 assert_eq!(
355 KeyPair::generate(KeyType::P256).unwrap().algorithm(),
356 SignatureAlgorithm::Es256
357 );
358 assert_eq!(
359 KeyPair::generate(KeyType::P384).unwrap().algorithm(),
360 SignatureAlgorithm::Es384
361 );
362 assert_eq!(
363 KeyPair::generate(KeyType::Secp256k1).unwrap().algorithm(),
364 SignatureAlgorithm::Es256k
365 );
366 }
367}