1use coset::{
2 iana::{self, EnumI64},
3 CoseKey, KeyType, Label,
4};
5use ssi_claims_core::{ProofValidationError, SignatureError};
6use ssi_crypto::{
7 rand::{CryptoRng, RngCore},
8 PublicKey, SecretKey,
9};
10use std::borrow::Cow;
11
12use crate::{
13 algorithm::{algorithm_name, instantiate_algorithm, preferred_algorithm},
14 CoseSigner, CoseSignerInfo,
15};
16
17pub trait CoseKeyResolver {
19 #[allow(async_fn_in_trait)]
21 async fn fetch_public_cose_key(
22 &'_ self,
23 id: Option<&[u8]>,
24 ) -> Result<Cow<'_, CoseKey>, ProofValidationError>;
25}
26
27impl<T: CoseKeyResolver> CoseKeyResolver for &T {
28 async fn fetch_public_cose_key(
29 &'_ self,
30 id: Option<&[u8]>,
31 ) -> Result<Cow<'_, CoseKey>, ProofValidationError> {
32 T::fetch_public_cose_key(*self, id).await
33 }
34}
35
36impl CoseKeyResolver for CoseKey {
37 async fn fetch_public_cose_key(
38 &'_ self,
39 _id: Option<&[u8]>,
40 ) -> Result<Cow<'_, CoseKey>, ProofValidationError> {
41 Ok(Cow::Borrowed(self))
42 }
43}
44
45impl CoseSigner for CoseKey {
46 async fn fetch_info(&self) -> Result<CoseSignerInfo, ssi_claims_core::SignatureError> {
47 Ok(CoseSignerInfo {
48 algorithm: preferred_algorithm(self).map(Cow::into_owned),
49 key_id: self.key_id.clone(),
50 })
51 }
52
53 async fn sign_bytes(&self, signing_bytes: &[u8]) -> Result<Vec<u8>, SignatureError> {
54 let algorithm = preferred_algorithm(self).ok_or(SignatureError::MissingAlgorithm)?;
55 let secret_key = self.decode_secret()?;
56 secret_key
57 .sign(
58 instantiate_algorithm(&algorithm).ok_or_else(|| {
59 SignatureError::UnsupportedAlgorithm(algorithm_name(&algorithm))
60 })?,
61 signing_bytes,
62 )
63 .map_err(Into::into)
64 }
65}
66
67#[derive(Debug, thiserror::Error)]
68pub enum KeyDecodingError {
69 #[error("unsupported key type")]
70 UnsupportedKeyType(KeyType),
71
72 #[error("missing parameter")]
73 MissingParam(Label),
74
75 #[error("invalid parameter")]
76 InvalidParam(Label),
77
78 #[error("unsupported parameter value")]
79 UnsupportedParam(Label, ciborium::Value),
80
81 #[error("invalid key")]
82 InvalidKey,
83}
84
85impl From<ssi_crypto::key::InvalidPublicKey> for KeyDecodingError {
86 fn from(_value: ssi_crypto::key::InvalidPublicKey) -> Self {
87 Self::InvalidKey
88 }
89}
90
91impl From<ssi_crypto::key::InvalidSecretKey> for KeyDecodingError {
92 fn from(_value: ssi_crypto::key::InvalidSecretKey) -> Self {
93 Self::InvalidKey
94 }
95}
96
97impl From<KeyDecodingError> for ssi_claims_core::SignatureError {
98 fn from(_value: KeyDecodingError) -> Self {
99 Self::InvalidSecretKey
100 }
101}
102
103pub trait CoseKeyDecode {
105 fn fetch_param(&self, label: &Label) -> Option<&ciborium::Value>;
107
108 fn require_param(&self, label: &Label) -> Result<&ciborium::Value, KeyDecodingError> {
112 self.fetch_param(label)
113 .ok_or_else(|| KeyDecodingError::MissingParam(label.clone()))
114 }
115
116 fn parse_required_param<'a, T>(
121 &'a self,
122 label: &Label,
123 f: impl FnOnce(&'a ciborium::Value) -> Option<T>,
124 ) -> Result<T, KeyDecodingError> {
125 f(self.require_param(label)?).ok_or_else(|| KeyDecodingError::InvalidParam(label.clone()))
126 }
127
128 fn decode_public(&self) -> Result<ssi_crypto::PublicKey, KeyDecodingError>;
130
131 fn decode_secret(&self) -> Result<ssi_crypto::SecretKey, KeyDecodingError>;
133}
134
135impl CoseKeyDecode for CoseKey {
136 fn fetch_param(&self, label: &Label) -> Option<&ciborium::Value> {
138 self.params
139 .iter()
140 .find_map(|(l, value)| if l == label { Some(value) } else { None })
141 }
142
143 fn decode_public(&self) -> Result<ssi_crypto::PublicKey, KeyDecodingError> {
144 match &self.kty {
145 t @ KeyType::Assigned(kty) => {
146 match kty {
147 iana::KeyType::OKP => {
149 let crv = self.parse_required_param(&OKP_CRV, |v| {
150 v.as_integer().and_then(|i| i64::try_from(i).ok())
151 })?;
152
153 #[allow(unused_variables)]
154 let x = self.parse_required_param(&OKP_X, ciborium::Value::as_bytes)?;
155
156 match iana::EllipticCurve::from_i64(crv) {
157 #[cfg(feature = "ed25519")]
158 Some(iana::EllipticCurve::Ed25519) => {
159 ssi_crypto::PublicKey::new_ed25519(x).map_err(Into::into)
160 }
161 _ => Err(KeyDecodingError::UnsupportedParam(EC2_CRV, crv.into())),
162 }
163 }
164 iana::KeyType::EC2 => {
167 let crv = self.parse_required_param(&EC2_CRV, |v| {
168 v.as_integer().and_then(|i| i64::try_from(i).ok())
169 })?;
170
171 #[allow(unused_variables)]
172 let x = self.parse_required_param(&EC2_X, ciborium::Value::as_bytes)?;
173
174 #[allow(unused_variables)]
175 let y = self.parse_required_param(
176 &EC2_Y,
177 ciborium::Value::as_bytes, )?;
179
180 match iana::EllipticCurve::from_i64(crv) {
181 #[cfg(feature = "secp256k1")]
182 Some(iana::EllipticCurve::Secp256k1) => {
183 ssi_crypto::PublicKey::new_secp256k1(x, y).map_err(Into::into)
184 }
185 #[cfg(feature = "secp256r1")]
186 Some(iana::EllipticCurve::P_256) => {
187 ssi_crypto::PublicKey::new_p256(x, y).map_err(Into::into)
188 }
189 #[cfg(feature = "secp384r1")]
190 Some(iana::EllipticCurve::P_384) => {
191 ssi_crypto::PublicKey::new_p384(x, y).map_err(Into::into)
192 }
193 _ => Err(KeyDecodingError::UnsupportedParam(EC2_CRV, crv.into())),
194 }
195 }
196 _ => Err(KeyDecodingError::UnsupportedKeyType(t.clone())),
197 }
198 }
199 other => Err(KeyDecodingError::UnsupportedKeyType(other.clone())),
200 }
201 }
202
203 fn decode_secret(&self) -> Result<ssi_crypto::SecretKey, KeyDecodingError> {
204 match &self.kty {
205 t @ KeyType::Assigned(kty) => {
206 match kty {
207 iana::KeyType::OKP => {
209 let crv = self.parse_required_param(&OKP_CRV, |v| {
210 v.as_integer().and_then(|i| i64::try_from(i).ok())
211 })?;
212
213 #[allow(unused_variables)]
214 let d = self.parse_required_param(&OKP_D, ciborium::Value::as_bytes)?;
215
216 match iana::EllipticCurve::from_i64(crv) {
217 #[cfg(feature = "ed25519")]
218 Some(iana::EllipticCurve::Ed25519) => {
219 ssi_crypto::SecretKey::new_ed25519(d).map_err(Into::into)
220 }
221 _ => Err(KeyDecodingError::UnsupportedParam(EC2_CRV, crv.into())),
222 }
223 }
224 iana::KeyType::EC2 => {
227 let crv = self.parse_required_param(&EC2_CRV, |v| {
228 v.as_integer().and_then(|i| i64::try_from(i).ok())
229 })?;
230
231 #[allow(unused_variables)]
232 let d = self.parse_required_param(&EC2_D, ciborium::Value::as_bytes)?;
233
234 match iana::EllipticCurve::from_i64(crv) {
235 #[cfg(feature = "secp256k1")]
236 Some(iana::EllipticCurve::Secp256k1) => {
237 ssi_crypto::SecretKey::new_secp256k1(d).map_err(Into::into)
238 }
239 #[cfg(feature = "secp256r1")]
240 Some(iana::EllipticCurve::P_256) => {
241 ssi_crypto::SecretKey::new_p256(d).map_err(Into::into)
242 }
243 #[cfg(feature = "secp384r1")]
244 Some(iana::EllipticCurve::P_384) => {
245 ssi_crypto::SecretKey::new_p384(d).map_err(Into::into)
246 }
247 _ => Err(KeyDecodingError::UnsupportedParam(EC2_CRV, crv.into())),
248 }
249 }
250 _ => Err(KeyDecodingError::UnsupportedKeyType(t.clone())),
251 }
252 }
253 other => Err(KeyDecodingError::UnsupportedKeyType(other.clone())),
254 }
255 }
256}
257
258pub const OKP_CRV: Label = Label::Int(iana::OkpKeyParameter::Crv as i64);
259pub const OKP_X: Label = Label::Int(iana::OkpKeyParameter::X as i64);
260pub const OKP_D: Label = Label::Int(iana::OkpKeyParameter::D as i64);
261
262pub const EC2_CRV: Label = Label::Int(iana::Ec2KeyParameter::Crv as i64);
263pub const EC2_X: Label = Label::Int(iana::Ec2KeyParameter::X as i64);
264pub const EC2_Y: Label = Label::Int(iana::Ec2KeyParameter::Y as i64);
265pub const EC2_D: Label = Label::Int(iana::Ec2KeyParameter::D as i64);
266
267#[derive(Debug, thiserror::Error)]
268pub enum KeyEncodingError {
269 #[error("unsupported key type")]
270 UnsupportedKeyType,
271}
272
273pub trait CoseKeyEncode: Sized {
275 fn encode_public(key: &PublicKey) -> Result<CoseKey, KeyEncodingError>;
276
277 fn encode_public_with_id(key: &PublicKey, id: Vec<u8>) -> Result<CoseKey, KeyEncodingError> {
278 let mut cose_key = Self::encode_public(key)?;
279 cose_key.key_id = id;
280 Ok(cose_key)
281 }
282
283 fn encode_secret(key: &SecretKey) -> Result<CoseKey, KeyEncodingError>;
284
285 fn encode_secret_with_id(key: &SecretKey, id: Vec<u8>) -> Result<CoseKey, KeyEncodingError> {
286 let mut cose_key = Self::encode_secret(key)?;
287 cose_key.key_id = id;
288 Ok(cose_key)
289 }
290}
291
292impl CoseKeyEncode for CoseKey {
293 fn encode_public(key: &PublicKey) -> Result<Self, KeyEncodingError> {
294 match key {
295 #[cfg(feature = "ed25519")]
296 PublicKey::Ed25519(key) => Ok(Self {
297 kty: KeyType::Assigned(iana::KeyType::OKP),
298 params: vec![
299 (OKP_CRV, iana::EllipticCurve::Ed25519.to_i64().into()),
300 (OKP_X, key.as_bytes().to_vec().into()),
301 ],
302 ..Default::default()
303 }),
304 #[cfg(feature = "secp256k1")]
305 PublicKey::Secp256k1(key) => {
306 use ssi_crypto::k256::elliptic_curve::sec1::ToEncodedPoint;
307 let encoded_point = key.to_encoded_point(false);
308 Ok(Self {
309 kty: KeyType::Assigned(iana::KeyType::EC2),
310 params: vec![
311 (EC2_CRV, iana::EllipticCurve::Secp256k1.to_i64().into()),
312 (EC2_X, encoded_point.x().unwrap().to_vec().into()),
313 (EC2_Y, encoded_point.y().unwrap().to_vec().into()),
314 ],
315 ..Default::default()
316 })
317 }
318 #[cfg(feature = "secp256r1")]
319 PublicKey::P256(key) => {
320 use ssi_crypto::p256::elliptic_curve::sec1::ToEncodedPoint;
321 let encoded_point = key.to_encoded_point(false);
322 Ok(Self {
323 kty: KeyType::Assigned(iana::KeyType::EC2),
324 params: vec![
325 (EC2_CRV, iana::EllipticCurve::P_256.to_i64().into()),
326 (EC2_X, encoded_point.x().unwrap().to_vec().into()),
327 (EC2_Y, encoded_point.y().unwrap().to_vec().into()),
328 ],
329 ..Default::default()
330 })
331 }
332 #[cfg(feature = "secp384r1")]
333 PublicKey::P384(key) => {
334 use ssi_crypto::p384::elliptic_curve::sec1::ToEncodedPoint;
335 let encoded_point = key.to_encoded_point(false);
336 Ok(Self {
337 kty: KeyType::Assigned(iana::KeyType::EC2),
338 params: vec![
339 (EC2_CRV, iana::EllipticCurve::P_384.to_i64().into()),
340 (EC2_X, encoded_point.x().unwrap().to_vec().into()),
341 (EC2_Y, encoded_point.y().unwrap().to_vec().into()),
342 ],
343 ..Default::default()
344 })
345 }
346 _ => Err(KeyEncodingError::UnsupportedKeyType),
347 }
348 }
349
350 fn encode_secret(key: &SecretKey) -> Result<Self, KeyEncodingError> {
351 match key {
352 #[cfg(feature = "ed25519")]
353 SecretKey::Ed25519(key) => {
354 let public_key = key.verifying_key();
355 Ok(Self {
356 kty: KeyType::Assigned(iana::KeyType::OKP),
357 params: vec![
358 (OKP_CRV, iana::EllipticCurve::Ed25519.to_i64().into()),
359 (OKP_X, public_key.as_bytes().to_vec().into()),
360 (OKP_D, key.to_bytes().to_vec().into()),
361 ],
362 ..Default::default()
363 })
364 }
365 #[cfg(feature = "secp256k1")]
366 SecretKey::Secp256k1(key) => {
367 use ssi_crypto::k256::elliptic_curve::sec1::ToEncodedPoint;
368 let public_key = key.public_key();
369 let encoded_point = public_key.to_encoded_point(false);
370 Ok(Self {
371 kty: KeyType::Assigned(iana::KeyType::EC2),
372 params: vec![
373 (EC2_CRV, iana::EllipticCurve::Secp256k1.to_i64().into()),
374 (EC2_X, encoded_point.x().unwrap().to_vec().into()),
375 (EC2_Y, encoded_point.y().unwrap().to_vec().into()),
376 (EC2_D, key.to_bytes().to_vec().into()),
377 ],
378 ..Default::default()
379 })
380 }
381 #[cfg(feature = "secp256r1")]
382 SecretKey::P256(key) => {
383 use ssi_crypto::p256::elliptic_curve::sec1::ToEncodedPoint;
384 let public_key = key.public_key();
385 let encoded_point = public_key.to_encoded_point(false);
386 Ok(Self {
387 kty: KeyType::Assigned(iana::KeyType::EC2),
388 params: vec![
389 (EC2_CRV, iana::EllipticCurve::P_256.to_i64().into()),
390 (EC2_X, encoded_point.x().unwrap().to_vec().into()),
391 (EC2_Y, encoded_point.y().unwrap().to_vec().into()),
392 (EC2_D, key.to_bytes().to_vec().into()),
393 ],
394 ..Default::default()
395 })
396 }
397 #[cfg(feature = "secp384r1")]
398 SecretKey::P384(key) => {
399 use ssi_crypto::p384::elliptic_curve::sec1::ToEncodedPoint;
400 let public_key = key.public_key();
401 let encoded_point = public_key.to_encoded_point(false);
402 Ok(Self {
403 kty: KeyType::Assigned(iana::KeyType::EC2),
404 params: vec![
405 (EC2_CRV, iana::EllipticCurve::P_384.to_i64().into()),
406 (EC2_X, encoded_point.x().unwrap().to_vec().into()),
407 (EC2_Y, encoded_point.y().unwrap().to_vec().into()),
408 (EC2_D, key.to_bytes().to_vec().into()),
409 ],
410 ..Default::default()
411 })
412 }
413 _ => Err(KeyEncodingError::UnsupportedKeyType),
414 }
415 }
416}
417
418pub trait CoseKeyGenerate {
419 #[cfg(feature = "ed25519")]
420 fn generate_ed25519() -> Self;
421
422 #[cfg(feature = "ed25519")]
423 fn generate_ed25519_from(rng: &mut (impl RngCore + CryptoRng)) -> Self;
424
425 #[cfg(feature = "secp256k1")]
426 fn generate_secp256k1() -> Self;
427
428 #[cfg(feature = "secp256k1")]
429 fn generate_secp256k1_from(rng: &mut (impl RngCore + CryptoRng)) -> Self;
430
431 #[cfg(feature = "secp256r1")]
432 fn generate_p256() -> Self;
433
434 #[cfg(feature = "secp256r1")]
435 fn generate_p256_from(rng: &mut (impl RngCore + CryptoRng)) -> Self;
436
437 #[cfg(feature = "secp384r1")]
438 fn generate_p384() -> Self;
439
440 #[cfg(feature = "secp384r1")]
441 fn generate_p384_from(rng: &mut (impl RngCore + CryptoRng)) -> Self;
442}
443
444impl CoseKeyGenerate for CoseKey {
445 #[cfg(feature = "ed25519")]
446 fn generate_ed25519() -> Self {
447 Self::encode_secret(&ssi_crypto::SecretKey::generate_ed25519()).unwrap()
448 }
449
450 #[cfg(feature = "ed25519")]
451 fn generate_ed25519_from(rng: &mut (impl RngCore + CryptoRng)) -> Self {
452 Self::encode_secret(&ssi_crypto::SecretKey::generate_ed25519_from(rng)).unwrap()
453 }
454
455 #[cfg(feature = "secp256k1")]
456 fn generate_secp256k1() -> Self {
457 Self::encode_secret(&ssi_crypto::SecretKey::generate_secp256k1()).unwrap()
458 }
459
460 #[cfg(feature = "secp256k1")]
461 fn generate_secp256k1_from(rng: &mut (impl RngCore + CryptoRng)) -> Self {
462 Self::encode_secret(&ssi_crypto::SecretKey::generate_secp256k1_from(rng)).unwrap()
463 }
464
465 #[cfg(feature = "secp256r1")]
466 fn generate_p256() -> Self {
467 Self::encode_secret(&ssi_crypto::SecretKey::generate_p256()).unwrap()
468 }
469
470 #[cfg(feature = "secp256r1")]
471 fn generate_p256_from(rng: &mut (impl RngCore + CryptoRng)) -> Self {
472 Self::encode_secret(&ssi_crypto::SecretKey::generate_p256_from(rng)).unwrap()
473 }
474
475 #[cfg(feature = "secp384r1")]
476 fn generate_p384() -> Self {
477 Self::encode_secret(&ssi_crypto::SecretKey::generate_p384()).unwrap()
478 }
479
480 #[cfg(feature = "secp384r1")]
481 fn generate_p384_from(rng: &mut (impl RngCore + CryptoRng)) -> Self {
482 Self::encode_secret(&ssi_crypto::SecretKey::generate_p384_from(rng)).unwrap()
483 }
484}
485
486#[cfg(test)]
487mod tests {
488 use super::{CoseKeyDecode, CoseKeyEncode};
489 use coset::{CborSerializable, CoseKey};
490 use ssi_crypto::{PublicKey, SecretKey};
491
492 #[cfg(feature = "ed25519")]
502 #[test]
503 fn public_ed25519_1() {
504 let input = hex::decode(
505 "a3010120062158208816d41001dd1a9ddea1232381b2eede803161e88ebb19eaf573d393dec800a7",
506 )
507 .unwrap();
508 let cose_key = CoseKey::from_slice(&input).unwrap();
509 let key = cose_key.decode_public().unwrap();
510 assert!(matches!(key, PublicKey::Ed25519(_)));
511 assert_eq!(
512 CoseKey::encode_public_with_id(&key, cose_key.key_id.clone()).unwrap(),
513 cose_key
514 )
515 }
516
517 #[cfg(feature = "ed25519")]
528 #[test]
529 fn secret_ed25519_1() {
530 let input = hex::decode("a4010120062158208816d41001dd1a9ddea1232381b2eede803161e88ebb19eaf573d393dec800a7235820e25df1249ab766fc5a8c9f98d5e311cd4f7d5fd1c6b6a2032adc973056c87dc3").unwrap();
531 let cose_key = CoseKey::from_slice(&input).unwrap();
532 let key = cose_key.decode_secret().unwrap();
533 assert!(matches!(key, SecretKey::Ed25519(_)));
534 assert_eq!(
535 CoseKey::encode_secret_with_id(&key, cose_key.key_id.clone()).unwrap(),
536 cose_key
537 )
538 }
539
540 #[cfg(feature = "secp256k1")]
551 #[test]
552 fn public_secp256k1_1() {
553 let input = hex::decode("a401022008215820394fd5a1e33b8a67d5fa9ddca42d261219dde202e65bbf07bf2f671e157ac41f225820199d7db667e74905c8371168b815c267db76243fbfd387fa5f2d8a691099a89a").unwrap();
554 let cose_key = CoseKey::from_slice(&input).unwrap();
555 let key = cose_key.decode_public().unwrap();
556 assert!(matches!(key, PublicKey::Secp256k1(_)));
557 assert_eq!(
558 CoseKey::encode_public_with_id(&key, cose_key.key_id.clone()).unwrap(),
559 cose_key
560 )
561 }
562
563 #[cfg(feature = "secp256k1")]
575 #[test]
576 fn secret_secp256k1_1() {
577 let input = hex::decode("a501022008215820394fd5a1e33b8a67d5fa9ddca42d261219dde202e65bbf07bf2f671e157ac41f225820199d7db667e74905c8371168b815c267db76243fbfd387fa5f2d8a691099a89a2358203e0fada8be75e5e47ab4c1c91c3f8f9185d1e18a2a16b3400a1eb33c9cdf8b96").unwrap();
578 let cose_key = CoseKey::from_slice(&input).unwrap();
579 let key = cose_key.decode_secret().unwrap();
580 assert!(matches!(key, SecretKey::Secp256k1(_)));
581 assert_eq!(
582 CoseKey::encode_secret_with_id(&key, cose_key.key_id.clone()).unwrap(),
583 cose_key
584 )
585 }
586
587 #[cfg(feature = "secp256r1")]
592 #[test]
593 fn public_p256_1() {
594 let input = hex::decode("a5200121582065eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d2258201e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c01020258246d65726961646f632e6272616e64796275636b406275636b6c616e642e6578616d706c65").unwrap();
595 let cose_key = CoseKey::from_slice(&input).unwrap();
596 let key = cose_key.decode_public().unwrap();
597 assert!(matches!(key, PublicKey::P256(_)));
598 assert_eq!(
599 CoseKey::encode_public_with_id(&key, cose_key.key_id.clone()).unwrap(),
600 cose_key
601 )
602 }
603
604 #[cfg(feature = "secp256r1")]
609 #[test]
610 fn secret_p256_1() {
611 let input = hex::decode("a601020258246d65726961646f632e6272616e64796275636b406275636b6c616e642e6578616d706c65200121582065eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d2258201e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c235820aff907c99f9ad3aae6c4cdf21122bce2bd68b5283e6907154ad911840fa208cf").unwrap();
612 let cose_key = CoseKey::from_slice(&input).unwrap();
613 let key = cose_key.decode_secret().unwrap();
614 assert!(matches!(key, SecretKey::P256(_)));
615 assert_eq!(
616 CoseKey::encode_secret_with_id(&key, cose_key.key_id.clone()).unwrap(),
617 cose_key
618 )
619 }
620
621 #[cfg(feature = "secp256r1")]
625 #[test]
626 fn public_p256_2() {
627 let input = hex::decode("a52001215820bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff22582020138bf82dc1b6d562be0fa54ab7804a3a64b6d72ccfed6b6fb6ed28bbfc117e010202423131").unwrap();
628 let cose_key = CoseKey::from_slice(&input).unwrap();
629 let key = cose_key.decode_public().unwrap();
630 assert!(matches!(key, PublicKey::P256(_)));
631 assert_eq!(
632 CoseKey::encode_public_with_id(&key, cose_key.key_id.clone()).unwrap(),
633 cose_key
634 )
635 }
636
637 #[cfg(feature = "secp256r1")]
641 #[test]
642 fn secret_p256_2() {
643 let input = hex::decode("a60102024231312001215820bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff22582020138bf82dc1b6d562be0fa54ab7804a3a64b6d72ccfed6b6fb6ed28bbfc117e23582057c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3").unwrap();
644 let cose_key = CoseKey::from_slice(&input).unwrap();
645 let key = cose_key.decode_secret().unwrap();
646 assert!(matches!(key, SecretKey::P256(_)));
647 assert_eq!(
648 CoseKey::encode_secret_with_id(&key, cose_key.key_id.clone()).unwrap(),
649 cose_key
650 )
651 }
652
653 #[cfg(feature = "secp256r1")]
657 #[test]
658 fn public_p256_3() {
659 let input = hex::decode("a5200121582098f50a4ff6c05861c8860d13a638ea56c3f5ad7590bbfbf054e1c7b4d91d6280225820f01400b089867804b8e9fc96c3932161f1934f4223069170d924b7e03bf822bb0102025821706572656772696e2e746f6f6b407475636b626f726f7567682e6578616d706c65").unwrap();
660 let cose_key = CoseKey::from_slice(&input).unwrap();
661 let key = cose_key.decode_public().unwrap();
662 assert!(matches!(key, PublicKey::P256(_)));
663 assert_eq!(
664 CoseKey::encode_public_with_id(&key, cose_key.key_id.clone()).unwrap(),
665 cose_key
666 )
667 }
668
669 #[cfg(feature = "secp256r1")]
674 #[test]
675 fn secret_p256_3() {
676 let input = hex::decode("a601022001025821706572656772696e2e746f6f6b407475636b626f726f7567682e6578616d706c6521582098f50a4ff6c05861c8860d13a638ea56c3f5ad7590bbfbf054e1c7b4d91d6280225820f01400b089867804b8e9fc96c3932161f1934f4223069170d924b7e03bf822bb23582002d1f7e6f26c43d4868d87ceb2353161740aacf1f7163647984b522a848df1c3").unwrap();
677 let cose_key = CoseKey::from_slice(&input).unwrap();
678 let key = cose_key.decode_secret().unwrap();
679 assert!(matches!(key, SecretKey::P256(_)));
680 assert_eq!(
681 CoseKey::encode_secret_with_id(&key, cose_key.key_id.clone()).unwrap(),
682 cose_key
683 )
684 }
685
686 #[cfg(feature = "secp384r1")]
697 #[test]
698 fn public_p384_1() {
699 let input = hex::decode("a401022002215830fa1d31d39853d37fbfd145675635d52795f5feb3eacf11371ad8c6eb30c6f2493b0ec74d8c5b5a20ebf68ce3e0bd2c072258307c2b27b366e4fc73b79d28bac0b18ae2f2b0c4e7849656a71aac8987e60af5af57a9af3faf206afc798fa5fb06db15aa").unwrap();
700 let cose_key = CoseKey::from_slice(&input).unwrap();
701 let key = cose_key.decode_public().unwrap();
702 assert!(matches!(key, PublicKey::P384(_)));
703 assert_eq!(
704 CoseKey::encode_public_with_id(&key, cose_key.key_id.clone()).unwrap(),
705 cose_key
706 )
707 }
708
709 #[cfg(feature = "secp384r1")]
721 #[test]
722 fn secret_p384_1() {
723 let input = hex::decode("a501022002215830fa1d31d39853d37fbfd145675635d52795f5feb3eacf11371ad8c6eb30c6f2493b0ec74d8c5b5a20ebf68ce3e0bd2c072258307c2b27b366e4fc73b79d28bac0b18ae2f2b0c4e7849656a71aac8987e60af5af57a9af3faf206afc798fa5fb06db15aa23583021d8eb2250cdaa19bfb01f03211be11a70ef4739650ed954166531808aa254c1d6d968b36d16184d350600253fa672c0").unwrap();
724 let cose_key = CoseKey::from_slice(&input).unwrap();
725 let key = cose_key.decode_secret().unwrap();
726 assert!(matches!(key, SecretKey::P384(_)));
727 assert_eq!(
728 CoseKey::encode_secret_with_id(&key, cose_key.key_id.clone()).unwrap(),
729 cose_key
730 )
731 }
732}