1use thiserror::Error;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum CodecNameReason {
10 Unsupported,
12}
13
14impl core::fmt::Display for CodecNameReason {
15 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
16 let detail = match self {
17 CodecNameReason::Unsupported => "unsupported codec name",
18 };
19 write!(f, "{detail}")
20 }
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25pub enum BindingTypeKind {
26 Multikey,
28 P256Key2024,
30 P384Key2024,
32 P521Key2024,
34 RsaVerificationKey2024,
36 MlDsa44Key2024,
38 MlDsa65Key2024,
40 MlDsa87Key2024,
42 MlKem512Key2024,
44 MlKem768Key2024,
46 MlKem1024Key2024,
48 Unsupported,
50}
51
52impl core::fmt::Display for BindingTypeKind {
53 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
54 let detail = match self {
55 BindingTypeKind::Multikey => "Multikey",
56 BindingTypeKind::P256Key2024 => "P256Key2024",
57 BindingTypeKind::P384Key2024 => "P384Key2024",
58 BindingTypeKind::P521Key2024 => "P521Key2024",
59 BindingTypeKind::RsaVerificationKey2024 => "RsaVerificationKey2024",
60 BindingTypeKind::MlDsa44Key2024 => "ML_DSA_44Key2024",
61 BindingTypeKind::MlDsa65Key2024 => "ML_DSA_65Key2024",
62 BindingTypeKind::MlDsa87Key2024 => "ML_DSA_87Key2024",
63 BindingTypeKind::MlKem512Key2024 => "MLKEM512Key2024",
64 BindingTypeKind::MlKem768Key2024 => "MLKEM768Key2024",
65 BindingTypeKind::MlKem1024Key2024 => "MLKEM1024Key2024",
66 BindingTypeKind::Unsupported => "unsupported binding type",
67 };
68 write!(f, "{detail}")
69 }
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum BindingAlgorithmKind {
75 Ed25519,
77 Ed448,
79 X25519,
81 P256,
83 P384,
85 P521,
87 Rsa,
89 Secp256k1,
91 MlDsa44,
93 MlDsa65,
95 MlDsa87,
97 MlKem512,
99 MlKem768,
101 MlKem1024,
103 Unsupported,
105}
106
107impl core::fmt::Display for BindingAlgorithmKind {
108 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
109 let detail = match self {
110 BindingAlgorithmKind::Ed25519 => "Ed25519",
111 BindingAlgorithmKind::Ed448 => "Ed448",
112 BindingAlgorithmKind::X25519 => "X25519",
113 BindingAlgorithmKind::P256 => "P-256",
114 BindingAlgorithmKind::P384 => "P-384",
115 BindingAlgorithmKind::P521 => "P-521",
116 BindingAlgorithmKind::Rsa => "RSA",
117 BindingAlgorithmKind::Secp256k1 => "secp256k1",
118 BindingAlgorithmKind::MlDsa44 => "ML-DSA-44",
119 BindingAlgorithmKind::MlDsa65 => "ML-DSA-65",
120 BindingAlgorithmKind::MlDsa87 => "ML-DSA-87",
121 BindingAlgorithmKind::MlKem512 => "ML-KEM-512",
122 BindingAlgorithmKind::MlKem768 => "ML-KEM-768",
123 BindingAlgorithmKind::MlKem1024 => "ML-KEM-1024",
124 BindingAlgorithmKind::Unsupported => "unsupported algorithm",
125 };
126 write!(f, "{detail}")
127 }
128}
129
130#[derive(Debug, Error)]
134pub enum MultikeyError {
135 #[error("multikey: invalid multibase string")]
137 InvalidMultibase,
138
139 #[error("multikey: decoded key too short: length={0}")]
141 DecodedTooShort(usize),
142
143 #[error("multikey: unknown multicodec prefix")]
145 UnknownCodecPrefix,
146
147 #[error("multikey: unknown codec name: {reason}")]
149 UnknownCodecName {
150 reason: CodecNameReason,
152 },
153
154 #[error("multikey: key length mismatch for {codec_name}: expected {expected}, got {actual}")]
156 KeyLengthMismatch {
157 codec_name: &'static str,
159 expected: usize,
161 actual: usize,
163 },
164
165 #[error(
167 "multikey: binding type '{binding_type}' does not match codec '{codec_name}' (alg={alg})"
168 )]
169 BindingTypeCodecMismatch {
170 binding_type: BindingTypeKind,
172 codec_name: &'static str,
174 alg: &'static str,
176 },
177
178 #[error(
180 "multikey: algorithm mismatch: binding.algorithm='{binding_alg}' but codec implies '{codec_alg}'"
181 )]
182 BindingAlgorithmMismatch {
183 binding_alg: BindingAlgorithmKind,
185 codec_alg: &'static str,
187 },
188
189 #[error(
191 "multikey: binding.algorithm missing but binding type '{binding_type}' requires an explicit algorithm"
192 )]
193 BindingAlgorithmMissing {
194 binding_type: BindingTypeKind,
196 },
197}
198
199pub(crate) fn classify_binding_type(binding_type: &str) -> BindingTypeKind {
200 match binding_type {
201 "Multikey" => BindingTypeKind::Multikey,
202 "P256Key2024" => BindingTypeKind::P256Key2024,
203 "P384Key2024" => BindingTypeKind::P384Key2024,
204 "P521Key2024" => BindingTypeKind::P521Key2024,
205 "RsaVerificationKey2024" => BindingTypeKind::RsaVerificationKey2024,
206 "ML_DSA_44Key2024" => BindingTypeKind::MlDsa44Key2024,
207 "ML_DSA_65Key2024" => BindingTypeKind::MlDsa65Key2024,
208 "ML_DSA_87Key2024" => BindingTypeKind::MlDsa87Key2024,
209 "MLKEM512Key2024" => BindingTypeKind::MlKem512Key2024,
210 "MLKEM768Key2024" => BindingTypeKind::MlKem768Key2024,
211 "MLKEM1024Key2024" => BindingTypeKind::MlKem1024Key2024,
212 _ => BindingTypeKind::Unsupported,
213 }
214}
215
216pub(crate) fn classify_binding_algorithm(algorithm: &str) -> BindingAlgorithmKind {
217 match algorithm {
218 "Ed25519" => BindingAlgorithmKind::Ed25519,
219 "Ed448" => BindingAlgorithmKind::Ed448,
220 "X25519" => BindingAlgorithmKind::X25519,
221 "P-256" => BindingAlgorithmKind::P256,
222 "P-384" => BindingAlgorithmKind::P384,
223 "P-521" => BindingAlgorithmKind::P521,
224 "RSA" => BindingAlgorithmKind::Rsa,
225 "secp256k1" => BindingAlgorithmKind::Secp256k1,
226 "ML-DSA-44" => BindingAlgorithmKind::MlDsa44,
227 "ML-DSA-65" => BindingAlgorithmKind::MlDsa65,
228 "ML-DSA-87" => BindingAlgorithmKind::MlDsa87,
229 "ML-KEM-512" => BindingAlgorithmKind::MlKem512,
230 "ML-KEM-768" => BindingAlgorithmKind::MlKem768,
231 "ML-KEM-1024" => BindingAlgorithmKind::MlKem1024,
232 _ => BindingAlgorithmKind::Unsupported,
233 }
234}