use thiserror::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CodecNameReason {
Unsupported,
}
impl core::fmt::Display for CodecNameReason {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let detail = match self {
CodecNameReason::Unsupported => "unsupported codec name",
};
write!(f, "{detail}")
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BindingTypeKind {
Multikey,
P256Key2024,
P384Key2024,
P521Key2024,
RsaVerificationKey2024,
MlDsa44Key2024,
MlDsa65Key2024,
MlDsa87Key2024,
MlKem512Key2024,
MlKem768Key2024,
MlKem1024Key2024,
Unsupported,
}
impl core::fmt::Display for BindingTypeKind {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let detail = match self {
BindingTypeKind::Multikey => "Multikey",
BindingTypeKind::P256Key2024 => "P256Key2024",
BindingTypeKind::P384Key2024 => "P384Key2024",
BindingTypeKind::P521Key2024 => "P521Key2024",
BindingTypeKind::RsaVerificationKey2024 => "RsaVerificationKey2024",
BindingTypeKind::MlDsa44Key2024 => "ML_DSA_44Key2024",
BindingTypeKind::MlDsa65Key2024 => "ML_DSA_65Key2024",
BindingTypeKind::MlDsa87Key2024 => "ML_DSA_87Key2024",
BindingTypeKind::MlKem512Key2024 => "MLKEM512Key2024",
BindingTypeKind::MlKem768Key2024 => "MLKEM768Key2024",
BindingTypeKind::MlKem1024Key2024 => "MLKEM1024Key2024",
BindingTypeKind::Unsupported => "unsupported binding type",
};
write!(f, "{detail}")
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BindingAlgorithmKind {
Ed25519,
Ed448,
X25519,
P256,
P384,
P521,
Rsa,
Secp256k1,
MlDsa44,
MlDsa65,
MlDsa87,
MlKem512,
MlKem768,
MlKem1024,
Unsupported,
}
impl core::fmt::Display for BindingAlgorithmKind {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let detail = match self {
BindingAlgorithmKind::Ed25519 => "Ed25519",
BindingAlgorithmKind::Ed448 => "Ed448",
BindingAlgorithmKind::X25519 => "X25519",
BindingAlgorithmKind::P256 => "P-256",
BindingAlgorithmKind::P384 => "P-384",
BindingAlgorithmKind::P521 => "P-521",
BindingAlgorithmKind::Rsa => "RSA",
BindingAlgorithmKind::Secp256k1 => "secp256k1",
BindingAlgorithmKind::MlDsa44 => "ML-DSA-44",
BindingAlgorithmKind::MlDsa65 => "ML-DSA-65",
BindingAlgorithmKind::MlDsa87 => "ML-DSA-87",
BindingAlgorithmKind::MlKem512 => "ML-KEM-512",
BindingAlgorithmKind::MlKem768 => "ML-KEM-768",
BindingAlgorithmKind::MlKem1024 => "ML-KEM-1024",
BindingAlgorithmKind::Unsupported => "unsupported algorithm",
};
write!(f, "{detail}")
}
}
#[derive(Debug, Error)]
pub enum MultikeyError {
#[error("multikey: invalid multibase string")]
InvalidMultibase,
#[error("multikey: decoded key too short: length={0}")]
DecodedTooShort(usize),
#[error("multikey: unknown multicodec prefix")]
UnknownCodecPrefix,
#[error("multikey: unknown codec name: {reason}")]
UnknownCodecName {
reason: CodecNameReason,
},
#[error("multikey: key length mismatch for {codec_name}: expected {expected}, got {actual}")]
KeyLengthMismatch {
codec_name: &'static str,
expected: usize,
actual: usize,
},
#[error(
"multikey: binding type '{binding_type}' does not match codec '{codec_name}' (alg={alg})"
)]
BindingTypeCodecMismatch {
binding_type: BindingTypeKind,
codec_name: &'static str,
alg: &'static str,
},
#[error(
"multikey: algorithm mismatch: binding.algorithm='{binding_alg}' but codec implies '{codec_alg}'"
)]
BindingAlgorithmMismatch {
binding_alg: BindingAlgorithmKind,
codec_alg: &'static str,
},
#[error(
"multikey: binding.algorithm missing but binding type '{binding_type}' requires an explicit algorithm"
)]
BindingAlgorithmMissing {
binding_type: BindingTypeKind,
},
}
pub(crate) fn classify_binding_type(binding_type: &str) -> BindingTypeKind {
match binding_type {
"Multikey" => BindingTypeKind::Multikey,
"P256Key2024" => BindingTypeKind::P256Key2024,
"P384Key2024" => BindingTypeKind::P384Key2024,
"P521Key2024" => BindingTypeKind::P521Key2024,
"RsaVerificationKey2024" => BindingTypeKind::RsaVerificationKey2024,
"ML_DSA_44Key2024" => BindingTypeKind::MlDsa44Key2024,
"ML_DSA_65Key2024" => BindingTypeKind::MlDsa65Key2024,
"ML_DSA_87Key2024" => BindingTypeKind::MlDsa87Key2024,
"MLKEM512Key2024" => BindingTypeKind::MlKem512Key2024,
"MLKEM768Key2024" => BindingTypeKind::MlKem768Key2024,
"MLKEM1024Key2024" => BindingTypeKind::MlKem1024Key2024,
_ => BindingTypeKind::Unsupported,
}
}
pub(crate) fn classify_binding_algorithm(algorithm: &str) -> BindingAlgorithmKind {
match algorithm {
"Ed25519" => BindingAlgorithmKind::Ed25519,
"Ed448" => BindingAlgorithmKind::Ed448,
"X25519" => BindingAlgorithmKind::X25519,
"P-256" => BindingAlgorithmKind::P256,
"P-384" => BindingAlgorithmKind::P384,
"P-521" => BindingAlgorithmKind::P521,
"RSA" => BindingAlgorithmKind::Rsa,
"secp256k1" => BindingAlgorithmKind::Secp256k1,
"ML-DSA-44" => BindingAlgorithmKind::MlDsa44,
"ML-DSA-65" => BindingAlgorithmKind::MlDsa65,
"ML-DSA-87" => BindingAlgorithmKind::MlDsa87,
"ML-KEM-512" => BindingAlgorithmKind::MlKem512,
"ML-KEM-768" => BindingAlgorithmKind::MlKem768,
"ML-KEM-1024" => BindingAlgorithmKind::MlKem1024,
_ => BindingAlgorithmKind::Unsupported,
}
}