#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CoseAlg {
Es256,
Es384,
Es512,
Ps256,
Ps384,
Ps512,
EdDsa,
Esp256,
Esp384,
Esp512,
MlDsa44,
MlDsa65,
MlDsa87,
}
impl CoseAlg {
pub const ALL: [CoseAlg; 13] = [
CoseAlg::Es256,
CoseAlg::Es384,
CoseAlg::Es512,
CoseAlg::Ps256,
CoseAlg::Ps384,
CoseAlg::Ps512,
CoseAlg::EdDsa,
CoseAlg::Esp256,
CoseAlg::Esp384,
CoseAlg::Esp512,
CoseAlg::MlDsa44,
CoseAlg::MlDsa65,
CoseAlg::MlDsa87,
];
pub fn cose_id(self) -> i128 {
match self {
CoseAlg::Es256 => -7,
CoseAlg::Es384 => -35,
CoseAlg::Es512 => -36,
CoseAlg::Ps256 => -37,
CoseAlg::Ps384 => -38,
CoseAlg::Ps512 => -39,
CoseAlg::EdDsa => -8,
CoseAlg::Esp256 => -9,
CoseAlg::Esp384 => -51,
CoseAlg::Esp512 => -52,
CoseAlg::MlDsa44 => -48,
CoseAlg::MlDsa65 => -49,
CoseAlg::MlDsa87 => -50,
}
}
pub fn from_cose_id(id: i128) -> Option<Self> {
Self::ALL.into_iter().find(|alg| alg.cose_id() == id)
}
pub fn iana_name(self) -> &'static str {
match self {
CoseAlg::Es256 => "ES256",
CoseAlg::Es384 => "ES384",
CoseAlg::Es512 => "ES512",
CoseAlg::Ps256 => "PS256",
CoseAlg::Ps384 => "PS384",
CoseAlg::Ps512 => "PS512",
CoseAlg::EdDsa => "EdDSA",
CoseAlg::Esp256 => "ESP256",
CoseAlg::Esp384 => "ESP384",
CoseAlg::Esp512 => "ESP512",
CoseAlg::MlDsa44 => "ML-DSA-44",
CoseAlg::MlDsa65 => "ML-DSA-65",
CoseAlg::MlDsa87 => "ML-DSA-87",
}
}
pub fn introduced_in_c2pa_2_5(self) -> bool {
matches!(
self,
CoseAlg::Esp256
| CoseAlg::Esp384
| CoseAlg::Esp512
| CoseAlg::MlDsa44
| CoseAlg::MlDsa65
| CoseAlg::MlDsa87
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn every_known_id_round_trips() {
for alg in CoseAlg::ALL {
assert_eq!(CoseAlg::from_cose_id(alg.cose_id()), Some(alg));
}
}
#[test]
fn known_ids_match_registry() {
let expected = [
(CoseAlg::Es256, -7, "ES256"),
(CoseAlg::Es384, -35, "ES384"),
(CoseAlg::Es512, -36, "ES512"),
(CoseAlg::Ps256, -37, "PS256"),
(CoseAlg::Ps384, -38, "PS384"),
(CoseAlg::Ps512, -39, "PS512"),
(CoseAlg::EdDsa, -8, "EdDSA"),
(CoseAlg::Esp256, -9, "ESP256"),
(CoseAlg::Esp384, -51, "ESP384"),
(CoseAlg::Esp512, -52, "ESP512"),
(CoseAlg::MlDsa44, -48, "ML-DSA-44"),
(CoseAlg::MlDsa65, -49, "ML-DSA-65"),
(CoseAlg::MlDsa87, -50, "ML-DSA-87"),
];
for (alg, id, name) in expected {
assert_eq!(alg.cose_id(), id);
assert_eq!(alg.iana_name(), name);
}
}
#[test]
fn unknown_id_is_none() {
assert_eq!(CoseAlg::from_cose_id(0), None);
assert_eq!(CoseAlg::from_cose_id(-100), None);
assert_eq!(CoseAlg::from_cose_id(-19), None);
assert_eq!(CoseAlg::from_cose_id(-53), None);
}
}