1use anyhow::Result;
7use atproto_identity::key::{KeyData, KeyType, to_public};
8use base64::{Engine, engine::general_purpose::URL_SAFE_NO_PAD};
9use elliptic_curve::{JwkEcKey, sec1::ToEncodedPoint};
10use serde::{Deserialize, Serialize};
11use serde_json::json;
12use sha2::{Digest, Sha256};
13
14use crate::errors::JWKError;
15
16#[cfg(feature = "zeroize")]
17use zeroize::{Zeroize, ZeroizeOnDrop};
18
19#[derive(Serialize, Deserialize, Clone, PartialEq)]
21#[cfg_attr(debug_assertions, derive(Debug))]
22#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))]
23pub struct WrappedJsonWebKey {
24 #[serde(skip_serializing_if = "Option::is_none", default)]
26 #[cfg_attr(feature = "zeroize", zeroize(skip))]
27 pub kid: Option<String>,
28
29 #[serde(skip_serializing_if = "Option::is_none", default)]
31 #[cfg_attr(feature = "zeroize", zeroize(skip))]
32 pub alg: Option<String>,
33
34 #[serde(rename = "use", skip_serializing_if = "Option::is_none")]
36 #[cfg_attr(feature = "zeroize", zeroize(skip))]
37 pub _use: Option<String>,
38
39 #[serde(flatten)]
41 pub jwk: JwkEcKey,
42}
43
44#[derive(Serialize, Deserialize, Clone)]
46pub struct WrappedJsonWebKeySet {
47 pub keys: Vec<WrappedJsonWebKey>,
49}
50
51pub fn generate(key_data: &KeyData) -> Result<WrappedJsonWebKey> {
53 let alg = match key_data.key_type() {
54 KeyType::P256Public => Some("ES256".to_string()),
55 KeyType::P256Private => Some("ES256".to_string()),
56 KeyType::P384Public => Some("ES384".to_string()),
57 KeyType::P384Private => Some("ES384".to_string()),
58 KeyType::K256Public => Some("ES256K".to_string()),
59 KeyType::K256Private => Some("ES256K".to_string()),
60 };
61 let jwk = key_data.try_into()?;
62
63 let public_key = to_public(key_data)?;
64 let kid = Some(public_key.to_string());
65
66 Ok(WrappedJsonWebKey {
67 kid,
68 alg,
69 jwk,
70 _use: Some("sig".to_string()),
71 })
72}
73
74pub fn to_key_data(wrapped_jwk: &WrappedJsonWebKey) -> Result<KeyData, JWKError> {
76 let curve = wrapped_jwk.jwk.crv();
78
79 match curve {
80 "P-256" => {
81 if let Ok(secret_key) = p256::SecretKey::try_from(&wrapped_jwk.jwk) {
83 Ok(KeyData::new(
84 KeyType::P256Private,
85 secret_key.to_bytes().to_vec(),
86 ))
87 } else if let Ok(public_key) = p256::PublicKey::try_from(&wrapped_jwk.jwk) {
88 let compressed = public_key.to_encoded_point(true);
90 Ok(KeyData::new(
91 KeyType::P256Public,
92 compressed.as_bytes().to_vec(),
93 ))
94 } else {
95 Err(JWKError::P256ConversionFailed)
96 }
97 }
98 "P-384" => {
99 if let Ok(secret_key) = p384::SecretKey::try_from(&wrapped_jwk.jwk) {
101 Ok(KeyData::new(
102 KeyType::P384Private,
103 secret_key.to_bytes().to_vec(),
104 ))
105 } else if let Ok(public_key) = p384::PublicKey::try_from(&wrapped_jwk.jwk) {
106 let compressed = public_key.to_encoded_point(true);
108 Ok(KeyData::new(
109 KeyType::P384Public,
110 compressed.as_bytes().to_vec(),
111 ))
112 } else {
113 Err(JWKError::P384ConversionFailed)
114 }
115 }
116 "secp256k1" => {
117 if let Ok(secret_key) = k256::SecretKey::try_from(&wrapped_jwk.jwk) {
119 Ok(KeyData::new(
120 KeyType::K256Private,
121 secret_key.to_bytes().to_vec(),
122 ))
123 } else if let Ok(public_key) = k256::PublicKey::try_from(&wrapped_jwk.jwk) {
124 let compressed = public_key.to_encoded_point(true);
126 Ok(KeyData::new(
127 KeyType::K256Public,
128 compressed.as_bytes().to_vec(),
129 ))
130 } else {
131 Err(JWKError::K256ConversionFailed)
132 }
133 }
134 _ => Err(JWKError::UnsupportedCurve {
135 curve: curve.to_string(),
136 }),
137 }
138}
139
140pub fn thumbprint(wrapped_jwk: &WrappedJsonWebKey) -> Result<String, JWKError> {
151 let jwk_json =
153 serde_json::to_value(&wrapped_jwk.jwk).map_err(|e| JWKError::SerializationError {
154 message: e.to_string(),
155 })?;
156
157 let jwk_obj = jwk_json
159 .as_object()
160 .ok_or_else(|| JWKError::SerializationError {
161 message: "JWK is not a JSON object".to_string(),
162 })?;
163
164 let kty =
166 jwk_obj
167 .get("kty")
168 .and_then(|v| v.as_str())
169 .ok_or_else(|| JWKError::MissingField {
170 field: "kty".to_string(),
171 })?;
172
173 if kty != "EC" {
174 return Err(JWKError::UnsupportedKeyType {
175 kty: kty.to_string(),
176 });
177 }
178
179 let crv = jwk_obj.get("crv").ok_or_else(|| JWKError::MissingField {
181 field: "crv".to_string(),
182 })?;
183 let x = jwk_obj.get("x").ok_or_else(|| JWKError::MissingField {
184 field: "x".to_string(),
185 })?;
186 let y = jwk_obj.get("y").ok_or_else(|| JWKError::MissingField {
187 field: "y".to_string(),
188 })?;
189
190 let thumbprint_json = json!({
192 "crv": crv,
193 "kty": kty,
194 "x": x,
195 "y": y
196 });
197
198 let canonical_json =
200 serde_json::to_string(&thumbprint_json).map_err(|e| JWKError::SerializationError {
201 message: e.to_string(),
202 })?;
203
204 let mut hasher = Sha256::new();
206 hasher.update(canonical_json.as_bytes());
207 let hash = hasher.finalize();
208
209 Ok(URL_SAFE_NO_PAD.encode(hash))
211}
212
213impl TryFrom<WrappedJsonWebKey> for KeyData {
218 type Error = anyhow::Error;
219
220 fn try_from(wrapped_jwk: WrappedJsonWebKey) -> Result<Self, Self::Error> {
221 to_key_data(&wrapped_jwk).map_err(Into::into)
222 }
223}
224
225impl TryFrom<&WrappedJsonWebKey> for KeyData {
230 type Error = anyhow::Error;
231
232 fn try_from(wrapped_jwk: &WrappedJsonWebKey) -> Result<Self, Self::Error> {
233 to_key_data(wrapped_jwk).map_err(Into::into)
234 }
235}
236
237#[cfg(test)]
238mod tests {
239 use super::*;
240 use atproto_identity::key::{generate_key, sign, to_public, validate};
241
242 #[test]
243 fn test_to_key_data_p256_private_round_trip() -> Result<()> {
244 let original_key = generate_key(KeyType::P256Private)?;
246
247 let wrapped_jwk = generate(&original_key)?;
249 assert_eq!(wrapped_jwk.alg, Some("ES256".to_string()));
250 assert_eq!(wrapped_jwk._use, Some("sig".to_string()));
251 assert_eq!(wrapped_jwk.jwk.crv(), "P-256");
252
253 let converted_key = to_key_data(&wrapped_jwk)?;
255
256 assert_eq!(*converted_key.key_type(), KeyType::P256Private);
258 assert_eq!(original_key.bytes(), converted_key.bytes());
259
260 let test_data = "P-256 private key round trip test".as_bytes();
262 let signature = sign(&converted_key, test_data)?;
263 validate(&converted_key, &signature, test_data)?;
264
265 Ok(())
266 }
267
268 #[test]
269 fn test_to_key_data_p256_public_round_trip() -> Result<()> {
270 let private_key = generate_key(KeyType::P256Private)?;
272 let original_public_key = to_public(&private_key)?;
273
274 let wrapped_jwk = generate(&original_public_key)?;
276 assert_eq!(wrapped_jwk.alg, Some("ES256".to_string()));
277 assert_eq!(wrapped_jwk.jwk.crv(), "P-256");
278
279 let converted_key = to_key_data(&wrapped_jwk)?;
281
282 assert_eq!(*converted_key.key_type(), KeyType::P256Public);
284 assert_eq!(original_public_key.bytes(), converted_key.bytes());
285
286 let test_data = "P-256 public key round trip test".as_bytes();
288 let signature = sign(&private_key, test_data)?;
289 validate(&converted_key, &signature, test_data)?;
290
291 Ok(())
292 }
293
294 #[test]
295 fn test_to_key_data_p384_private_round_trip() -> Result<()> {
296 let original_key = generate_key(KeyType::P384Private)?;
298
299 let wrapped_jwk = generate(&original_key)?;
301 assert_eq!(wrapped_jwk.alg, Some("ES384".to_string()));
302 assert_eq!(wrapped_jwk._use, Some("sig".to_string()));
303 assert_eq!(wrapped_jwk.jwk.crv(), "P-384");
304
305 let converted_key = to_key_data(&wrapped_jwk)?;
307
308 assert_eq!(*converted_key.key_type(), KeyType::P384Private);
310 assert_eq!(original_key.bytes(), converted_key.bytes());
311
312 let test_data = "P-384 private key round trip test".as_bytes();
314 let signature = sign(&converted_key, test_data)?;
315 validate(&converted_key, &signature, test_data)?;
316
317 Ok(())
318 }
319
320 #[test]
321 fn test_to_key_data_p384_public_round_trip() -> Result<()> {
322 let private_key = generate_key(KeyType::P384Private)?;
324 let original_public_key = to_public(&private_key)?;
325
326 let wrapped_jwk = generate(&original_public_key)?;
328 assert_eq!(wrapped_jwk.alg, Some("ES384".to_string()));
329 assert_eq!(wrapped_jwk.jwk.crv(), "P-384");
330
331 let converted_key = to_key_data(&wrapped_jwk)?;
333
334 assert_eq!(*converted_key.key_type(), KeyType::P384Public);
336 assert_eq!(original_public_key.bytes(), converted_key.bytes());
337
338 let test_data = "P-384 public key round trip test".as_bytes();
340 let signature = sign(&private_key, test_data)?;
341 validate(&converted_key, &signature, test_data)?;
342
343 Ok(())
344 }
345
346 #[test]
347 fn test_to_key_data_k256_private_round_trip() -> Result<()> {
348 let original_key = generate_key(KeyType::K256Private)?;
350
351 let wrapped_jwk = generate(&original_key)?;
353 assert_eq!(wrapped_jwk.alg, Some("ES256K".to_string()));
354 assert_eq!(wrapped_jwk._use, Some("sig".to_string()));
355 assert_eq!(wrapped_jwk.jwk.crv(), "secp256k1");
356
357 let converted_key = to_key_data(&wrapped_jwk)?;
359
360 assert_eq!(*converted_key.key_type(), KeyType::K256Private);
362 assert_eq!(original_key.bytes(), converted_key.bytes());
363
364 let test_data = "K-256 private key round trip test".as_bytes();
366 let signature = sign(&converted_key, test_data)?;
367 validate(&converted_key, &signature, test_data)?;
368
369 Ok(())
370 }
371
372 #[test]
373 fn test_to_key_data_k256_public_round_trip() -> Result<()> {
374 let private_key = generate_key(KeyType::K256Private)?;
376 let original_public_key = to_public(&private_key)?;
377
378 let wrapped_jwk = generate(&original_public_key)?;
380 assert_eq!(wrapped_jwk.alg, Some("ES256K".to_string()));
381 assert_eq!(wrapped_jwk.jwk.crv(), "secp256k1");
382
383 let converted_key = to_key_data(&wrapped_jwk)?;
385
386 assert_eq!(*converted_key.key_type(), KeyType::K256Public);
388 assert_eq!(original_public_key.bytes(), converted_key.bytes());
389
390 let test_data = "K-256 public key round trip test".as_bytes();
392 let signature = sign(&private_key, test_data)?;
393 validate(&converted_key, &signature, test_data)?;
394
395 Ok(())
396 }
397
398 #[test]
399 fn test_to_key_data_multiple_round_trips() -> Result<()> {
400 for _ in 0..3 {
402 let p256_private = generate_key(KeyType::P256Private)?;
404 let p256_private_jwk = generate(&p256_private)?;
405 let p256_private_converted = to_key_data(&p256_private_jwk)?;
406 assert_eq!(p256_private.bytes(), p256_private_converted.bytes());
407
408 let p256_public = to_public(&p256_private)?;
410 let p256_public_jwk = generate(&p256_public)?;
411 let p256_public_converted = to_key_data(&p256_public_jwk)?;
412 assert_eq!(p256_public.bytes(), p256_public_converted.bytes());
413
414 let p384_private = generate_key(KeyType::P384Private)?;
416 let p384_private_jwk = generate(&p384_private)?;
417 let p384_private_converted = to_key_data(&p384_private_jwk)?;
418 assert_eq!(p384_private.bytes(), p384_private_converted.bytes());
419
420 let p384_public = to_public(&p384_private)?;
422 let p384_public_jwk = generate(&p384_public)?;
423 let p384_public_converted = to_key_data(&p384_public_jwk)?;
424 assert_eq!(p384_public.bytes(), p384_public_converted.bytes());
425
426 let k256_private = generate_key(KeyType::K256Private)?;
428 let k256_private_jwk = generate(&k256_private)?;
429 let k256_private_converted = to_key_data(&k256_private_jwk)?;
430 assert_eq!(k256_private.bytes(), k256_private_converted.bytes());
431
432 let k256_public = to_public(&k256_private)?;
434 let k256_public_jwk = generate(&k256_public)?;
435 let k256_public_converted = to_key_data(&k256_public_jwk)?;
436 assert_eq!(k256_public.bytes(), k256_public_converted.bytes());
437 }
438
439 Ok(())
440 }
441
442 #[test]
443 fn test_to_key_data_cross_curve_verification() -> Result<()> {
444 let p256_private = generate_key(KeyType::P256Private)?;
446 let p384_private = generate_key(KeyType::P384Private)?;
447 let k256_private = generate_key(KeyType::K256Private)?;
448
449 let p256_jwk = generate(&p256_private)?;
451 let p384_jwk = generate(&p384_private)?;
452 let k256_jwk = generate(&k256_private)?;
453
454 let p256_converted = to_key_data(&p256_jwk)?;
455 let p384_converted = to_key_data(&p384_jwk)?;
456 let k256_converted = to_key_data(&k256_jwk)?;
457
458 let test_data = "Cross-curve verification test".as_bytes();
460
461 let p256_signature = sign(&p256_converted, test_data)?;
462 let p384_signature = sign(&p384_converted, test_data)?;
463 let k256_signature = sign(&k256_converted, test_data)?;
464
465 validate(&p256_converted, &p256_signature, test_data)?;
467 validate(&p384_converted, &p384_signature, test_data)?;
468 validate(&k256_converted, &k256_signature, test_data)?;
469
470 assert!(validate(&p256_converted, &p384_signature, test_data).is_err());
472 assert!(validate(&p256_converted, &k256_signature, test_data).is_err());
473 assert!(validate(&p384_converted, &p256_signature, test_data).is_err());
474 assert!(validate(&p384_converted, &k256_signature, test_data).is_err());
475 assert!(validate(&k256_converted, &p256_signature, test_data).is_err());
476 assert!(validate(&k256_converted, &p384_signature, test_data).is_err());
477
478 Ok(())
479 }
480
481 #[test]
482 fn test_to_key_data_algorithm_consistency() -> Result<()> {
483 let p256_key = generate_key(KeyType::P256Private)?;
485 let p384_key = generate_key(KeyType::P384Private)?;
486 let k256_key = generate_key(KeyType::K256Private)?;
487
488 let p256_jwk = generate(&p256_key)?;
489 let p384_jwk = generate(&p384_key)?;
490 let k256_jwk = generate(&k256_key)?;
491
492 assert_eq!(p256_jwk.alg, Some("ES256".to_string()));
494 assert_eq!(p384_jwk.alg, Some("ES384".to_string()));
495 assert_eq!(k256_jwk.alg, Some("ES256K".to_string()));
496
497 assert_eq!(p256_jwk.jwk.crv(), "P-256");
499 assert_eq!(p384_jwk.jwk.crv(), "P-384");
500 assert_eq!(k256_jwk.jwk.crv(), "secp256k1");
501
502 let p256_converted = to_key_data(&p256_jwk)?;
504 let p384_converted = to_key_data(&p384_jwk)?;
505 let k256_converted = to_key_data(&k256_jwk)?;
506
507 assert_eq!(*p256_converted.key_type(), KeyType::P256Private);
508 assert_eq!(*p384_converted.key_type(), KeyType::P384Private);
509 assert_eq!(*k256_converted.key_type(), KeyType::K256Private);
510
511 Ok(())
512 }
513
514 #[test]
515 fn test_to_key_data_key_sizes() -> Result<()> {
516 let p256_private = generate_key(KeyType::P256Private)?;
518 let p384_private = generate_key(KeyType::P384Private)?;
519 let k256_private = generate_key(KeyType::K256Private)?;
520
521 let p256_public = to_public(&p256_private)?;
522 let p384_public = to_public(&p384_private)?;
523 let k256_public = to_public(&k256_private)?;
524
525 let keys = [
527 (&p256_private, 32), (&p384_private, 48), (&k256_private, 32), (&p256_public, 33), (&p384_public, 49), (&k256_public, 33), ];
534
535 for (original_key, expected_size) in keys {
536 let jwk = generate(original_key)?;
537 let converted_key = to_key_data(&jwk)?;
538
539 assert_eq!(
540 converted_key.bytes().len(),
541 expected_size,
542 "Key size mismatch for {:?}",
543 original_key.key_type()
544 );
545 assert_eq!(original_key.bytes(), converted_key.bytes());
546 }
547
548 Ok(())
549 }
550
551 #[test]
552 fn test_to_key_data_did_string_consistency() -> Result<()> {
553 let test_keys = [
555 generate_key(KeyType::P256Private)?,
556 generate_key(KeyType::P384Private)?,
557 generate_key(KeyType::K256Private)?,
558 ];
559
560 for original_key in test_keys {
561 let original_did = format!("{}", original_key);
562
563 let jwk = generate(&original_key)?;
565 let converted_key = to_key_data(&jwk)?;
566 let converted_did = format!("{}", converted_key);
567
568 assert_eq!(
569 original_did,
570 converted_did,
571 "DID string mismatch for {:?}",
572 original_key.key_type()
573 );
574
575 let public_key = to_public(&original_key)?;
577 let public_did = format!("{}", public_key);
578
579 let public_jwk = generate(&public_key)?;
580 let converted_public_key = to_key_data(&public_jwk)?;
581 let converted_public_did = format!("{}", converted_public_key);
582
583 assert_eq!(
584 public_did,
585 converted_public_did,
586 "Public DID string mismatch for {:?}",
587 public_key.key_type()
588 );
589 }
590
591 Ok(())
592 }
593
594 #[test]
595 fn test_to_key_data_unsupported_curve() {
596 let valid_key = generate_key(KeyType::P256Private).unwrap();
604 let valid_jwk = generate(&valid_key).unwrap();
605
606 let result = to_key_data(&valid_jwk);
608 assert!(result.is_ok());
609
610 }
614
615 #[test]
616 fn test_to_key_data_invalid_jwk_conversion() {
617 use serde_json::json;
622
623 let invalid_jwk_json = json!({
625 "kty": "EC",
626 "crv": "P-256",
627 "x": "invalid-base64-data!!!",
628 "y": "also-invalid-base64!!!"
629 });
630
631 let _jwk_result: Result<elliptic_curve::JwkEcKey, _> =
633 serde_json::from_value(invalid_jwk_json);
634 let p256_key = generate_key(KeyType::P256Private).unwrap();
639 let valid_jwk = generate(&p256_key).unwrap();
640
641 let result = to_key_data(&valid_jwk);
643 assert!(result.is_ok());
644 }
645
646 #[test]
647 fn test_to_key_data_round_trip_with_existing_keys() -> Result<()> {
648 use atproto_identity::key::identify_key;
650
651 let test_keys = [
652 "did:key:z42tnbHmmnhF11nwSnp5kQJbcZQw2Vbw5WF3ABDSxPtDgU2o", "did:key:zDnaeXduWbJ1b1Kgjf3uCdCpMDF1LEDizUiyxAxGwerou3Nh2", "did:key:z3vLY4nbXy2rV4Qr65gUtfnSF3A8Be7gmYzUiCX6eo2PR1Rt", "did:key:zQ3shNzMp4oaaQ1gQRzCxMGXFrSW3NEM1M9T6KCY9eA7HhyEA", ];
657
658 for key_did in test_keys {
659 let original_key = identify_key(key_did)?;
660 let jwk = generate(&original_key)?;
661 let converted_key = to_key_data(&jwk)?;
662
663 assert_eq!(*original_key.key_type(), *converted_key.key_type());
665 assert_eq!(original_key.bytes(), converted_key.bytes());
666
667 let original_did = format!("{}", original_key);
669 let converted_did = format!("{}", converted_key);
670 assert_eq!(original_did, converted_did);
671 }
672
673 Ok(())
674 }
675
676 #[test]
677 fn test_to_key_data_metadata_preservation() -> Result<()> {
678 let test_keys = [
680 (generate_key(KeyType::P256Private)?, "ES256", "P-256"),
681 (generate_key(KeyType::P384Private)?, "ES384", "P-384"),
682 (generate_key(KeyType::K256Private)?, "ES256K", "secp256k1"),
683 ];
684
685 for (key, expected_alg, expected_crv) in test_keys {
686 let jwk = generate(&key)?;
687
688 assert_eq!(jwk.alg, Some(expected_alg.to_string()));
690 assert_eq!(jwk._use, Some("sig".to_string()));
691 assert_eq!(jwk.jwk.crv(), expected_crv);
692 assert!(jwk.kid.is_some());
693
694 let converted_key = to_key_data(&jwk)?;
696 assert_eq!(key.bytes(), converted_key.bytes());
697 }
698
699 Ok(())
700 }
701
702 #[test]
703 fn test_to_key_data_performance_stress() -> Result<()> {
704 use std::time::Instant;
706
707 let start = Instant::now();
708
709 for _ in 0..100 {
710 let p256_key = generate_key(KeyType::P256Private)?;
712 let p256_jwk = generate(&p256_key)?;
713 let p256_converted = to_key_data(&p256_jwk)?;
714 assert_eq!(p256_key.bytes(), p256_converted.bytes());
715
716 let p384_key = generate_key(KeyType::P384Private)?;
718 let p384_jwk = generate(&p384_key)?;
719 let p384_converted = to_key_data(&p384_jwk)?;
720 assert_eq!(p384_key.bytes(), p384_converted.bytes());
721
722 let k256_key = generate_key(KeyType::K256Private)?;
724 let k256_jwk = generate(&k256_key)?;
725 let k256_converted = to_key_data(&k256_jwk)?;
726 assert_eq!(k256_key.bytes(), k256_converted.bytes());
727 }
728
729 let duration = start.elapsed();
730 println!("300 round-trip conversions completed in: {:?}", duration);
731
732 assert!(
734 duration.as_millis() < 10000,
735 "Performance test took too long: {:?}",
736 duration
737 );
738
739 Ok(())
740 }
741
742 #[test]
743 fn test_to_key_data_serialization_consistency() -> Result<()> {
744 let test_keys = [
746 generate_key(KeyType::P256Private)?,
747 generate_key(KeyType::P384Private)?,
748 generate_key(KeyType::K256Private)?,
749 ];
750
751 for original_key in test_keys {
752 let jwk = generate(&original_key)?;
754
755 let json_string = serde_json::to_string(&jwk)?;
757 let deserialized_jwk: WrappedJsonWebKey = serde_json::from_str(&json_string)?;
758
759 let converted_from_original = to_key_data(&jwk)?;
761 let converted_from_deserialized = to_key_data(&deserialized_jwk)?;
762
763 assert_eq!(
765 *converted_from_original.key_type(),
766 *converted_from_deserialized.key_type()
767 );
768 assert_eq!(
769 converted_from_original.bytes(),
770 converted_from_deserialized.bytes()
771 );
772 assert_eq!(original_key.bytes(), converted_from_original.bytes());
773 }
774
775 Ok(())
776 }
777
778 #[test]
779 fn test_to_key_data_comprehensive_workflow() -> Result<()> {
780 println!("\n=== WrappedJsonWebKey to KeyData Comprehensive Test ===");
781
782 let test_cases = [
784 ("P-256 private", KeyType::P256Private),
785 ("P-384 private", KeyType::P384Private),
786 ("K-256 private", KeyType::K256Private),
787 ];
788
789 for (description, key_type) in test_cases {
790 println!("Testing {}", description);
791
792 let original_private = generate_key(key_type)?;
794 let original_public = to_public(&original_private)?;
795
796 let private_jwk = generate(&original_private)?;
798 let public_jwk = generate(&original_public)?;
799
800 let converted_private = to_key_data(&private_jwk)?;
802 let converted_public = to_key_data(&public_jwk)?;
803
804 assert_eq!(original_private.bytes(), converted_private.bytes());
806 assert_eq!(original_public.bytes(), converted_public.bytes());
807
808 let test_message = format!("Test data for {}", description);
810 let test_data = test_message.as_bytes();
811
812 let signature_original = sign(&original_private, test_data)?;
813 let signature_converted = sign(&converted_private, test_data)?;
814
815 validate(&original_public, &signature_original, test_data)?;
817 validate(&converted_public, &signature_original, test_data)?;
818 validate(&original_public, &signature_converted, test_data)?;
819 validate(&converted_public, &signature_converted, test_data)?;
820
821 assert_eq!(
823 format!("{}", original_private),
824 format!("{}", converted_private)
825 );
826 assert_eq!(
827 format!("{}", original_public),
828 format!("{}", converted_public)
829 );
830
831 println!(" ✓ {} passed all tests", description);
832 }
833
834 println!("=== All comprehensive tests completed successfully! ===\n");
835
836 Ok(())
837 }
838
839 #[test]
842 fn test_try_from_owned_p256_private() -> Result<()> {
843 let original_key = generate_key(KeyType::P256Private)?;
844 let wrapped_jwk = generate(&original_key)?;
845
846 let converted_key: KeyData = wrapped_jwk.try_into()?;
848
849 assert_eq!(*converted_key.key_type(), KeyType::P256Private);
850 assert_eq!(original_key.bytes(), converted_key.bytes());
851
852 Ok(())
853 }
854
855 #[test]
856 fn test_try_from_reference_p256_private() -> Result<()> {
857 let original_key = generate_key(KeyType::P256Private)?;
858 let wrapped_jwk = generate(&original_key)?;
859
860 let converted_key: KeyData = (&wrapped_jwk).try_into()?;
862
863 assert_eq!(*converted_key.key_type(), KeyType::P256Private);
864 assert_eq!(original_key.bytes(), converted_key.bytes());
865
866 Ok(())
867 }
868
869 #[test]
870 fn test_try_from_explicit_p256_private() -> Result<()> {
871 let original_key = generate_key(KeyType::P256Private)?;
872 let wrapped_jwk = generate(&original_key)?;
873
874 let converted_owned = KeyData::try_from(wrapped_jwk.clone())?;
876 let converted_ref = KeyData::try_from(&wrapped_jwk)?;
877
878 assert_eq!(*converted_owned.key_type(), KeyType::P256Private);
879 assert_eq!(*converted_ref.key_type(), KeyType::P256Private);
880 assert_eq!(original_key.bytes(), converted_owned.bytes());
881 assert_eq!(original_key.bytes(), converted_ref.bytes());
882 assert_eq!(converted_owned.bytes(), converted_ref.bytes());
883
884 Ok(())
885 }
886
887 #[test]
888 fn test_try_into_vs_to_key_data_consistency() -> Result<()> {
889 let test_keys = [
891 generate_key(KeyType::P256Private)?,
892 generate_key(KeyType::P384Private)?,
893 generate_key(KeyType::K256Private)?,
894 ];
895
896 for original_key in test_keys {
897 let public_key = to_public(&original_key)?;
898
899 for key in [&original_key, &public_key] {
900 let wrapped_jwk = generate(key)?;
901
902 let from_to_key_data = to_key_data(&wrapped_jwk)?;
904 let from_try_from_owned: KeyData = wrapped_jwk.clone().try_into()?;
905 let from_try_from_ref: KeyData = (&wrapped_jwk).try_into()?;
906 let from_explicit_owned = KeyData::try_from(wrapped_jwk.clone())?;
907 let from_explicit_ref = KeyData::try_from(&wrapped_jwk)?;
908
909 assert_eq!(from_to_key_data.key_type(), from_try_from_owned.key_type());
911 assert_eq!(from_to_key_data.key_type(), from_try_from_ref.key_type());
912 assert_eq!(from_to_key_data.key_type(), from_explicit_owned.key_type());
913 assert_eq!(from_to_key_data.key_type(), from_explicit_ref.key_type());
914
915 assert_eq!(from_to_key_data.bytes(), from_try_from_owned.bytes());
916 assert_eq!(from_to_key_data.bytes(), from_try_from_ref.bytes());
917 assert_eq!(from_to_key_data.bytes(), from_explicit_owned.bytes());
918 assert_eq!(from_to_key_data.bytes(), from_explicit_ref.bytes());
919 }
920 }
921
922 Ok(())
923 }
924
925 #[test]
926 fn test_trait_implementations_all_curves() -> Result<()> {
927 let test_cases = [
929 (KeyType::P256Private, "P-256 private"),
930 (KeyType::P384Private, "P-384 private"),
931 (KeyType::K256Private, "K-256 private"),
932 ];
933
934 for (key_type, description) in test_cases {
935 let private_key = generate_key(key_type)?;
937 let private_jwk = generate(&private_key)?;
938
939 let converted_private_owned: KeyData = private_jwk.clone().try_into()?;
941 let converted_private_ref: KeyData = (&private_jwk).try_into()?;
942
943 assert_eq!(
944 private_key.bytes(),
945 converted_private_owned.bytes(),
946 "Owned conversion failed for {}",
947 description
948 );
949 assert_eq!(
950 private_key.bytes(),
951 converted_private_ref.bytes(),
952 "Reference conversion failed for {}",
953 description
954 );
955
956 let public_key = to_public(&private_key)?;
958 let public_jwk = generate(&public_key)?;
959
960 let converted_public_owned: KeyData = public_jwk.clone().try_into()?;
962 let converted_public_ref: KeyData = (&public_jwk).try_into()?;
963
964 assert_eq!(
965 public_key.bytes(),
966 converted_public_owned.bytes(),
967 "Public owned conversion failed for {}",
968 description
969 );
970 assert_eq!(
971 public_key.bytes(),
972 converted_public_ref.bytes(),
973 "Public reference conversion failed for {}",
974 description
975 );
976
977 let test_data = format!("Trait test for {}", description);
979 let test_bytes = test_data.as_bytes();
980
981 let signature = sign(&converted_private_owned, test_bytes)?;
982 validate(&converted_public_owned, &signature, test_bytes)?;
983 validate(&converted_public_ref, &signature, test_bytes)?;
984 }
985
986 Ok(())
987 }
988
989 #[test]
990 fn test_trait_error_handling() -> Result<()> {
991 let p256_key = generate_key(KeyType::P256Private)?;
993 let valid_jwk = generate(&p256_key)?;
994
995 let _: KeyData = valid_jwk.clone().try_into()?;
997 let _: KeyData = (&valid_jwk).try_into()?;
998 let _ = KeyData::try_from(valid_jwk.clone())?;
999 let _ = KeyData::try_from(&valid_jwk)?;
1000
1001 Ok(())
1005 }
1006
1007 #[test]
1008 fn test_trait_ownership_semantics() -> Result<()> {
1009 let original_key = generate_key(KeyType::P256Private)?;
1011 let wrapped_jwk = generate(&original_key)?;
1012
1013 let cloned_jwk = wrapped_jwk.clone();
1015 let converted_owned: KeyData = cloned_jwk.try_into()?;
1016
1017 let converted_ref: KeyData = (&wrapped_jwk).try_into()?;
1019
1020 let converted_ref2: KeyData = (&wrapped_jwk).try_into()?;
1022
1023 assert_eq!(converted_owned.bytes(), converted_ref.bytes());
1025 assert_eq!(converted_ref.bytes(), converted_ref2.bytes());
1026 assert_eq!(original_key.bytes(), converted_owned.bytes());
1027
1028 Ok(())
1029 }
1030
1031 #[test]
1032 fn test_trait_type_inference() -> Result<()> {
1033 let original_key = generate_key(KeyType::K256Private)?;
1035 let wrapped_jwk = generate(&original_key)?;
1036
1037 let converted1 = KeyData::try_from(wrapped_jwk.clone())?;
1039 let converted2 = KeyData::try_from(&wrapped_jwk)?;
1040
1041 let converted3: Result<KeyData, _> = wrapped_jwk.clone().try_into();
1043 let converted3 = converted3?;
1044
1045 let converted4: Result<KeyData, _> = (&wrapped_jwk).try_into();
1046 let converted4 = converted4?;
1047
1048 assert_eq!(converted1.bytes(), converted2.bytes());
1050 assert_eq!(converted2.bytes(), converted3.bytes());
1051 assert_eq!(converted3.bytes(), converted4.bytes());
1052 assert_eq!(original_key.bytes(), converted1.bytes());
1053
1054 Ok(())
1055 }
1056
1057 #[test]
1058 fn test_trait_comprehensive_workflow() -> Result<()> {
1059 println!("\n=== TryFrom/TryInto Trait Implementation Test ===");
1060
1061 let test_cases = [
1063 ("P-256", KeyType::P256Private),
1064 ("P-384", KeyType::P384Private),
1065 ("K-256", KeyType::K256Private),
1066 ];
1067
1068 for (curve_name, key_type) in test_cases {
1069 println!("Testing {} trait implementations", curve_name);
1070
1071 let original_private = generate_key(key_type)?;
1073 let original_public = to_public(&original_private)?;
1074
1075 let private_jwk = generate(&original_private)?;
1077 let public_jwk = generate(&original_public)?;
1078
1079 println!(" Testing TryFrom<WrappedJsonWebKey>");
1081 let private_from_owned = KeyData::try_from(private_jwk.clone())?;
1082 let public_from_owned = KeyData::try_from(public_jwk.clone())?;
1083
1084 println!(" Testing TryFrom<&WrappedJsonWebKey>");
1085 let private_from_ref = KeyData::try_from(&private_jwk)?;
1086 let public_from_ref = KeyData::try_from(&public_jwk)?;
1087
1088 println!(" Testing TryInto<KeyData> for WrappedJsonWebKey");
1089 let private_into_owned: KeyData = private_jwk.clone().try_into()?;
1090 let public_into_owned: KeyData = public_jwk.clone().try_into()?;
1091
1092 println!(" Testing TryInto<KeyData> for &WrappedJsonWebKey");
1093 let private_into_ref: KeyData = (&private_jwk).try_into()?;
1094 let public_into_ref: KeyData = (&public_jwk).try_into()?;
1095
1096 let private_results = [
1098 &private_from_owned,
1099 &private_from_ref,
1100 &private_into_owned,
1101 &private_into_ref,
1102 ];
1103 let public_results = [
1104 &public_from_owned,
1105 &public_from_ref,
1106 &public_into_owned,
1107 &public_into_ref,
1108 ];
1109
1110 for result in &private_results[1..] {
1111 assert_eq!(private_results[0].bytes(), result.bytes());
1112 assert_eq!(private_results[0].key_type(), result.key_type());
1113 }
1114
1115 for result in &public_results[1..] {
1116 assert_eq!(public_results[0].bytes(), result.bytes());
1117 assert_eq!(public_results[0].key_type(), result.key_type());
1118 }
1119
1120 assert_eq!(original_private.bytes(), private_results[0].bytes());
1122 assert_eq!(original_public.bytes(), public_results[0].bytes());
1123
1124 let test_data = format!("{} trait test", curve_name);
1126 let test_bytes = test_data.as_bytes();
1127
1128 let signature = sign(&private_from_owned, test_bytes)?;
1129 validate(&public_from_owned, &signature, test_bytes)?;
1130 validate(&public_into_ref, &signature, test_bytes)?;
1131
1132 println!(" ✓ {} trait implementations passed all tests", curve_name);
1133 }
1134
1135 println!("=== All trait implementation tests completed successfully! ===\n");
1136
1137 Ok(())
1138 }
1139
1140 #[test]
1141 fn test_trait_usage_examples() -> Result<()> {
1142 let original_key = generate_key(KeyType::P256Private)?;
1144 let wrapped_jwk = generate(&original_key)?;
1145
1146 let converted1: KeyData = wrapped_jwk.clone().try_into()?;
1148
1149 let converted2: KeyData = (&wrapped_jwk).try_into()?;
1151
1152 let converted3 = KeyData::try_from(wrapped_jwk.clone())?;
1154 let converted4 = KeyData::try_from(&wrapped_jwk)?;
1155
1156 let converted5 = to_key_data(&wrapped_jwk)?;
1158
1159 let results = [
1161 &converted1,
1162 &converted2,
1163 &converted3,
1164 &converted4,
1165 &converted5,
1166 ];
1167 for result in &results[1..] {
1168 assert_eq!(converted1.bytes(), result.bytes());
1169 assert_eq!(converted1.key_type(), result.key_type());
1170 }
1171
1172 assert_eq!(original_key.bytes(), converted1.bytes());
1174 assert_eq!(*original_key.key_type(), *converted1.key_type());
1175
1176 println!("✓ All trait usage examples work correctly");
1177 Ok(())
1178 }
1179
1180 #[test]
1183 fn test_thumbprint_p256() -> Result<()> {
1184 let key = generate_key(KeyType::P256Private)?;
1185 let wrapped_jwk = generate(&key)?;
1186
1187 let tp = thumbprint(&wrapped_jwk)?;
1188
1189 assert!(!tp.is_empty());
1191 assert!(tp.len() > 20); assert!(!tp.contains('=')); assert!(!tp.contains('+')); assert!(!tp.contains('/')); Ok(())
1197 }
1198
1199 #[test]
1200 fn test_thumbprint_p384() -> Result<()> {
1201 let key = generate_key(KeyType::P384Private)?;
1202 let wrapped_jwk = generate(&key)?;
1203
1204 let tp = thumbprint(&wrapped_jwk)?;
1205
1206 assert!(!tp.is_empty());
1208 assert!(tp.len() > 20);
1209 assert!(!tp.contains('='));
1210 assert!(!tp.contains('+'));
1211 assert!(!tp.contains('/'));
1212
1213 Ok(())
1214 }
1215
1216 #[test]
1217 fn test_thumbprint_k256() -> Result<()> {
1218 let key = generate_key(KeyType::K256Private)?;
1219 let wrapped_jwk = generate(&key)?;
1220
1221 let tp = thumbprint(&wrapped_jwk)?;
1222
1223 assert!(!tp.is_empty());
1225 assert!(tp.len() > 20);
1226 assert!(!tp.contains('='));
1227 assert!(!tp.contains('+'));
1228 assert!(!tp.contains('/'));
1229
1230 Ok(())
1231 }
1232
1233 #[test]
1234 fn test_thumbprint_consistency() -> Result<()> {
1235 let key = generate_key(KeyType::P256Private)?;
1237 let wrapped_jwk = generate(&key)?;
1238
1239 let tp1 = thumbprint(&wrapped_jwk)?;
1240 let tp2 = thumbprint(&wrapped_jwk)?;
1241 let tp3 = thumbprint(&wrapped_jwk)?;
1242
1243 assert_eq!(tp1, tp2);
1244 assert_eq!(tp2, tp3);
1245
1246 Ok(())
1247 }
1248
1249 #[test]
1250 fn test_thumbprint_different_keys_different_thumbprints() -> Result<()> {
1251 let key1 = generate_key(KeyType::P256Private)?;
1253 let key2 = generate_key(KeyType::P256Private)?;
1254
1255 let jwk1 = generate(&key1)?;
1256 let jwk2 = generate(&key2)?;
1257
1258 let tp1 = thumbprint(&jwk1)?;
1259 let tp2 = thumbprint(&jwk2)?;
1260
1261 assert_ne!(tp1, tp2);
1262
1263 Ok(())
1264 }
1265
1266 #[test]
1267 fn test_thumbprint_private_vs_public_same_thumbprint() -> Result<()> {
1268 let private_key = generate_key(KeyType::P256Private)?;
1271 let public_key = to_public(&private_key)?;
1272
1273 let private_jwk = generate(&private_key)?;
1274 let public_jwk = generate(&public_key)?;
1275
1276 let private_tp = thumbprint(&private_jwk)?;
1277 let public_tp = thumbprint(&public_jwk)?;
1278
1279 assert_eq!(private_tp, public_tp);
1280
1281 Ok(())
1282 }
1283
1284 #[test]
1285 fn test_thumbprint_cross_curve_different() -> Result<()> {
1286 let p256_key = generate_key(KeyType::P256Private)?;
1288 let p384_key = generate_key(KeyType::P384Private)?;
1289 let k256_key = generate_key(KeyType::K256Private)?;
1290
1291 let p256_jwk = generate(&p256_key)?;
1292 let p384_jwk = generate(&p384_key)?;
1293 let k256_jwk = generate(&k256_key)?;
1294
1295 let p256_tp = thumbprint(&p256_jwk)?;
1296 let p384_tp = thumbprint(&p384_jwk)?;
1297 let k256_tp = thumbprint(&k256_jwk)?;
1298
1299 assert_ne!(p256_tp, p384_tp);
1300 assert_ne!(p256_tp, k256_tp);
1301 assert_ne!(p384_tp, k256_tp);
1302
1303 Ok(())
1304 }
1305
1306 #[test]
1307 fn test_thumbprint_deterministic() -> Result<()> {
1308 use atproto_identity::key::identify_key;
1310
1311 let known_key = identify_key("did:key:z42tnbHmmnhF11nwSnp5kQJbcZQw2Vbw5WF3ABDSxPtDgU2o")?;
1312 let wrapped_jwk = generate(&known_key)?;
1313
1314 let tp = thumbprint(&wrapped_jwk)?;
1315
1316 assert!(!tp.is_empty());
1318 assert!(tp.len() == 43); let tp2 = thumbprint(&wrapped_jwk)?;
1322 assert_eq!(tp, tp2);
1323
1324 Ok(())
1325 }
1326
1327 #[test]
1328 fn test_thumbprint_performance() -> Result<()> {
1329 use std::time::Instant;
1331
1332 let key = generate_key(KeyType::P256Private)?;
1333 let wrapped_jwk = generate(&key)?;
1334
1335 let start = Instant::now();
1336
1337 for _ in 0..1000 {
1338 let _tp = thumbprint(&wrapped_jwk)?;
1339 }
1340
1341 let duration = start.elapsed();
1342
1343 assert!(
1345 duration.as_millis() < 2000,
1346 "Thumbprint performance test took too long: {:?}",
1347 duration
1348 );
1349
1350 Ok(())
1351 }
1352
1353 #[test]
1354 fn test_thumbprint_spec_compliance() -> Result<()> {
1355 let key = generate_key(KeyType::P256Private)?;
1357 let wrapped_jwk = generate(&key)?;
1358
1359 let tp = thumbprint(&wrapped_jwk)?;
1360
1361 assert_eq!(tp.len(), 43);
1365
1366 for c in tp.chars() {
1368 assert!(c.is_alphanumeric() || c == '-' || c == '_');
1369 }
1370
1371 Ok(())
1372 }
1373
1374 #[test]
1375 fn test_thumbprint_with_all_curves() -> Result<()> {
1376 let test_cases = [
1378 (KeyType::P256Private, "P-256"),
1379 (KeyType::P384Private, "P-384"),
1380 (KeyType::K256Private, "K-256"),
1381 ];
1382
1383 for (key_type, curve_name) in test_cases {
1384 let private_key = generate_key(key_type)?;
1386 let public_key = to_public(&private_key)?;
1387
1388 let private_jwk = generate(&private_key)?;
1389 let public_jwk = generate(&public_key)?;
1390
1391 let private_tp = thumbprint(&private_jwk)?;
1392 let public_tp = thumbprint(&public_jwk)?;
1393
1394 assert_eq!(
1396 private_tp, public_tp,
1397 "Thumbprint mismatch for {}",
1398 curve_name
1399 );
1400
1401 assert_eq!(
1403 private_tp.len(),
1404 43,
1405 "Invalid thumbprint length for {}",
1406 curve_name
1407 );
1408 assert!(
1409 !private_tp.contains('='),
1410 "Thumbprint contains padding for {}",
1411 curve_name
1412 );
1413 }
1414
1415 Ok(())
1416 }
1417
1418 #[test]
1419 fn test_thumbprint_comprehensive() -> Result<()> {
1420 let curves = [
1422 (KeyType::P256Private, "P-256"),
1423 (KeyType::P384Private, "P-384"),
1424 (KeyType::K256Private, "K-256"),
1425 ];
1426
1427 for (key_type, curve_name) in curves {
1428 let keys: Vec<_> = (0..5)
1430 .map(|_| generate_key(key_type.clone()))
1431 .collect::<Result<Vec<_>, _>>()?;
1432
1433 let mut thumbprints = Vec::new();
1434
1435 for (i, key) in keys.iter().enumerate() {
1436 let private_jwk = generate(key)?;
1437 let public_jwk = generate(&to_public(key)?)?;
1438
1439 let private_tp = thumbprint(&private_jwk)?;
1440 let public_tp = thumbprint(&public_jwk)?;
1441
1442 assert_eq!(
1444 private_tp, public_tp,
1445 "Thumbprint mismatch for {} key {}",
1446 curve_name, i
1447 );
1448
1449 assert!(
1451 !thumbprints.contains(&private_tp),
1452 "Duplicate thumbprint for {} key {}",
1453 curve_name,
1454 i
1455 );
1456
1457 thumbprints.push(private_tp);
1458 }
1459
1460 assert_eq!(
1462 thumbprints.len(),
1463 5,
1464 "Not all thumbprints are unique for {}",
1465 curve_name
1466 );
1467
1468 for tp in &thumbprints {
1470 assert_eq!(tp.len(), 43, "Invalid length for {} thumbprint", curve_name);
1471 assert!(
1472 !tp.contains(&['=', '+', '/'][..]),
1473 "Invalid characters in {} thumbprint",
1474 curve_name
1475 );
1476 }
1477 }
1478
1479 Ok(())
1480 }
1481}