diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b6f2f9..06d8692 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `ctap2::get_info`: Use `ByteArray<16>` instead of `Bytes<16>` for AAGUID. - Remove re-exports for `heapless` and `heapless-bytes` as the relevant types are already re-exported. - `ctap2::get_info`: Use subcommand enum for `authenticator_config_commands`. +- `webauthn`: Make `KnownPublicKeyCredentialParameters` an enum. ## [0.6.0-rc.4] 2026-06-01 diff --git a/src/arbitrary.rs b/src/arbitrary.rs index 9549ed7..10bb00a 100644 --- a/src/arbitrary.rs +++ b/src/arbitrary.rs @@ -235,14 +235,6 @@ impl<'a> Arbitrary<'a> for webauthn::FilteredPublicKeyCredentialParameters { } } -// cannot be derived because we want to make sure that we have valid values -impl<'a> Arbitrary<'a> for webauthn::KnownPublicKeyCredentialParameters { - fn arbitrary(u: &mut Unstructured<'a>) -> Result { - let alg = *u.choose(&webauthn::KNOWN_ALGS)?; - Ok(Self { alg }) - } -} - // cannot be derived because of missing impl for serde_bytes::Bytes impl<'a> Arbitrary<'a> for webauthn::PublicKeyCredentialDescriptorRef<'a> { fn arbitrary(u: &mut Unstructured<'a>) -> Result { diff --git a/src/webauthn.rs b/src/webauthn.rs index 7a9b80e..ec9eb37 100644 --- a/src/webauthn.rs +++ b/src/webauthn.rs @@ -135,15 +135,29 @@ impl PublicKeyCredentialUserEntity { } } -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct KnownPublicKeyCredentialParameters { - pub alg: i32, +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +#[non_exhaustive] +pub enum KnownPublicKeyCredentialParameters { + ES256, + EdDSA, +} + +impl KnownPublicKeyCredentialParameters { + pub const ALL: [Self; COUNT_KNOWN_ALGS] = [Self::ES256, Self::EdDSA]; + + pub fn alg(&self) -> i32 { + match self { + Self::ES256 => ES256, + Self::EdDSA => ED_DSA, + } + } } impl From for PublicKeyCredentialParameters { fn from(value: KnownPublicKeyCredentialParameters) -> Self { Self { - alg: value.alg, + alg: value.alg(), key_type: String::try_from("public-key").unwrap(), } } @@ -155,12 +169,11 @@ pub enum UnknownPKCredentialParam { } /// ECDSA w/ SHA-256 -pub const ES256: i32 = -7; +const ES256: i32 = -7; /// EdDSA -pub const ED_DSA: i32 = -8; +const ED_DSA: i32 = -8; pub const COUNT_KNOWN_ALGS: usize = 2; -pub const KNOWN_ALGS: [i32; COUNT_KNOWN_ALGS] = [ES256, ED_DSA]; impl TryFrom for KnownPublicKeyCredentialParameters { type Error = UnknownPKCredentialParam; @@ -168,10 +181,12 @@ impl TryFrom for KnownPublicKeyCredentialParamete fn try_from(value: PublicKeyCredentialParameters) -> Result { if value.key_type != "public-key" { Err(UnknownPKCredentialParam::UnknownType) - } else if KNOWN_ALGS.contains(&value.alg) { - Ok(Self { alg: value.alg }) } else { - Err(UnknownPKCredentialParam::UnknownAlg) + match value.alg { + ES256 => Ok(Self::ES256), + ED_DSA => Ok(Self::EdDSA), + _ => Err(UnknownPKCredentialParam::UnknownAlg), + } } } } @@ -190,7 +205,7 @@ impl Serialize for FilteredPublicKeyCredentialParameters { use serde::ser::SerializeSeq; let mut seq = serializer.serialize_seq(Some(self.0.len()))?; for element in &self.0 { - let el: PublicKeyCredentialParameters = element.clone().into(); + let el = PublicKeyCredentialParameters::from(*element); seq.serialize_element(&el)? } seq.end()