1use anyhow::Result;
9use atproto_identity::key::{KeyData, KeyType, to_public};
10use base64::{Engine, engine::general_purpose::URL_SAFE_NO_PAD};
11use elliptic_curve::{JwkEcKey, sec1::ToEncodedPoint};
12use serde::{Deserialize, Serialize};
13use serde_json::json;
14use sha2::{Digest, Sha256};
15
16use crate::errors::JWKError;
17
18#[cfg_attr(debug_assertions, derive(Debug))]
20#[derive(Serialize, Deserialize, Clone, PartialEq)]
21pub struct WrappedJsonWebKey {
22 #[serde(skip_serializing_if = "Option::is_none", default)]
24 pub kid: Option<String>,
25
26 #[serde(skip_serializing_if = "Option::is_none", default)]
28 pub alg: Option<String>,
29
30 #[serde(rename = "use", skip_serializing_if = "Option::is_none")]
32 pub _use: Option<String>,
33
34 #[serde(flatten)]
36 pub jwk: JwkEcKey,
37}
38
39#[derive(Serialize, Deserialize, Clone)]
41pub struct WrappedJsonWebKeySet {
42 pub keys: Vec<WrappedJsonWebKey>,
44}
45
46pub fn generate(key_data: &KeyData) -> Result<WrappedJsonWebKey> {
48 let alg = match key_data.key_type() {
49 KeyType::P256Public => Some("ES256".to_string()),
50 KeyType::P256Private => Some("ES256".to_string()),
51 KeyType::P384Public => Some("ES384".to_string()),
52 KeyType::P384Private => Some("ES384".to_string()),
53 KeyType::K256Public => Some("ES256K".to_string()),
54 KeyType::K256Private => Some("ES256K".to_string()),
55 };
56 let jwk = key_data.try_into()?;
57
58 let public_key = to_public(key_data)?;
59 let kid = Some(public_key.to_string());
60
61 Ok(WrappedJsonWebKey {
62 kid,
63 alg,
64 jwk,
65 _use: Some("sig".to_string()),
66 })
67}
68
69pub fn to_key_data(wrapped_jwk: &WrappedJsonWebKey) -> Result<KeyData, JWKError> {
71 let curve = wrapped_jwk.jwk.crv();
73
74 match curve {
75 "P-256" => {
76 if let Ok(secret_key) = p256::SecretKey::try_from(&wrapped_jwk.jwk) {
78 Ok(KeyData::new(
79 KeyType::P256Private,
80 secret_key.to_bytes().to_vec(),
81 ))
82 } else if let Ok(public_key) = p256::PublicKey::try_from(&wrapped_jwk.jwk) {
83 let compressed = public_key.to_encoded_point(true);
85 Ok(KeyData::new(
86 KeyType::P256Public,
87 compressed.as_bytes().to_vec(),
88 ))
89 } else {
90 Err(JWKError::P256ConversionFailed)
91 }
92 }
93 "P-384" => {
94 if let Ok(secret_key) = p384::SecretKey::try_from(&wrapped_jwk.jwk) {
96 Ok(KeyData::new(
97 KeyType::P384Private,
98 secret_key.to_bytes().to_vec(),
99 ))
100 } else if let Ok(public_key) = p384::PublicKey::try_from(&wrapped_jwk.jwk) {
101 let compressed = public_key.to_encoded_point(true);
103 Ok(KeyData::new(
104 KeyType::P384Public,
105 compressed.as_bytes().to_vec(),
106 ))
107 } else {
108 Err(JWKError::P384ConversionFailed)
109 }
110 }
111 "secp256k1" => {
112 if let Ok(secret_key) = k256::SecretKey::try_from(&wrapped_jwk.jwk) {
114 Ok(KeyData::new(
115 KeyType::K256Private,
116 secret_key.to_bytes().to_vec(),
117 ))
118 } else if let Ok(public_key) = k256::PublicKey::try_from(&wrapped_jwk.jwk) {
119 let compressed = public_key.to_encoded_point(true);
121 Ok(KeyData::new(
122 KeyType::K256Public,
123 compressed.as_bytes().to_vec(),
124 ))
125 } else {
126 Err(JWKError::K256ConversionFailed)
127 }
128 }
129 _ => Err(JWKError::UnsupportedCurve {
130 curve: curve.to_string(),
131 }),
132 }
133}
134
135pub fn thumbprint(wrapped_jwk: &WrappedJsonWebKey) -> Result<String, JWKError> {
146 let jwk_json =
148 serde_json::to_value(&wrapped_jwk.jwk).map_err(|e| JWKError::SerializationError {
149 message: e.to_string(),
150 })?;
151
152 let jwk_obj = jwk_json
154 .as_object()
155 .ok_or_else(|| JWKError::SerializationError {
156 message: "JWK is not a JSON object".to_string(),
157 })?;
158
159 let kty =
161 jwk_obj
162 .get("kty")
163 .and_then(|v| v.as_str())
164 .ok_or_else(|| JWKError::MissingField {
165 field: "kty".to_string(),
166 })?;
167
168 if kty != "EC" {
169 return Err(JWKError::UnsupportedKeyType {
170 kty: kty.to_string(),
171 });
172 }
173
174 let crv = jwk_obj.get("crv").ok_or_else(|| JWKError::MissingField {
176 field: "crv".to_string(),
177 })?;
178 let x = jwk_obj.get("x").ok_or_else(|| JWKError::MissingField {
179 field: "x".to_string(),
180 })?;
181 let y = jwk_obj.get("y").ok_or_else(|| JWKError::MissingField {
182 field: "y".to_string(),
183 })?;
184
185 let thumbprint_json = json!({
187 "crv": crv,
188 "kty": kty,
189 "x": x,
190 "y": y
191 });
192
193 let canonical_json =
195 serde_json::to_string(&thumbprint_json).map_err(|e| JWKError::SerializationError {
196 message: e.to_string(),
197 })?;
198
199 let mut hasher = Sha256::new();
201 hasher.update(canonical_json.as_bytes());
202 let hash = hasher.finalize();
203
204 Ok(URL_SAFE_NO_PAD.encode(hash))
206}
207
208impl TryFrom<WrappedJsonWebKey> for KeyData {
213 type Error = anyhow::Error;
214
215 fn try_from(wrapped_jwk: WrappedJsonWebKey) -> Result<Self, Self::Error> {
216 to_key_data(&wrapped_jwk).map_err(Into::into)
217 }
218}
219
220impl TryFrom<&WrappedJsonWebKey> for KeyData {
225 type Error = anyhow::Error;
226
227 fn try_from(wrapped_jwk: &WrappedJsonWebKey) -> Result<Self, Self::Error> {
228 to_key_data(wrapped_jwk).map_err(Into::into)
229 }
230}
231
232#[cfg(test)]
233mod tests {
234 use super::*;
235 use atproto_identity::key::{generate_key, sign, to_public, validate};
236
237 #[test]
238 fn test_to_key_data_p256_private_round_trip() -> Result<()> {
239 let original_key = generate_key(KeyType::P256Private)?;
241
242 let wrapped_jwk = generate(&original_key)?;
244 assert_eq!(wrapped_jwk.alg, Some("ES256".to_string()));
245 assert_eq!(wrapped_jwk._use, Some("sig".to_string()));
246 assert_eq!(wrapped_jwk.jwk.crv(), "P-256");
247
248 let converted_key = to_key_data(&wrapped_jwk)?;
250
251 assert_eq!(*converted_key.key_type(), KeyType::P256Private);
253 assert_eq!(original_key.bytes(), converted_key.bytes());
254
255 let test_data = "P-256 private key round trip test".as_bytes();
257 let signature = sign(&converted_key, test_data)?;
258 validate(&converted_key, &signature, test_data)?;
259
260 Ok(())
261 }
262
263 #[test]
264 fn test_to_key_data_p256_public_round_trip() -> Result<()> {
265 let private_key = generate_key(KeyType::P256Private)?;
267 let original_public_key = to_public(&private_key)?;
268
269 let wrapped_jwk = generate(&original_public_key)?;
271 assert_eq!(wrapped_jwk.alg, Some("ES256".to_string()));
272 assert_eq!(wrapped_jwk.jwk.crv(), "P-256");
273
274 let converted_key = to_key_data(&wrapped_jwk)?;
276
277 assert_eq!(*converted_key.key_type(), KeyType::P256Public);
279 assert_eq!(original_public_key.bytes(), converted_key.bytes());
280
281 let test_data = "P-256 public key round trip test".as_bytes();
283 let signature = sign(&private_key, test_data)?;
284 validate(&converted_key, &signature, test_data)?;
285
286 Ok(())
287 }
288
289 #[test]
290 fn test_to_key_data_p384_private_round_trip() -> Result<()> {
291 let original_key = generate_key(KeyType::P384Private)?;
293
294 let wrapped_jwk = generate(&original_key)?;
296 assert_eq!(wrapped_jwk.alg, Some("ES384".to_string()));
297 assert_eq!(wrapped_jwk._use, Some("sig".to_string()));
298 assert_eq!(wrapped_jwk.jwk.crv(), "P-384");
299
300 let converted_key = to_key_data(&wrapped_jwk)?;
302
303 assert_eq!(*converted_key.key_type(), KeyType::P384Private);
305 assert_eq!(original_key.bytes(), converted_key.bytes());
306
307 let test_data = "P-384 private key round trip test".as_bytes();
309 let signature = sign(&converted_key, test_data)?;
310 validate(&converted_key, &signature, test_data)?;
311
312 Ok(())
313 }
314
315 #[test]
316 fn test_to_key_data_p384_public_round_trip() -> Result<()> {
317 let private_key = generate_key(KeyType::P384Private)?;
319 let original_public_key = to_public(&private_key)?;
320
321 let wrapped_jwk = generate(&original_public_key)?;
323 assert_eq!(wrapped_jwk.alg, Some("ES384".to_string()));
324 assert_eq!(wrapped_jwk.jwk.crv(), "P-384");
325
326 let converted_key = to_key_data(&wrapped_jwk)?;
328
329 assert_eq!(*converted_key.key_type(), KeyType::P384Public);
331 assert_eq!(original_public_key.bytes(), converted_key.bytes());
332
333 let test_data = "P-384 public key round trip test".as_bytes();
335 let signature = sign(&private_key, test_data)?;
336 validate(&converted_key, &signature, test_data)?;
337
338 Ok(())
339 }
340
341 #[test]
342 fn test_to_key_data_k256_private_round_trip() -> Result<()> {
343 let original_key = generate_key(KeyType::K256Private)?;
345
346 let wrapped_jwk = generate(&original_key)?;
348 assert_eq!(wrapped_jwk.alg, Some("ES256K".to_string()));
349 assert_eq!(wrapped_jwk._use, Some("sig".to_string()));
350 assert_eq!(wrapped_jwk.jwk.crv(), "secp256k1");
351
352 let converted_key = to_key_data(&wrapped_jwk)?;
354
355 assert_eq!(*converted_key.key_type(), KeyType::K256Private);
357 assert_eq!(original_key.bytes(), converted_key.bytes());
358
359 let test_data = "K-256 private key round trip test".as_bytes();
361 let signature = sign(&converted_key, test_data)?;
362 validate(&converted_key, &signature, test_data)?;
363
364 Ok(())
365 }
366
367 #[test]
368 fn test_to_key_data_k256_public_round_trip() -> Result<()> {
369 let private_key = generate_key(KeyType::K256Private)?;
371 let original_public_key = to_public(&private_key)?;
372
373 let wrapped_jwk = generate(&original_public_key)?;
375 assert_eq!(wrapped_jwk.alg, Some("ES256K".to_string()));
376 assert_eq!(wrapped_jwk.jwk.crv(), "secp256k1");
377
378 let converted_key = to_key_data(&wrapped_jwk)?;
380
381 assert_eq!(*converted_key.key_type(), KeyType::K256Public);
383 assert_eq!(original_public_key.bytes(), converted_key.bytes());
384
385 let test_data = "K-256 public key round trip test".as_bytes();
387 let signature = sign(&private_key, test_data)?;
388 validate(&converted_key, &signature, test_data)?;
389
390 Ok(())
391 }
392
393 #[test]
394 fn test_to_key_data_multiple_round_trips() -> Result<()> {
395 for _ in 0..3 {
397 let p256_private = generate_key(KeyType::P256Private)?;
399 let p256_private_jwk = generate(&p256_private)?;
400 let p256_private_converted = to_key_data(&p256_private_jwk)?;
401 assert_eq!(p256_private.bytes(), p256_private_converted.bytes());
402
403 let p256_public = to_public(&p256_private)?;
405 let p256_public_jwk = generate(&p256_public)?;
406 let p256_public_converted = to_key_data(&p256_public_jwk)?;
407 assert_eq!(p256_public.bytes(), p256_public_converted.bytes());
408
409 let p384_private = generate_key(KeyType::P384Private)?;
411 let p384_private_jwk = generate(&p384_private)?;
412 let p384_private_converted = to_key_data(&p384_private_jwk)?;
413 assert_eq!(p384_private.bytes(), p384_private_converted.bytes());
414
415 let p384_public = to_public(&p384_private)?;
417 let p384_public_jwk = generate(&p384_public)?;
418 let p384_public_converted = to_key_data(&p384_public_jwk)?;
419 assert_eq!(p384_public.bytes(), p384_public_converted.bytes());
420
421 let k256_private = generate_key(KeyType::K256Private)?;
423 let k256_private_jwk = generate(&k256_private)?;
424 let k256_private_converted = to_key_data(&k256_private_jwk)?;
425 assert_eq!(k256_private.bytes(), k256_private_converted.bytes());
426
427 let k256_public = to_public(&k256_private)?;
429 let k256_public_jwk = generate(&k256_public)?;
430 let k256_public_converted = to_key_data(&k256_public_jwk)?;
431 assert_eq!(k256_public.bytes(), k256_public_converted.bytes());
432 }
433
434 Ok(())
435 }
436
437 #[test]
438 fn test_to_key_data_cross_curve_verification() -> Result<()> {
439 let p256_private = generate_key(KeyType::P256Private)?;
441 let p384_private = generate_key(KeyType::P384Private)?;
442 let k256_private = generate_key(KeyType::K256Private)?;
443
444 let p256_jwk = generate(&p256_private)?;
446 let p384_jwk = generate(&p384_private)?;
447 let k256_jwk = generate(&k256_private)?;
448
449 let p256_converted = to_key_data(&p256_jwk)?;
450 let p384_converted = to_key_data(&p384_jwk)?;
451 let k256_converted = to_key_data(&k256_jwk)?;
452
453 let test_data = "Cross-curve verification test".as_bytes();
455
456 let p256_signature = sign(&p256_converted, test_data)?;
457 let p384_signature = sign(&p384_converted, test_data)?;
458 let k256_signature = sign(&k256_converted, test_data)?;
459
460 validate(&p256_converted, &p256_signature, test_data)?;
462 validate(&p384_converted, &p384_signature, test_data)?;
463 validate(&k256_converted, &k256_signature, test_data)?;
464
465 assert!(validate(&p256_converted, &p384_signature, test_data).is_err());
467 assert!(validate(&p256_converted, &k256_signature, test_data).is_err());
468 assert!(validate(&p384_converted, &p256_signature, test_data).is_err());
469 assert!(validate(&p384_converted, &k256_signature, test_data).is_err());
470 assert!(validate(&k256_converted, &p256_signature, test_data).is_err());
471 assert!(validate(&k256_converted, &p384_signature, test_data).is_err());
472
473 Ok(())
474 }
475
476 #[test]
477 fn test_to_key_data_algorithm_consistency() -> Result<()> {
478 let p256_key = generate_key(KeyType::P256Private)?;
480 let p384_key = generate_key(KeyType::P384Private)?;
481 let k256_key = generate_key(KeyType::K256Private)?;
482
483 let p256_jwk = generate(&p256_key)?;
484 let p384_jwk = generate(&p384_key)?;
485 let k256_jwk = generate(&k256_key)?;
486
487 assert_eq!(p256_jwk.alg, Some("ES256".to_string()));
489 assert_eq!(p384_jwk.alg, Some("ES384".to_string()));
490 assert_eq!(k256_jwk.alg, Some("ES256K".to_string()));
491
492 assert_eq!(p256_jwk.jwk.crv(), "P-256");
494 assert_eq!(p384_jwk.jwk.crv(), "P-384");
495 assert_eq!(k256_jwk.jwk.crv(), "secp256k1");
496
497 let p256_converted = to_key_data(&p256_jwk)?;
499 let p384_converted = to_key_data(&p384_jwk)?;
500 let k256_converted = to_key_data(&k256_jwk)?;
501
502 assert_eq!(*p256_converted.key_type(), KeyType::P256Private);
503 assert_eq!(*p384_converted.key_type(), KeyType::P384Private);
504 assert_eq!(*k256_converted.key_type(), KeyType::K256Private);
505
506 Ok(())
507 }
508
509 #[test]
510 fn test_to_key_data_key_sizes() -> Result<()> {
511 let p256_private = generate_key(KeyType::P256Private)?;
513 let p384_private = generate_key(KeyType::P384Private)?;
514 let k256_private = generate_key(KeyType::K256Private)?;
515
516 let p256_public = to_public(&p256_private)?;
517 let p384_public = to_public(&p384_private)?;
518 let k256_public = to_public(&k256_private)?;
519
520 let keys = [
522 (&p256_private, 32), (&p384_private, 48), (&k256_private, 32), (&p256_public, 33), (&p384_public, 49), (&k256_public, 33), ];
529
530 for (original_key, expected_size) in keys {
531 let jwk = generate(original_key)?;
532 let converted_key = to_key_data(&jwk)?;
533
534 assert_eq!(
535 converted_key.bytes().len(),
536 expected_size,
537 "Key size mismatch for {:?}",
538 original_key.key_type()
539 );
540 assert_eq!(original_key.bytes(), converted_key.bytes());
541 }
542
543 Ok(())
544 }
545
546 #[test]
547 fn test_to_key_data_did_string_consistency() -> Result<()> {
548 let test_keys = [
550 generate_key(KeyType::P256Private)?,
551 generate_key(KeyType::P384Private)?,
552 generate_key(KeyType::K256Private)?,
553 ];
554
555 for original_key in test_keys {
556 let original_did = format!("{}", original_key);
557
558 let jwk = generate(&original_key)?;
560 let converted_key = to_key_data(&jwk)?;
561 let converted_did = format!("{}", converted_key);
562
563 assert_eq!(
564 original_did,
565 converted_did,
566 "DID string mismatch for {:?}",
567 original_key.key_type()
568 );
569
570 let public_key = to_public(&original_key)?;
572 let public_did = format!("{}", public_key);
573
574 let public_jwk = generate(&public_key)?;
575 let converted_public_key = to_key_data(&public_jwk)?;
576 let converted_public_did = format!("{}", converted_public_key);
577
578 assert_eq!(
579 public_did,
580 converted_public_did,
581 "Public DID string mismatch for {:?}",
582 public_key.key_type()
583 );
584 }
585
586 Ok(())
587 }
588
589 #[test]
590 fn test_to_key_data_unsupported_curve() {
591 let valid_key = generate_key(KeyType::P256Private).unwrap();
599 let valid_jwk = generate(&valid_key).unwrap();
600
601 let result = to_key_data(&valid_jwk);
603 assert!(result.is_ok());
604
605 }
609
610 #[test]
611 fn test_to_key_data_invalid_jwk_conversion() {
612 use serde_json::json;
617
618 let invalid_jwk_json = json!({
620 "kty": "EC",
621 "crv": "P-256",
622 "x": "invalid-base64-data!!!",
623 "y": "also-invalid-base64!!!"
624 });
625
626 let _jwk_result: Result<elliptic_curve::JwkEcKey, _> =
628 serde_json::from_value(invalid_jwk_json);
629 let p256_key = generate_key(KeyType::P256Private).unwrap();
634 let valid_jwk = generate(&p256_key).unwrap();
635
636 let result = to_key_data(&valid_jwk);
638 assert!(result.is_ok());
639 }
640
641 #[test]
642 fn test_to_key_data_round_trip_with_existing_keys() -> Result<()> {
643 use atproto_identity::key::identify_key;
645
646 let test_keys = [
647 "did:key:z42tnbHmmnhF11nwSnp5kQJbcZQw2Vbw5WF3ABDSxPtDgU2o", "did:key:zDnaeXduWbJ1b1Kgjf3uCdCpMDF1LEDizUiyxAxGwerou3Nh2", "did:key:z3vLY4nbXy2rV4Qr65gUtfnSF3A8Be7gmYzUiCX6eo2PR1Rt", "did:key:zQ3shNzMp4oaaQ1gQRzCxMGXFrSW3NEM1M9T6KCY9eA7HhyEA", ];
652
653 for key_did in test_keys {
654 let original_key = identify_key(key_did)?;
655 let jwk = generate(&original_key)?;
656 let converted_key = to_key_data(&jwk)?;
657
658 assert_eq!(*original_key.key_type(), *converted_key.key_type());
660 assert_eq!(original_key.bytes(), converted_key.bytes());
661
662 let original_did = format!("{}", original_key);
664 let converted_did = format!("{}", converted_key);
665 assert_eq!(original_did, converted_did);
666 }
667
668 Ok(())
669 }
670
671 #[test]
672 fn test_to_key_data_metadata_preservation() -> Result<()> {
673 let test_keys = [
675 (generate_key(KeyType::P256Private)?, "ES256", "P-256"),
676 (generate_key(KeyType::P384Private)?, "ES384", "P-384"),
677 (generate_key(KeyType::K256Private)?, "ES256K", "secp256k1"),
678 ];
679
680 for (key, expected_alg, expected_crv) in test_keys {
681 let jwk = generate(&key)?;
682
683 assert_eq!(jwk.alg, Some(expected_alg.to_string()));
685 assert_eq!(jwk._use, Some("sig".to_string()));
686 assert_eq!(jwk.jwk.crv(), expected_crv);
687 assert!(jwk.kid.is_some());
688
689 let converted_key = to_key_data(&jwk)?;
691 assert_eq!(key.bytes(), converted_key.bytes());
692 }
693
694 Ok(())
695 }
696
697 #[test]
698 fn test_to_key_data_performance_stress() -> Result<()> {
699 use std::time::Instant;
701
702 let start = Instant::now();
703
704 for _ in 0..100 {
705 let p256_key = generate_key(KeyType::P256Private)?;
707 let p256_jwk = generate(&p256_key)?;
708 let p256_converted = to_key_data(&p256_jwk)?;
709 assert_eq!(p256_key.bytes(), p256_converted.bytes());
710
711 let p384_key = generate_key(KeyType::P384Private)?;
713 let p384_jwk = generate(&p384_key)?;
714 let p384_converted = to_key_data(&p384_jwk)?;
715 assert_eq!(p384_key.bytes(), p384_converted.bytes());
716
717 let k256_key = generate_key(KeyType::K256Private)?;
719 let k256_jwk = generate(&k256_key)?;
720 let k256_converted = to_key_data(&k256_jwk)?;
721 assert_eq!(k256_key.bytes(), k256_converted.bytes());
722 }
723
724 let duration = start.elapsed();
725 println!("300 round-trip conversions completed in: {:?}", duration);
726
727 assert!(
729 duration.as_millis() < 5000,
730 "Performance test took too long: {:?}",
731 duration
732 );
733
734 Ok(())
735 }
736
737 #[test]
738 fn test_to_key_data_serialization_consistency() -> Result<()> {
739 let test_keys = [
741 generate_key(KeyType::P256Private)?,
742 generate_key(KeyType::P384Private)?,
743 generate_key(KeyType::K256Private)?,
744 ];
745
746 for original_key in test_keys {
747 let jwk = generate(&original_key)?;
749
750 let json_string = serde_json::to_string(&jwk)?;
752 let deserialized_jwk: WrappedJsonWebKey = serde_json::from_str(&json_string)?;
753
754 let converted_from_original = to_key_data(&jwk)?;
756 let converted_from_deserialized = to_key_data(&deserialized_jwk)?;
757
758 assert_eq!(
760 *converted_from_original.key_type(),
761 *converted_from_deserialized.key_type()
762 );
763 assert_eq!(
764 converted_from_original.bytes(),
765 converted_from_deserialized.bytes()
766 );
767 assert_eq!(original_key.bytes(), converted_from_original.bytes());
768 }
769
770 Ok(())
771 }
772
773 #[test]
774 fn test_to_key_data_comprehensive_workflow() -> Result<()> {
775 println!("\n=== WrappedJsonWebKey to KeyData Comprehensive Test ===");
776
777 let test_cases = [
779 ("P-256 private", KeyType::P256Private),
780 ("P-384 private", KeyType::P384Private),
781 ("K-256 private", KeyType::K256Private),
782 ];
783
784 for (description, key_type) in test_cases {
785 println!("Testing {}", description);
786
787 let original_private = generate_key(key_type)?;
789 let original_public = to_public(&original_private)?;
790
791 let private_jwk = generate(&original_private)?;
793 let public_jwk = generate(&original_public)?;
794
795 let converted_private = to_key_data(&private_jwk)?;
797 let converted_public = to_key_data(&public_jwk)?;
798
799 assert_eq!(original_private.bytes(), converted_private.bytes());
801 assert_eq!(original_public.bytes(), converted_public.bytes());
802
803 let test_message = format!("Test data for {}", description);
805 let test_data = test_message.as_bytes();
806
807 let signature_original = sign(&original_private, test_data)?;
808 let signature_converted = sign(&converted_private, test_data)?;
809
810 validate(&original_public, &signature_original, test_data)?;
812 validate(&converted_public, &signature_original, test_data)?;
813 validate(&original_public, &signature_converted, test_data)?;
814 validate(&converted_public, &signature_converted, test_data)?;
815
816 assert_eq!(
818 format!("{}", original_private),
819 format!("{}", converted_private)
820 );
821 assert_eq!(
822 format!("{}", original_public),
823 format!("{}", converted_public)
824 );
825
826 println!(" ✓ {} passed all tests", description);
827 }
828
829 println!("=== All comprehensive tests completed successfully! ===\n");
830
831 Ok(())
832 }
833
834 #[test]
837 fn test_try_from_owned_p256_private() -> Result<()> {
838 let original_key = generate_key(KeyType::P256Private)?;
839 let wrapped_jwk = generate(&original_key)?;
840
841 let converted_key: KeyData = wrapped_jwk.try_into()?;
843
844 assert_eq!(*converted_key.key_type(), KeyType::P256Private);
845 assert_eq!(original_key.bytes(), converted_key.bytes());
846
847 Ok(())
848 }
849
850 #[test]
851 fn test_try_from_reference_p256_private() -> Result<()> {
852 let original_key = generate_key(KeyType::P256Private)?;
853 let wrapped_jwk = generate(&original_key)?;
854
855 let converted_key: KeyData = (&wrapped_jwk).try_into()?;
857
858 assert_eq!(*converted_key.key_type(), KeyType::P256Private);
859 assert_eq!(original_key.bytes(), converted_key.bytes());
860
861 Ok(())
862 }
863
864 #[test]
865 fn test_try_from_explicit_p256_private() -> Result<()> {
866 let original_key = generate_key(KeyType::P256Private)?;
867 let wrapped_jwk = generate(&original_key)?;
868
869 let converted_owned = KeyData::try_from(wrapped_jwk.clone())?;
871 let converted_ref = KeyData::try_from(&wrapped_jwk)?;
872
873 assert_eq!(*converted_owned.key_type(), KeyType::P256Private);
874 assert_eq!(*converted_ref.key_type(), KeyType::P256Private);
875 assert_eq!(original_key.bytes(), converted_owned.bytes());
876 assert_eq!(original_key.bytes(), converted_ref.bytes());
877 assert_eq!(converted_owned.bytes(), converted_ref.bytes());
878
879 Ok(())
880 }
881
882 #[test]
883 fn test_try_into_vs_to_key_data_consistency() -> Result<()> {
884 let test_keys = [
886 generate_key(KeyType::P256Private)?,
887 generate_key(KeyType::P384Private)?,
888 generate_key(KeyType::K256Private)?,
889 ];
890
891 for original_key in test_keys {
892 let public_key = to_public(&original_key)?;
893
894 for key in [&original_key, &public_key] {
895 let wrapped_jwk = generate(key)?;
896
897 let from_to_key_data = to_key_data(&wrapped_jwk)?;
899 let from_try_from_owned: KeyData = wrapped_jwk.clone().try_into()?;
900 let from_try_from_ref: KeyData = (&wrapped_jwk).try_into()?;
901 let from_explicit_owned = KeyData::try_from(wrapped_jwk.clone())?;
902 let from_explicit_ref = KeyData::try_from(&wrapped_jwk)?;
903
904 assert_eq!(from_to_key_data.key_type(), from_try_from_owned.key_type());
906 assert_eq!(from_to_key_data.key_type(), from_try_from_ref.key_type());
907 assert_eq!(from_to_key_data.key_type(), from_explicit_owned.key_type());
908 assert_eq!(from_to_key_data.key_type(), from_explicit_ref.key_type());
909
910 assert_eq!(from_to_key_data.bytes(), from_try_from_owned.bytes());
911 assert_eq!(from_to_key_data.bytes(), from_try_from_ref.bytes());
912 assert_eq!(from_to_key_data.bytes(), from_explicit_owned.bytes());
913 assert_eq!(from_to_key_data.bytes(), from_explicit_ref.bytes());
914 }
915 }
916
917 Ok(())
918 }
919
920 #[test]
921 fn test_trait_implementations_all_curves() -> Result<()> {
922 let test_cases = [
924 (KeyType::P256Private, "P-256 private"),
925 (KeyType::P384Private, "P-384 private"),
926 (KeyType::K256Private, "K-256 private"),
927 ];
928
929 for (key_type, description) in test_cases {
930 let private_key = generate_key(key_type)?;
932 let private_jwk = generate(&private_key)?;
933
934 let converted_private_owned: KeyData = private_jwk.clone().try_into()?;
936 let converted_private_ref: KeyData = (&private_jwk).try_into()?;
937
938 assert_eq!(
939 private_key.bytes(),
940 converted_private_owned.bytes(),
941 "Owned conversion failed for {}",
942 description
943 );
944 assert_eq!(
945 private_key.bytes(),
946 converted_private_ref.bytes(),
947 "Reference conversion failed for {}",
948 description
949 );
950
951 let public_key = to_public(&private_key)?;
953 let public_jwk = generate(&public_key)?;
954
955 let converted_public_owned: KeyData = public_jwk.clone().try_into()?;
957 let converted_public_ref: KeyData = (&public_jwk).try_into()?;
958
959 assert_eq!(
960 public_key.bytes(),
961 converted_public_owned.bytes(),
962 "Public owned conversion failed for {}",
963 description
964 );
965 assert_eq!(
966 public_key.bytes(),
967 converted_public_ref.bytes(),
968 "Public reference conversion failed for {}",
969 description
970 );
971
972 let test_data = format!("Trait test for {}", description);
974 let test_bytes = test_data.as_bytes();
975
976 let signature = sign(&converted_private_owned, test_bytes)?;
977 validate(&converted_public_owned, &signature, test_bytes)?;
978 validate(&converted_public_ref, &signature, test_bytes)?;
979 }
980
981 Ok(())
982 }
983
984 #[test]
985 fn test_trait_error_handling() -> Result<()> {
986 let p256_key = generate_key(KeyType::P256Private)?;
988 let valid_jwk = generate(&p256_key)?;
989
990 let _: KeyData = valid_jwk.clone().try_into()?;
992 let _: KeyData = (&valid_jwk).try_into()?;
993 let _ = KeyData::try_from(valid_jwk.clone())?;
994 let _ = KeyData::try_from(&valid_jwk)?;
995
996 Ok(())
1000 }
1001
1002 #[test]
1003 fn test_trait_ownership_semantics() -> Result<()> {
1004 let original_key = generate_key(KeyType::P256Private)?;
1006 let wrapped_jwk = generate(&original_key)?;
1007
1008 let cloned_jwk = wrapped_jwk.clone();
1010 let converted_owned: KeyData = cloned_jwk.try_into()?;
1011
1012 let converted_ref: KeyData = (&wrapped_jwk).try_into()?;
1014
1015 let converted_ref2: KeyData = (&wrapped_jwk).try_into()?;
1017
1018 assert_eq!(converted_owned.bytes(), converted_ref.bytes());
1020 assert_eq!(converted_ref.bytes(), converted_ref2.bytes());
1021 assert_eq!(original_key.bytes(), converted_owned.bytes());
1022
1023 Ok(())
1024 }
1025
1026 #[test]
1027 fn test_trait_type_inference() -> Result<()> {
1028 let original_key = generate_key(KeyType::K256Private)?;
1030 let wrapped_jwk = generate(&original_key)?;
1031
1032 let converted1 = KeyData::try_from(wrapped_jwk.clone())?;
1034 let converted2 = KeyData::try_from(&wrapped_jwk)?;
1035
1036 let converted3: Result<KeyData, _> = wrapped_jwk.clone().try_into();
1038 let converted3 = converted3?;
1039
1040 let converted4: Result<KeyData, _> = (&wrapped_jwk).try_into();
1041 let converted4 = converted4?;
1042
1043 assert_eq!(converted1.bytes(), converted2.bytes());
1045 assert_eq!(converted2.bytes(), converted3.bytes());
1046 assert_eq!(converted3.bytes(), converted4.bytes());
1047 assert_eq!(original_key.bytes(), converted1.bytes());
1048
1049 Ok(())
1050 }
1051
1052 #[test]
1053 fn test_trait_comprehensive_workflow() -> Result<()> {
1054 println!("\n=== TryFrom/TryInto Trait Implementation Test ===");
1055
1056 let test_cases = [
1058 ("P-256", KeyType::P256Private),
1059 ("P-384", KeyType::P384Private),
1060 ("K-256", KeyType::K256Private),
1061 ];
1062
1063 for (curve_name, key_type) in test_cases {
1064 println!("Testing {} trait implementations", curve_name);
1065
1066 let original_private = generate_key(key_type)?;
1068 let original_public = to_public(&original_private)?;
1069
1070 let private_jwk = generate(&original_private)?;
1072 let public_jwk = generate(&original_public)?;
1073
1074 println!(" Testing TryFrom<WrappedJsonWebKey>");
1076 let private_from_owned = KeyData::try_from(private_jwk.clone())?;
1077 let public_from_owned = KeyData::try_from(public_jwk.clone())?;
1078
1079 println!(" Testing TryFrom<&WrappedJsonWebKey>");
1080 let private_from_ref = KeyData::try_from(&private_jwk)?;
1081 let public_from_ref = KeyData::try_from(&public_jwk)?;
1082
1083 println!(" Testing TryInto<KeyData> for WrappedJsonWebKey");
1084 let private_into_owned: KeyData = private_jwk.clone().try_into()?;
1085 let public_into_owned: KeyData = public_jwk.clone().try_into()?;
1086
1087 println!(" Testing TryInto<KeyData> for &WrappedJsonWebKey");
1088 let private_into_ref: KeyData = (&private_jwk).try_into()?;
1089 let public_into_ref: KeyData = (&public_jwk).try_into()?;
1090
1091 let private_results = [
1093 &private_from_owned,
1094 &private_from_ref,
1095 &private_into_owned,
1096 &private_into_ref,
1097 ];
1098 let public_results = [
1099 &public_from_owned,
1100 &public_from_ref,
1101 &public_into_owned,
1102 &public_into_ref,
1103 ];
1104
1105 for result in &private_results[1..] {
1106 assert_eq!(private_results[0].bytes(), result.bytes());
1107 assert_eq!(private_results[0].key_type(), result.key_type());
1108 }
1109
1110 for result in &public_results[1..] {
1111 assert_eq!(public_results[0].bytes(), result.bytes());
1112 assert_eq!(public_results[0].key_type(), result.key_type());
1113 }
1114
1115 assert_eq!(original_private.bytes(), private_results[0].bytes());
1117 assert_eq!(original_public.bytes(), public_results[0].bytes());
1118
1119 let test_data = format!("{} trait test", curve_name);
1121 let test_bytes = test_data.as_bytes();
1122
1123 let signature = sign(&private_from_owned, test_bytes)?;
1124 validate(&public_from_owned, &signature, test_bytes)?;
1125 validate(&public_into_ref, &signature, test_bytes)?;
1126
1127 println!(" ✓ {} trait implementations passed all tests", curve_name);
1128 }
1129
1130 println!("=== All trait implementation tests completed successfully! ===\n");
1131
1132 Ok(())
1133 }
1134
1135 #[test]
1136 fn test_trait_usage_examples() -> Result<()> {
1137 let original_key = generate_key(KeyType::P256Private)?;
1139 let wrapped_jwk = generate(&original_key)?;
1140
1141 let converted1: KeyData = wrapped_jwk.clone().try_into()?;
1143
1144 let converted2: KeyData = (&wrapped_jwk).try_into()?;
1146
1147 let converted3 = KeyData::try_from(wrapped_jwk.clone())?;
1149 let converted4 = KeyData::try_from(&wrapped_jwk)?;
1150
1151 let converted5 = to_key_data(&wrapped_jwk)?;
1153
1154 let results = [
1156 &converted1,
1157 &converted2,
1158 &converted3,
1159 &converted4,
1160 &converted5,
1161 ];
1162 for result in &results[1..] {
1163 assert_eq!(converted1.bytes(), result.bytes());
1164 assert_eq!(converted1.key_type(), result.key_type());
1165 }
1166
1167 assert_eq!(original_key.bytes(), converted1.bytes());
1169 assert_eq!(*original_key.key_type(), *converted1.key_type());
1170
1171 println!("✓ All trait usage examples work correctly");
1172 Ok(())
1173 }
1174
1175 #[test]
1178 fn test_thumbprint_p256() -> Result<()> {
1179 let key = generate_key(KeyType::P256Private)?;
1180 let wrapped_jwk = generate(&key)?;
1181
1182 let tp = thumbprint(&wrapped_jwk)?;
1183
1184 assert!(!tp.is_empty());
1186 assert!(tp.len() > 20); assert!(!tp.contains('=')); assert!(!tp.contains('+')); assert!(!tp.contains('/')); Ok(())
1192 }
1193
1194 #[test]
1195 fn test_thumbprint_p384() -> Result<()> {
1196 let key = generate_key(KeyType::P384Private)?;
1197 let wrapped_jwk = generate(&key)?;
1198
1199 let tp = thumbprint(&wrapped_jwk)?;
1200
1201 assert!(!tp.is_empty());
1203 assert!(tp.len() > 20);
1204 assert!(!tp.contains('='));
1205 assert!(!tp.contains('+'));
1206 assert!(!tp.contains('/'));
1207
1208 Ok(())
1209 }
1210
1211 #[test]
1212 fn test_thumbprint_k256() -> Result<()> {
1213 let key = generate_key(KeyType::K256Private)?;
1214 let wrapped_jwk = generate(&key)?;
1215
1216 let tp = thumbprint(&wrapped_jwk)?;
1217
1218 assert!(!tp.is_empty());
1220 assert!(tp.len() > 20);
1221 assert!(!tp.contains('='));
1222 assert!(!tp.contains('+'));
1223 assert!(!tp.contains('/'));
1224
1225 Ok(())
1226 }
1227
1228 #[test]
1229 fn test_thumbprint_consistency() -> Result<()> {
1230 let key = generate_key(KeyType::P256Private)?;
1232 let wrapped_jwk = generate(&key)?;
1233
1234 let tp1 = thumbprint(&wrapped_jwk)?;
1235 let tp2 = thumbprint(&wrapped_jwk)?;
1236 let tp3 = thumbprint(&wrapped_jwk)?;
1237
1238 assert_eq!(tp1, tp2);
1239 assert_eq!(tp2, tp3);
1240
1241 Ok(())
1242 }
1243
1244 #[test]
1245 fn test_thumbprint_different_keys_different_thumbprints() -> Result<()> {
1246 let key1 = generate_key(KeyType::P256Private)?;
1248 let key2 = generate_key(KeyType::P256Private)?;
1249
1250 let jwk1 = generate(&key1)?;
1251 let jwk2 = generate(&key2)?;
1252
1253 let tp1 = thumbprint(&jwk1)?;
1254 let tp2 = thumbprint(&jwk2)?;
1255
1256 assert_ne!(tp1, tp2);
1257
1258 Ok(())
1259 }
1260
1261 #[test]
1262 fn test_thumbprint_private_vs_public_same_thumbprint() -> Result<()> {
1263 let private_key = generate_key(KeyType::P256Private)?;
1266 let public_key = to_public(&private_key)?;
1267
1268 let private_jwk = generate(&private_key)?;
1269 let public_jwk = generate(&public_key)?;
1270
1271 let private_tp = thumbprint(&private_jwk)?;
1272 let public_tp = thumbprint(&public_jwk)?;
1273
1274 assert_eq!(private_tp, public_tp);
1275
1276 Ok(())
1277 }
1278
1279 #[test]
1280 fn test_thumbprint_cross_curve_different() -> Result<()> {
1281 let p256_key = generate_key(KeyType::P256Private)?;
1283 let p384_key = generate_key(KeyType::P384Private)?;
1284 let k256_key = generate_key(KeyType::K256Private)?;
1285
1286 let p256_jwk = generate(&p256_key)?;
1287 let p384_jwk = generate(&p384_key)?;
1288 let k256_jwk = generate(&k256_key)?;
1289
1290 let p256_tp = thumbprint(&p256_jwk)?;
1291 let p384_tp = thumbprint(&p384_jwk)?;
1292 let k256_tp = thumbprint(&k256_jwk)?;
1293
1294 assert_ne!(p256_tp, p384_tp);
1295 assert_ne!(p256_tp, k256_tp);
1296 assert_ne!(p384_tp, k256_tp);
1297
1298 Ok(())
1299 }
1300
1301 #[test]
1302 fn test_thumbprint_deterministic() -> Result<()> {
1303 use atproto_identity::key::identify_key;
1305
1306 let known_key = identify_key("did:key:z42tnbHmmnhF11nwSnp5kQJbcZQw2Vbw5WF3ABDSxPtDgU2o")?;
1307 let wrapped_jwk = generate(&known_key)?;
1308
1309 let tp = thumbprint(&wrapped_jwk)?;
1310
1311 assert!(!tp.is_empty());
1313 assert!(tp.len() == 43); let tp2 = thumbprint(&wrapped_jwk)?;
1317 assert_eq!(tp, tp2);
1318
1319 Ok(())
1320 }
1321
1322 #[test]
1323 fn test_thumbprint_performance() -> Result<()> {
1324 use std::time::Instant;
1326
1327 let key = generate_key(KeyType::P256Private)?;
1328 let wrapped_jwk = generate(&key)?;
1329
1330 let start = Instant::now();
1331
1332 for _ in 0..1000 {
1333 let _tp = thumbprint(&wrapped_jwk)?;
1334 }
1335
1336 let duration = start.elapsed();
1337
1338 assert!(
1340 duration.as_millis() < 2000,
1341 "Thumbprint performance test took too long: {:?}",
1342 duration
1343 );
1344
1345 Ok(())
1346 }
1347
1348 #[test]
1349 fn test_thumbprint_spec_compliance() -> Result<()> {
1350 let key = generate_key(KeyType::P256Private)?;
1352 let wrapped_jwk = generate(&key)?;
1353
1354 let tp = thumbprint(&wrapped_jwk)?;
1355
1356 assert_eq!(tp.len(), 43);
1360
1361 for c in tp.chars() {
1363 assert!(c.is_alphanumeric() || c == '-' || c == '_');
1364 }
1365
1366 Ok(())
1367 }
1368
1369 #[test]
1370 fn test_thumbprint_with_all_curves() -> Result<()> {
1371 let test_cases = [
1373 (KeyType::P256Private, "P-256"),
1374 (KeyType::P384Private, "P-384"),
1375 (KeyType::K256Private, "K-256"),
1376 ];
1377
1378 for (key_type, curve_name) in test_cases {
1379 let private_key = generate_key(key_type)?;
1381 let public_key = to_public(&private_key)?;
1382
1383 let private_jwk = generate(&private_key)?;
1384 let public_jwk = generate(&public_key)?;
1385
1386 let private_tp = thumbprint(&private_jwk)?;
1387 let public_tp = thumbprint(&public_jwk)?;
1388
1389 assert_eq!(
1391 private_tp, public_tp,
1392 "Thumbprint mismatch for {}",
1393 curve_name
1394 );
1395
1396 assert_eq!(
1398 private_tp.len(),
1399 43,
1400 "Invalid thumbprint length for {}",
1401 curve_name
1402 );
1403 assert!(
1404 !private_tp.contains('='),
1405 "Thumbprint contains padding for {}",
1406 curve_name
1407 );
1408 }
1409
1410 Ok(())
1411 }
1412
1413 #[test]
1414 fn test_thumbprint_comprehensive() -> Result<()> {
1415 let curves = [
1417 (KeyType::P256Private, "P-256"),
1418 (KeyType::P384Private, "P-384"),
1419 (KeyType::K256Private, "K-256"),
1420 ];
1421
1422 for (key_type, curve_name) in curves {
1423 let keys: Vec<_> = (0..5)
1425 .map(|_| generate_key(key_type.clone()))
1426 .collect::<Result<Vec<_>, _>>()?;
1427
1428 let mut thumbprints = Vec::new();
1429
1430 for (i, key) in keys.iter().enumerate() {
1431 let private_jwk = generate(key)?;
1432 let public_jwk = generate(&to_public(key)?)?;
1433
1434 let private_tp = thumbprint(&private_jwk)?;
1435 let public_tp = thumbprint(&public_jwk)?;
1436
1437 assert_eq!(
1439 private_tp, public_tp,
1440 "Thumbprint mismatch for {} key {}",
1441 curve_name, i
1442 );
1443
1444 assert!(
1446 !thumbprints.contains(&private_tp),
1447 "Duplicate thumbprint for {} key {}",
1448 curve_name,
1449 i
1450 );
1451
1452 thumbprints.push(private_tp);
1453 }
1454
1455 assert_eq!(
1457 thumbprints.len(),
1458 5,
1459 "Not all thumbprints are unique for {}",
1460 curve_name
1461 );
1462
1463 for tp in &thumbprints {
1465 assert_eq!(tp.len(), 43, "Invalid length for {} thumbprint", curve_name);
1466 assert!(
1467 !tp.contains(&['=', '+', '/'][..]),
1468 "Invalid characters in {} thumbprint",
1469 curve_name
1470 );
1471 }
1472 }
1473
1474 Ok(())
1475 }
1476}