identity_jose/jwk/
composite_jwk.rs1use std::fmt::Display;
5use std::str::FromStr;
6
7use crate::jwk::PostQuantumJwk;
8use crate::jwk::TraditionalJwk;
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
12#[non_exhaustive]
13pub enum CompositeAlgId {
14 #[serde(rename = "id-MLDSA44-Ed25519")]
16 IdMldsa44Ed25519,
17 #[serde(rename = "id-MLDSA65-Ed25519")]
19 IdMldsa65Ed25519,
20}
21
22impl CompositeAlgId {
23 pub const fn name(self) -> &'static str {
25 match self {
26 Self::IdMldsa44Ed25519 => "id-MLDSA44-Ed25519",
27 Self::IdMldsa65Ed25519 => "id-MLDSA65-Ed25519",
28 }
29 }
30
31 pub const fn domain(self) -> &'static [u8] {
33 match self {
34 Self::IdMldsa44Ed25519 => &[
35 0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x08, 0x01, 0x3E,
36 ],
37 Self::IdMldsa65Ed25519 => &[
38 0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x08, 0x01, 0x47,
39 ],
40 }
41 }
42
43 pub const COMPOSITE_SIGNATURE_PREFIX: &[u8] = b"CompositeAlgorithmSignatures2025";
45}
46
47#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
49#[serde(rename_all = "camelCase")]
50pub struct CompositeJwk {
51 alg_id: CompositeAlgId,
52 traditional_public_key: TraditionalJwk,
53 pq_public_key: PostQuantumJwk,
54}
55
56impl CompositeJwk {
57 pub fn new(alg_id: CompositeAlgId, traditional_public_key: TraditionalJwk, pq_public_key: PostQuantumJwk) -> Self {
59 Self {
60 alg_id,
61 traditional_public_key: traditional_public_key.into_public().unwrap(),
62 pq_public_key: pq_public_key.into_public().unwrap(),
63 }
64 }
65 pub fn alg_id(&self) -> CompositeAlgId {
67 self.alg_id
68 }
69 pub fn pq_public_key(&self) -> &PostQuantumJwk {
71 &self.pq_public_key
72 }
73 pub fn traditional_public_key(&self) -> &TraditionalJwk {
75 &self.traditional_public_key
76 }
77}
78
79impl FromStr for CompositeAlgId {
80 type Err = CompositeAlgParsingError;
81
82 fn from_str(string: &str) -> std::result::Result<Self, Self::Err> {
83 match string {
84 "id-MLDSA44-Ed25519" => Ok(Self::IdMldsa44Ed25519),
85 "id-MLDSA65-Ed25519" => Ok(Self::IdMldsa65Ed25519),
86 invalid => Err(CompositeAlgParsingError {
87 input: invalid.to_owned(),
88 }),
89 }
90 }
91}
92
93#[derive(Debug, thiserror::Error)]
95#[non_exhaustive]
96pub struct CompositeAlgParsingError {
97 pub input: String,
99}
100
101impl Display for CompositeAlgParsingError {
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 write!(
104 f,
105 "invalid CompositeAlgId `{}`; valid values are: `{}`, `{}`",
106 self.input,
107 CompositeAlgId::IdMldsa44Ed25519.name(),
108 CompositeAlgId::IdMldsa65Ed25519.name()
109 )
110 }
111}
112
113impl From<CompositeAlgParsingError> for crate::error::Error {
114 fn from(_: CompositeAlgParsingError) -> Self {
115 crate::error::Error::JwsAlgorithmParsingError
116 }
117}