Skip to main content

ssi_cose/
algorithm.rs

1use std::borrow::Cow;
2
3use coset::{
4    iana::{self, EnumI64},
5    Algorithm, CoseKey, KeyType,
6};
7use ssi_crypto::AlgorithmInstance;
8
9use crate::key::{CoseKeyDecode, EC2_CRV};
10
11/// Converts a COSE algorithm into an SSI algorithm instance.
12pub fn instantiate_algorithm(algorithm: &Algorithm) -> Option<AlgorithmInstance> {
13    match algorithm {
14        Algorithm::Assigned(iana::Algorithm::PS256) => Some(AlgorithmInstance::PS256),
15        Algorithm::Assigned(iana::Algorithm::PS384) => Some(AlgorithmInstance::PS384),
16        Algorithm::Assigned(iana::Algorithm::PS512) => Some(AlgorithmInstance::PS512),
17        Algorithm::Assigned(iana::Algorithm::EdDSA) => Some(AlgorithmInstance::EdDSA),
18        Algorithm::Assigned(iana::Algorithm::ES256K) => Some(AlgorithmInstance::ES256K),
19        Algorithm::Assigned(iana::Algorithm::ES256) => Some(AlgorithmInstance::ES256),
20        Algorithm::Assigned(iana::Algorithm::ES384) => Some(AlgorithmInstance::ES384),
21        _ => None,
22    }
23}
24
25/// Computes a proper display name for the give COSE algorithm.
26pub fn algorithm_name(algorithm: &Algorithm) -> String {
27    match algorithm {
28        Algorithm::Assigned(iana::Algorithm::PS256) => "PS256".to_owned(),
29        Algorithm::Assigned(iana::Algorithm::PS384) => "PS384".to_owned(),
30        Algorithm::Assigned(iana::Algorithm::PS512) => "PS512".to_owned(),
31        Algorithm::Assigned(iana::Algorithm::EdDSA) => "EdDSA".to_owned(),
32        Algorithm::Assigned(iana::Algorithm::ES256K) => "ES256K".to_owned(),
33        Algorithm::Assigned(iana::Algorithm::ES256) => "ES256".to_owned(),
34        Algorithm::Assigned(iana::Algorithm::ES384) => "ES384".to_owned(),
35        Algorithm::Assigned(i) => format!("assigned({})", i.to_i64()),
36        Algorithm::PrivateUse(i) => format!("private_use({i})"),
37        Algorithm::Text(text) => text.to_owned(),
38    }
39}
40
41/// Returns the preferred signature algorithm for the give COSE key.
42pub fn preferred_algorithm(key: &'_ CoseKey) -> Option<Cow<'_, Algorithm>> {
43    key.alg
44        .as_ref()
45        .map(Cow::Borrowed)
46        .or_else(|| match key.kty {
47            KeyType::Assigned(iana::KeyType::RSA) => {
48                Some(Cow::Owned(Algorithm::Assigned(iana::Algorithm::PS256)))
49            }
50            KeyType::Assigned(iana::KeyType::OKP) => {
51                let crv = key
52                    .parse_required_param(&EC2_CRV, |v| {
53                        v.as_integer().and_then(|i| i64::try_from(i).ok())
54                    })
55                    .ok()?;
56
57                match iana::EllipticCurve::from_i64(crv)? {
58                    iana::EllipticCurve::Ed25519 => {
59                        Some(Cow::Owned(Algorithm::Assigned(iana::Algorithm::EdDSA)))
60                    }
61                    _ => None,
62                }
63            }
64            KeyType::Assigned(iana::KeyType::EC2) => {
65                let crv = key
66                    .parse_required_param(&EC2_CRV, |v| {
67                        v.as_integer().and_then(|i| i64::try_from(i).ok())
68                    })
69                    .ok()?;
70
71                match iana::EllipticCurve::from_i64(crv)? {
72                    iana::EllipticCurve::Secp256k1 => {
73                        Some(Cow::Owned(Algorithm::Assigned(iana::Algorithm::ES256K)))
74                    }
75                    iana::EllipticCurve::P_256 => {
76                        Some(Cow::Owned(Algorithm::Assigned(iana::Algorithm::ES256)))
77                    }
78                    iana::EllipticCurve::P_384 => {
79                        Some(Cow::Owned(Algorithm::Assigned(iana::Algorithm::ES384)))
80                    }
81                    _ => None,
82                }
83            }
84            _ => None,
85        })
86}