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("multikey: key too large for {codec_name}: maximum {max}, got {actual}")]
167 KeyTooLarge {
168 codec_name: &'static str,
170 max: usize,
172 actual: usize,
174 },
175
176 #[error("multikey: encoded payload too large")]
178 EncodedPayloadTooLarge,
179
180 #[error(
182 "multikey: binding type '{binding_type}' does not match codec '{codec_name}' (alg={alg})"
183 )]
184 BindingTypeCodecMismatch {
185 binding_type: BindingTypeKind,
187 codec_name: &'static str,
189 alg: &'static str,
191 },
192
193 #[error(
195 "multikey: algorithm mismatch: binding.algorithm='{binding_alg}' but codec implies '{codec_alg}'"
196 )]
197 BindingAlgorithmMismatch {
198 binding_alg: BindingAlgorithmKind,
200 codec_alg: &'static str,
202 },
203
204 #[error(
206 "multikey: binding.algorithm missing but binding type '{binding_type}' requires an explicit algorithm"
207 )]
208 BindingAlgorithmMissing {
209 binding_type: BindingTypeKind,
211 },
212}
213
214pub(crate) fn classify_binding_type(binding_type: &str) -> BindingTypeKind {
215 match binding_type {
216 "Multikey" => BindingTypeKind::Multikey,
217 "P256Key2024" => BindingTypeKind::P256Key2024,
218 "P384Key2024" => BindingTypeKind::P384Key2024,
219 "P521Key2024" => BindingTypeKind::P521Key2024,
220 "RsaVerificationKey2024" => BindingTypeKind::RsaVerificationKey2024,
221 "ML_DSA_44Key2024" => BindingTypeKind::MlDsa44Key2024,
222 "ML_DSA_65Key2024" => BindingTypeKind::MlDsa65Key2024,
223 "ML_DSA_87Key2024" => BindingTypeKind::MlDsa87Key2024,
224 "MLKEM512Key2024" => BindingTypeKind::MlKem512Key2024,
225 "MLKEM768Key2024" => BindingTypeKind::MlKem768Key2024,
226 "MLKEM1024Key2024" => BindingTypeKind::MlKem1024Key2024,
227 _ => BindingTypeKind::Unsupported,
228 }
229}
230
231pub(crate) fn classify_binding_algorithm(algorithm: &str) -> BindingAlgorithmKind {
232 match algorithm {
233 "Ed25519" => BindingAlgorithmKind::Ed25519,
234 "Ed448" => BindingAlgorithmKind::Ed448,
235 "X25519" => BindingAlgorithmKind::X25519,
236 "P-256" => BindingAlgorithmKind::P256,
237 "P-384" => BindingAlgorithmKind::P384,
238 "P-521" => BindingAlgorithmKind::P521,
239 "RSA" => BindingAlgorithmKind::Rsa,
240 "secp256k1" => BindingAlgorithmKind::Secp256k1,
241 "ML-DSA-44" => BindingAlgorithmKind::MlDsa44,
242 "ML-DSA-65" => BindingAlgorithmKind::MlDsa65,
243 "ML-DSA-87" => BindingAlgorithmKind::MlDsa87,
244 "ML-KEM-512" => BindingAlgorithmKind::MlKem512,
245 "ML-KEM-768" => BindingAlgorithmKind::MlKem768,
246 "ML-KEM-1024" => BindingAlgorithmKind::MlKem1024,
247 _ => BindingAlgorithmKind::Unsupported,
248 }
249}