webauthn_rp

WebAuthn Level 3 RP library.
git clone https://git.philomathiclife.com/repos/webauthn_rp
Log | Files | Refs | README

ser_relaxed.rs (301104B)


      1 #[cfg(doc)]
      2 use super::super::{super::request::register::CoseAlgorithmIdentifier, Challenge, CredentialId};
      3 use super::{
      4     super::{
      5         register::ser::{
      6             AUTH_ATTEST_FIELDS, AttObj, AuthenticatorAttestationVisitor,
      7             ClientExtensionsOutputsVisitor, EXT_FIELDS,
      8         },
      9         ser::{
     10             AuthenticationExtensionsPrfOutputsHelper, Base64DecodedVal, ClientExtensions,
     11             PublicKeyCredential, Type,
     12         },
     13         ser_relaxed::AuthenticationExtensionsPrfValuesRelaxed,
     14     },
     15     AttestationObject, AuthenticationExtensionsPrfOutputs, AuthenticatorAttachment,
     16     AuthenticatorAttestation, ClientExtensionsOutputs, CredentialPropertiesOutput, Registration,
     17     ser::{AuthAttest, CredentialPropertiesOutputVisitor, PROPS_FIELDS},
     18 };
     19 use core::{
     20     fmt::{self, Formatter},
     21     marker::PhantomData,
     22 };
     23 use serde::de::{Deserialize, Deserializer, Error, MapAccess, Unexpected, Visitor};
     24 /// `newtype` around `CredentialPropertiesOutput` with a "relaxed" [`Self::deserialize`] implementation.
     25 #[derive(Clone, Copy, Debug)]
     26 pub struct CredentialPropertiesOutputRelaxed(pub CredentialPropertiesOutput);
     27 impl From<CredentialPropertiesOutputRelaxed> for CredentialPropertiesOutput {
     28     #[inline]
     29     fn from(value: CredentialPropertiesOutputRelaxed) -> Self {
     30         value.0
     31     }
     32 }
     33 impl<'de> Deserialize<'de> for CredentialPropertiesOutputRelaxed {
     34     /// Same as [`CredentialPropertiesOutput::deserialize`] except unknown keys are ignored.
     35     ///
     36     /// Note that duplicate keys are still forbidden.
     37     #[inline]
     38     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     39     where
     40         D: Deserializer<'de>,
     41     {
     42         deserializer
     43             .deserialize_struct(
     44                 "CredentialPropertiesOutputRelaxed",
     45                 PROPS_FIELDS,
     46                 CredentialPropertiesOutputVisitor::<true>,
     47             )
     48             .map(Self)
     49     }
     50 }
     51 /// `newtype` around `AuthenticationExtensionsPrfOutputs` with a "relaxed" [`Self::deserialize`] implementation.
     52 #[derive(Clone, Copy, Debug)]
     53 pub struct AuthenticationExtensionsPrfOutputsRelaxed(AuthenticationExtensionsPrfOutputs);
     54 impl From<AuthenticationExtensionsPrfOutputsRelaxed> for AuthenticationExtensionsPrfOutputs {
     55     #[inline]
     56     fn from(value: AuthenticationExtensionsPrfOutputsRelaxed) -> Self {
     57         value.0
     58     }
     59 }
     60 impl<'de> Deserialize<'de> for AuthenticationExtensionsPrfOutputsRelaxed {
     61     /// Same as [`AuthenticationExtensionsPrfOutputs::deserialize`] except unknown keys are ignored.
     62     ///
     63     /// Note that duplicate keys are still forbidden;
     64     /// [`enabled`](https://www.w3.org/TR/webauthn-3/#dom-authenticationextensionsprfoutputs-enabled) must still exist
     65     /// (and not be `null`); and
     66     /// [`results`](https://www.w3.org/TR/webauthn-3/#dom-authenticationextensionsprfoutputs-results) must not exist,
     67     /// be `null`, or be an
     68     /// [`AuthenticationExtensionsPRFValues`](https://www.w3.org/TR/webauthn-3/#dictdef-authenticationextensionsprfvalues)
     69     /// such that unknown keys are ignored, duplicate keys are forbidden,
     70     /// [`first`](https://www.w3.org/TR/webauthn-3/#dom-authenticationextensionsprfvalues-first) is not required but
     71     /// if it exists it must be `null`, and
     72     /// [`second`](https://www.w3.org/TR/webauthn-3/#dom-authenticationextensionsprfvalues-second) can exist but
     73     /// must be `null` if so.
     74     #[inline]
     75     #[expect(clippy::unreachable, reason = "we want to crash when there is a bug")]
     76     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     77     where
     78         D: Deserializer<'de>,
     79     {
     80         AuthenticationExtensionsPrfOutputsHelper::<
     81             true,
     82             true,
     83             AuthenticationExtensionsPrfValuesRelaxed,
     84         >::deserialize(deserializer)
     85         .map(|v| {
     86             Self(AuthenticationExtensionsPrfOutputs {
     87                 enabled: v.0.unwrap_or_else(|| {
     88                     unreachable!(
     89                         "there is a bug in AuthenticationExtensionsPrfOutputsHelper::deserialize"
     90                     )
     91                 }),
     92             })
     93         })
     94     }
     95 }
     96 /// `newtype` around `ClientExtensionsOutputs` with a "relaxed" [`Self::deserialize`] implementation.
     97 #[derive(Clone, Copy, Debug)]
     98 pub struct ClientExtensionsOutputsRelaxed(pub ClientExtensionsOutputs);
     99 impl ClientExtensions for ClientExtensionsOutputsRelaxed {
    100     fn empty() -> Self {
    101         Self(ClientExtensionsOutputs::empty())
    102     }
    103 }
    104 impl<'de> Deserialize<'de> for ClientExtensionsOutputsRelaxed {
    105     /// Same as [`ClientExtensionsOutputs::deserialize`] except unknown keys are ignored,
    106     /// [`credProps`](https://www.w3.org/TR/webauthn-3/#dom-authenticationextensionsclientoutputs-credprops) is
    107     /// `null` or deserialized via [`CredentialPropertiesOutputRelaxed::deserialize`], and
    108     /// [`prf`](https://www.w3.org/TR/webauthn-3/#dom-authenticationextensionsclientoutputs-prf) is
    109     /// `null` or deserialized via [`AuthenticationExtensionsPrfOutputsRelaxed::deserialize`].
    110     ///
    111     /// Note that duplicate keys are still forbidden.
    112     #[inline]
    113     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    114     where
    115         D: Deserializer<'de>,
    116     {
    117         deserializer
    118             .deserialize_struct(
    119                 "ClientExtensionsOutputsRelaxed",
    120                 EXT_FIELDS,
    121                 ClientExtensionsOutputsVisitor::<
    122                     true,
    123                     CredentialPropertiesOutputRelaxed,
    124                     AuthenticationExtensionsPrfOutputsRelaxed,
    125                 >(PhantomData),
    126             )
    127             .map(Self)
    128     }
    129 }
    130 /// `newtype` around `AuthAttest` with a "relaxed" [`Self::deserialize`] implementation.
    131 struct AuthAttestRelaxed(pub AuthAttest);
    132 impl<'de> Deserialize<'de> for AuthAttestRelaxed {
    133     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    134     where
    135         D: Deserializer<'de>,
    136     {
    137         deserializer
    138             .deserialize_struct(
    139                 "AuthenticatorAttestation",
    140                 AUTH_ATTEST_FIELDS,
    141                 AuthenticatorAttestationVisitor::<true>,
    142             )
    143             .map(Self)
    144     }
    145 }
    146 /// `newtype` around `AuthenticatorAttestation` with a "relaxed" [`Self::deserialize`] implementation.
    147 #[derive(Debug)]
    148 pub struct AuthenticatorAttestationRelaxed(pub AuthenticatorAttestation);
    149 impl<'de> Deserialize<'de> for AuthenticatorAttestationRelaxed {
    150     /// Same as [`AuthenticatorAttestation::deserialize`] except unknown keys are ignored and only
    151     /// [`clientDataJSON`](https://www.w3.org/TR/webauthn-3/#dom-authenticatorattestationresponsejson-clientdatajson)
    152     /// and
    153     /// [`attestationObject`](https://www.w3.org/TR/webauthn-3/#dom-authenticatorattestationresponsejson-attestationobject)
    154     /// are required (and must not be `null`). For the other fields, they are allowed to not exist or be `null`.
    155     ///
    156     /// Note that duplicate keys are still forbidden, and data matching still applies when applicable.
    157     #[inline]
    158     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    159     where
    160         D: Deserializer<'de>,
    161     {
    162         AuthAttestRelaxed::deserialize(deserializer).map(|v| Self(v.0.attest))
    163     }
    164 }
    165 /// `newtype` around `Registration` with a "relaxed" [`Self::deserialize`] implementation.
    166 #[derive(Debug)]
    167 pub struct RegistrationRelaxed(pub Registration);
    168 impl<'de> Deserialize<'de> for RegistrationRelaxed {
    169     /// Same as [`Registration::deserialize`] except unknown keys are ignored,
    170     /// [`response`](https://www.w3.org/TR/webauthn-3/#dom-registrationresponsejson-response) is deserialized
    171     /// via [`AuthenticatorAttestationRelaxed::deserialize`],
    172     /// [`clientExtensionResults`](https://www.w3.org/TR/webauthn-3/#dom-registrationresponsejson-clientextensionresults)
    173     /// is `null` or deserialized via [`ClientExtensionsOutputsRelaxed::deserialize`], and only `response` is required.
    174     /// `id`, `rawId`, and `type` are allowed to not exist. For the other fields, they are allowed to not exist or
    175     /// be `null`.
    176     ///
    177     /// Note that duplicate keys are still forbidden, and data matching still applies when applicable.
    178     #[expect(clippy::indexing_slicing, reason = "comment justifies its correctness")]
    179     #[inline]
    180     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    181     where
    182         D: Deserializer<'de>,
    183     {
    184         PublicKeyCredential::<true, true, AuthAttestRelaxed, ClientExtensionsOutputsRelaxed>::deserialize(deserializer).and_then(|cred| {
    185             cred.id.map_or_else(|| Ok(()), |id| {
    186                 cred.response.0.cred_info.map_or_else(
    187                     || AttestationObject::try_from(cred.response.0.attest.attestation_object()).map_err(Error::custom).and_then(|att_obj| {
    188                         if id.as_ref() == att_obj.auth_data.attested_credential_data.credential_id.as_ref() {
    189                             Ok(())
    190                         } else {
    191                             Err(Error::invalid_value(Unexpected::Bytes(id.as_ref()), &format!("id, rawId, and the credential id in the attested credential data to all match: {:?}", att_obj.auth_data.attested_credential_data.credential_id.0).as_str()))
    192                         }
    193                     }),
    194                     // `start` and `last` were calculated based on `cred.response.attest.attestation_object()`
    195                     // and represent the starting and ending index of the `CredentialId`; therefore this is correct
    196                     // let alone won't `panic`.
    197                     |(start, last)| if *id.0 == cred.response.0.attest.attestation_object()[start..last] {
    198                         Ok(())
    199                     } else {
    200                         Err(Error::invalid_value(Unexpected::Bytes(id.as_ref()), &format!("id, rawId, and the credential id in the attested credential data to all match: {:?}", &cred.response.0.attest.attestation_object()[start..last]).as_str()))
    201                     }
    202                 )
    203             }).map(|()| {
    204                 Self(Registration { response: cred.response.0.attest, authenticator_attachment: cred.authenticator_attachment, client_extension_results: cred.client_extension_results.0 })
    205             })
    206         })
    207     }
    208 }
    209 /// `newtype` around `Registration` with a custom [`Self::deserialize`] implementation.
    210 #[derive(Debug)]
    211 pub struct CustomRegistration(pub Registration);
    212 impl<'de> Deserialize<'de> for CustomRegistration {
    213     /// Despite the spec having a
    214     /// [pre-defined format](https://www.w3.org/TR/webauthn-3/#dictdef-registrationresponsejson) that clients
    215     /// can follow, the downside is the superfluous data it contains.
    216     ///
    217     /// There simply is no reason to send the [`CredentialId`] _four_ times. This redundant data puts RPs in
    218     /// a position where they either ignore the data or parse the data to ensure no contradictions exist
    219     /// (e.g., [FIDO conformance requires one to verify `id` and `rawId` exist and match](https://github.com/w3c/webauthn/issues/2119#issuecomment-2287875401)).
    220     ///
    221     /// While [`Registration::deserialize`] _strictly_ adheres to the JSON definition (e.g., it requires `publicKey`
    222     /// to exist and match with what is in both `authenticatorData` and `attestationObject` when the underlying
    223     /// algorithm is not [`CoseAlgorithmIdentifier::Es384`]), this implementation
    224     /// strictly disallows superfluous data. Specifically the following JSON is required to be sent where duplicate
    225     /// and unknown keys are disallowed:
    226     ///
    227     /// ```json
    228     /// {
    229     ///   "attestationObject": <base64url string>,
    230     ///   "authenticatorAttachment": null | "platform" | "cross-platform",
    231     ///   "clientDataJSON": <base64url string>,
    232     ///   "clientExtensionResults": <see ClientExtensionsOutputs::deserialize>,
    233     ///   "transports": <see AuthTransports::deserialize>,
    234     ///   "type": "public-key"
    235     /// }
    236     /// ```
    237     ///
    238     /// All of the above keys are required with the exceptions of `"authenticatorAttachment"` and `"type"`.
    239     ///
    240     /// # Examples
    241     ///
    242     /// ```
    243     /// # use webauthn_rp::response::register::ser_relaxed::CustomRegistration;
    244     /// assert!(
    245     ///     // The below payload is technically valid, but `RegistrationServerState::verify` will fail
    246     ///     // since the attestationObject is not valid. This is true for `Registration::deserialize`
    247     ///     // as well since attestationObject parsing is always deferred.
    248     ///     serde_json::from_str::<CustomRegistration>(
    249     ///         r#"{
    250     ///             "transports": ["usb"],
    251     ///             "attestationObject": "AA",
    252     ///             "authenticatorAttachment": "cross-platform",
    253     ///             "clientExtensionResults": {},
    254     ///             "clientDataJSON": "AA",
    255     ///             "type": "public-key"
    256     ///         }"#
    257     ///     ).is_ok());
    258     /// ```
    259     #[expect(
    260         clippy::too_many_lines,
    261         reason = "want to hide; thus don't want to put in an outer scope"
    262     )]
    263     #[inline]
    264     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    265     where
    266         D: Deserializer<'de>,
    267     {
    268         /// `Visitor` for `CustomRegistration`.
    269         struct CustomRegistrationVisitor;
    270         impl<'d> Visitor<'d> for CustomRegistrationVisitor {
    271             type Value = CustomRegistration;
    272             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
    273                 formatter.write_str("CustomRegistration")
    274             }
    275             #[expect(
    276                 clippy::too_many_lines,
    277                 reason = "want to hide; thus don't want to put in an outer scope"
    278             )]
    279             fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
    280             where
    281                 A: MapAccess<'d>,
    282             {
    283                 /// Fields in the JSON.
    284                 enum Field {
    285                     /// `attestationObject` key.
    286                     AttestationObject,
    287                     /// `authenticatorAttachment` key.
    288                     AuthenticatorAttachment,
    289                     /// `clientDataJSON` key.
    290                     ClientDataJson,
    291                     /// `clientExtensionResults` key.
    292                     ClientExtensionResults,
    293                     /// `transports` key.
    294                     Transports,
    295                     /// `type` key.
    296                     Type,
    297                 }
    298                 impl<'e> Deserialize<'e> for Field {
    299                     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    300                     where
    301                         D: Deserializer<'e>,
    302                     {
    303                         /// `Visitor` for `Field`.
    304                         struct FieldVisitor;
    305                         impl Visitor<'_> for FieldVisitor {
    306                             type Value = Field;
    307                             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
    308                                 write!(
    309                                     formatter,
    310                                     "'{ATTESTATION_OBJECT}', '{AUTHENTICATOR_ATTACHMENT}', '{CLIENT_DATA_JSON}', '{CLIENT_EXTENSION_RESULTS}', '{TRANSPORTS}', or '{TYPE}'"
    311                                 )
    312                             }
    313                             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    314                             where
    315                                 E: Error,
    316                             {
    317                                 match v {
    318                                     ATTESTATION_OBJECT => Ok(Field::AttestationObject),
    319                                     AUTHENTICATOR_ATTACHMENT => Ok(Field::AuthenticatorAttachment),
    320                                     CLIENT_DATA_JSON => Ok(Field::ClientDataJson),
    321                                     CLIENT_EXTENSION_RESULTS => Ok(Field::ClientExtensionResults),
    322                                     TRANSPORTS => Ok(Field::Transports),
    323                                     TYPE => Ok(Field::Type),
    324                                     _ => Err(E::unknown_field(v, FIELDS)),
    325                                 }
    326                             }
    327                         }
    328                         deserializer.deserialize_identifier(FieldVisitor)
    329                     }
    330                 }
    331                 let mut attestation_object = None;
    332                 let mut authenticator_attachment = None;
    333                 let mut client_data_json = None;
    334                 let mut ext = None;
    335                 let mut transports = None;
    336                 let mut typ = false;
    337                 while let Some(key) = map.next_key()? {
    338                     match key {
    339                         Field::AttestationObject => {
    340                             if attestation_object.is_some() {
    341                                 return Err(Error::duplicate_field(ATTESTATION_OBJECT));
    342                             }
    343                             attestation_object =
    344                                 map.next_value::<AttObj>().map(|val| Some(val.0))?;
    345                         }
    346                         Field::AuthenticatorAttachment => {
    347                             if authenticator_attachment.is_some() {
    348                                 return Err(Error::duplicate_field(AUTHENTICATOR_ATTACHMENT));
    349                             }
    350                             authenticator_attachment = map.next_value::<Option<_>>().map(Some)?;
    351                         }
    352                         Field::ClientDataJson => {
    353                             if client_data_json.is_some() {
    354                                 return Err(Error::duplicate_field(CLIENT_DATA_JSON));
    355                             }
    356                             client_data_json = map
    357                                 .next_value::<Base64DecodedVal>()
    358                                 .map(|val| Some(val.0))?;
    359                         }
    360                         Field::ClientExtensionResults => {
    361                             if ext.is_some() {
    362                                 return Err(Error::duplicate_field(CLIENT_EXTENSION_RESULTS));
    363                             }
    364                             ext = map.next_value().map(Some)?;
    365                         }
    366                         Field::Transports => {
    367                             if transports.is_some() {
    368                                 return Err(Error::duplicate_field(TRANSPORTS));
    369                             }
    370                             transports = map.next_value().map(Some)?;
    371                         }
    372                         Field::Type => {
    373                             if typ {
    374                                 return Err(Error::duplicate_field(TYPE));
    375                             }
    376                             typ = map.next_value::<Type>().map(|_| true)?;
    377                         }
    378                     }
    379                 }
    380                 attestation_object
    381                     .ok_or_else(|| Error::missing_field(ATTESTATION_OBJECT))
    382                     .and_then(|att_obj| {
    383                         client_data_json
    384                             .ok_or_else(|| Error::missing_field(CLIENT_DATA_JSON))
    385                             .and_then(|c_data| {
    386                                 ext.ok_or_else(|| Error::missing_field(CLIENT_EXTENSION_RESULTS))
    387                                     .and_then(|client_extension_results| {
    388                                         transports
    389                                             .ok_or_else(|| Error::missing_field(TRANSPORTS))
    390                                             .map(|trans| {
    391                                                 CustomRegistration(Registration {
    392                                                     response: AuthenticatorAttestation::new(
    393                                                         c_data, att_obj, trans,
    394                                                     ),
    395                                                     authenticator_attachment:
    396                                                         authenticator_attachment.map_or(
    397                                                             AuthenticatorAttachment::None,
    398                                                             |auth_attach| {
    399                                                                 auth_attach.unwrap_or(
    400                                                                     AuthenticatorAttachment::None,
    401                                                                 )
    402                                                             },
    403                                                         ),
    404                                                     client_extension_results,
    405                                                 })
    406                                             })
    407                                     })
    408                             })
    409                     })
    410             }
    411         }
    412         /// `attestationObject` key.
    413         const ATTESTATION_OBJECT: &str = "attestationObject";
    414         /// `authenticatorAttachment` key.
    415         const AUTHENTICATOR_ATTACHMENT: &str = "authenticatorAttachment";
    416         /// `clientDataJSON` key.
    417         const CLIENT_DATA_JSON: &str = "clientDataJSON";
    418         /// `clientExtensionResults` key.
    419         const CLIENT_EXTENSION_RESULTS: &str = "clientExtensionResults";
    420         /// `transports` key.
    421         const TRANSPORTS: &str = "transports";
    422         /// `type` key.
    423         const TYPE: &str = "type";
    424         /// Fields.
    425         const FIELDS: &[&str; 6] = &[
    426             ATTESTATION_OBJECT,
    427             AUTHENTICATOR_ATTACHMENT,
    428             CLIENT_DATA_JSON,
    429             CLIENT_EXTENSION_RESULTS,
    430             TRANSPORTS,
    431             TYPE,
    432         ];
    433         deserializer.deserialize_struct("CustomRegistration", FIELDS, CustomRegistrationVisitor)
    434     }
    435 }
    436 #[cfg(test)]
    437 mod tests {
    438     use super::{
    439         super::{
    440             super::super::request::register::CoseAlgorithmIdentifier, AKP, ALG,
    441             AuthenticatorAttachment, EC2, EDDSA, ES256, ES384, KTY, MLDSA44, MLDSA65, MLDSA87, OKP,
    442             RSA, cbor,
    443         },
    444         CustomRegistration, RegistrationRelaxed,
    445     };
    446     use ed25519_dalek::{VerifyingKey, pkcs8::EncodePublicKey as _};
    447     use ml_dsa::{MlDsa44, MlDsa65, MlDsa87, VerifyingKey as MlDsaVerKey};
    448     use p256::{
    449         PublicKey as P256PubKey, Sec1Point as P256Pt, SecretKey as P256Key,
    450         elliptic_curve::sec1::{FromSec1Point as _, ToSec1Point as _},
    451     };
    452     use p384::{PublicKey as P384PubKey, Sec1Point as P384Pt, SecretKey as P384Key};
    453     use rsa::{
    454         BoxedUint, RsaPrivateKey,
    455         sha2::{Digest as _, Sha256},
    456         traits::PublicKeyParts as _,
    457     };
    458     use serde::de::{Error as _, Unexpected};
    459     use serde_json::Error;
    460     #[expect(clippy::unwrap_used, reason = "OK in tests")]
    461     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
    462     #[expect(
    463         clippy::cognitive_complexity,
    464         clippy::too_many_lines,
    465         reason = "a lot to test"
    466     )]
    467     #[test]
    468     fn eddsa_registration_deserialize_data_mismatch() {
    469         let c_data_json = serde_json::json!({}).to_string();
    470         let att_obj: [u8; 143] = [
    471             cbor::MAP_3,
    472             cbor::TEXT_3,
    473             b'f',
    474             b'm',
    475             b't',
    476             cbor::TEXT_4,
    477             b'n',
    478             b'o',
    479             b'n',
    480             b'e',
    481             cbor::TEXT_7,
    482             b'a',
    483             b't',
    484             b't',
    485             b'S',
    486             b't',
    487             b'm',
    488             b't',
    489             cbor::MAP_0,
    490             cbor::TEXT_8,
    491             b'a',
    492             b'u',
    493             b't',
    494             b'h',
    495             b'D',
    496             b'a',
    497             b't',
    498             b'a',
    499             cbor::BYTES_INFO_24,
    500             113,
    501             // `rpIdHash`.
    502             0,
    503             0,
    504             0,
    505             0,
    506             0,
    507             0,
    508             0,
    509             0,
    510             0,
    511             0,
    512             0,
    513             0,
    514             0,
    515             0,
    516             0,
    517             0,
    518             0,
    519             0,
    520             0,
    521             0,
    522             0,
    523             0,
    524             0,
    525             0,
    526             0,
    527             0,
    528             0,
    529             0,
    530             0,
    531             0,
    532             0,
    533             0,
    534             // `flags`.
    535             0b0100_0101,
    536             // `signCount`.
    537             0,
    538             0,
    539             0,
    540             0,
    541             // `aaguid`.
    542             0,
    543             0,
    544             0,
    545             0,
    546             0,
    547             0,
    548             0,
    549             0,
    550             0,
    551             0,
    552             0,
    553             0,
    554             0,
    555             0,
    556             0,
    557             0,
    558             // `credentialIdLength`.
    559             0,
    560             16,
    561             // `credentialId`.
    562             0,
    563             0,
    564             0,
    565             0,
    566             0,
    567             0,
    568             0,
    569             0,
    570             0,
    571             0,
    572             0,
    573             0,
    574             0,
    575             0,
    576             0,
    577             0,
    578             // Ed25519 COSE key.
    579             cbor::MAP_4,
    580             KTY,
    581             OKP,
    582             ALG,
    583             EDDSA,
    584             // `crv`.
    585             cbor::NEG_ONE,
    586             // `Ed25519`.
    587             cbor::SIX,
    588             // `x`.
    589             cbor::NEG_TWO,
    590             cbor::BYTES_INFO_24,
    591             32,
    592             // Compressed y-coordinate.
    593             1,
    594             1,
    595             1,
    596             1,
    597             1,
    598             1,
    599             1,
    600             1,
    601             1,
    602             1,
    603             1,
    604             1,
    605             1,
    606             1,
    607             1,
    608             1,
    609             1,
    610             1,
    611             1,
    612             1,
    613             1,
    614             1,
    615             1,
    616             1,
    617             1,
    618             1,
    619             1,
    620             1,
    621             1,
    622             1,
    623             1,
    624             1,
    625         ];
    626         let pub_key = VerifyingKey::from_bytes(&[1; 32])
    627             .unwrap()
    628             .to_public_key_der()
    629             .unwrap();
    630         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
    631         let att_obj_len = att_obj.len();
    632         let auth_data_start = att_obj_len - 113;
    633         let b64_adata = base64url_nopad::encode(&att_obj[auth_data_start..]);
    634         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
    635         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
    636         // Base case is valid.
    637         assert!(
    638             serde_json::from_str::<RegistrationRelaxed>(
    639                 serde_json::json!({
    640                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
    641                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    642                     "response": {
    643                         "clientDataJSON": b64_cdata_json,
    644                         "authenticatorData": b64_adata,
    645                         "transports": ["ble", "usb", "hybrid", "internal", "nfc", "smart-card"],
    646                         "publicKey": b64_key,
    647                         "publicKeyAlgorithm": -8i8,
    648                         "attestationObject": b64_aobj,
    649                     },
    650                     "authenticatorAttachment": "cross-platform",
    651                     "clientExtensionResults": {},
    652                     "type": "public-key"
    653                 })
    654                 .to_string()
    655                 .as_str()
    656             )
    657             .is_ok_and(
    658                 |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
    659                     && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
    660                     && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
    661                         == *Sha256::digest(c_data_json.as_bytes())
    662                     && reg.0.response.transports.count() == 6
    663                     && matches!(
    664                         reg.0.authenticator_attachment,
    665                         AuthenticatorAttachment::CrossPlatform
    666                     )
    667                     && reg.0.client_extension_results.cred_props.is_none()
    668                     && reg.0.client_extension_results.prf.is_none()
    669             )
    670         );
    671         // `id` and `rawId` mismatch.
    672         let mut err = Error::invalid_value(
    673             Unexpected::Bytes(
    674                 base64url_nopad::decode(b"ABABABABABABABABABABAA")
    675                     .unwrap()
    676                     .as_slice(),
    677             ),
    678             &format!("id and rawId to match: CredentialId({:?})", [0u8; 16]).as_str(),
    679         )
    680         .to_string()
    681         .into_bytes();
    682         assert_eq!(
    683             serde_json::from_str::<RegistrationRelaxed>(
    684                 serde_json::json!({
    685                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
    686                     "rawId": "ABABABABABABABABABABAA",
    687                     "response": {
    688                         "clientDataJSON": b64_cdata_json,
    689                         "authenticatorData": b64_adata,
    690                         "transports": [],
    691                         "publicKey": b64_key,
    692                         "publicKeyAlgorithm": -8i8,
    693                         "attestationObject": b64_aobj,
    694                     },
    695                     "clientExtensionResults": {},
    696                     "type": "public-key"
    697                 })
    698                 .to_string()
    699                 .as_str()
    700             )
    701             .unwrap_err()
    702             .to_string()
    703             .into_bytes()
    704             .get(..err.len()),
    705             Some(err.as_slice())
    706         );
    707         // missing `id`.
    708         drop(
    709             serde_json::from_str::<RegistrationRelaxed>(
    710                 serde_json::json!({
    711                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    712                     "response": {
    713                         "clientDataJSON": b64_cdata_json,
    714                         "authenticatorData": b64_adata,
    715                         "transports": [],
    716                         "publicKey": b64_key,
    717                         "publicKeyAlgorithm": -8i8,
    718                         "attestationObject": b64_aobj,
    719                     },
    720                     "clientExtensionResults": {},
    721                     "type": "public-key"
    722                 })
    723                 .to_string()
    724                 .as_str(),
    725             )
    726             .unwrap(),
    727         );
    728         // `null` `id`.
    729         err = Error::invalid_type(Unexpected::Other("null"), &"CredentialId")
    730             .to_string()
    731             .into_bytes();
    732         assert_eq!(
    733             serde_json::from_str::<RegistrationRelaxed>(
    734                 serde_json::json!({
    735                     "id": null,
    736                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    737                     "response": {
    738                         "clientDataJSON": null,
    739                         "authenticatorData": b64_adata,
    740                         "transports": [],
    741                         "publicKey": b64_key,
    742                         "publicKeyAlgorithm": -8i8,
    743                         "attestationObject": b64_aobj,
    744                     },
    745                     "clientExtensionResults": {},
    746                     "type": "public-key"
    747                 })
    748                 .to_string()
    749                 .as_str()
    750             )
    751             .unwrap_err()
    752             .to_string()
    753             .into_bytes()
    754             .get(..err.len()),
    755             Some(err.as_slice())
    756         );
    757         // Missing `rawId`.
    758         drop(
    759             serde_json::from_str::<RegistrationRelaxed>(
    760                 serde_json::json!({
    761                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
    762                     "response": {
    763                         "clientDataJSON": b64_cdata_json,
    764                         "authenticatorData": b64_adata,
    765                         "transports": [],
    766                         "publicKey": b64_key,
    767                         "publicKeyAlgorithm": -8i8,
    768                         "attestationObject": b64_aobj,
    769                     },
    770                     "clientExtensionResults": {},
    771                     "type": "public-key"
    772                 })
    773                 .to_string()
    774                 .as_str(),
    775             )
    776             .unwrap(),
    777         );
    778         // `null` `rawId`.
    779         err = Error::invalid_type(Unexpected::Other("null"), &"CredentialId")
    780             .to_string()
    781             .into_bytes();
    782         assert_eq!(
    783             serde_json::from_str::<RegistrationRelaxed>(
    784                 serde_json::json!({
    785                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
    786                     "rawId": null,
    787                     "response": {
    788                         "clientDataJSON": b64_cdata_json,
    789                         "authenticatorData": b64_adata,
    790                         "transports": [],
    791                         "publicKey": b64_key,
    792                         "publicKeyAlgorithm": -8i8,
    793                         "attestationObject": b64_aobj,
    794                     },
    795                     "clientExtensionResults": {},
    796                     "type": "public-key"
    797                 })
    798                 .to_string()
    799                 .as_str()
    800             )
    801             .unwrap_err()
    802             .to_string()
    803             .into_bytes()
    804             .get(..err.len()),
    805             Some(err.as_slice())
    806         );
    807         // `id` and the credential id in authenticator data mismatch.
    808         err = Error::invalid_value(
    809             Unexpected::Bytes(
    810                 base64url_nopad
    811                     ::decode(b"ABABABABABABABABABABAA")
    812                     .unwrap()
    813                     .as_slice(),
    814             ),
    815             &format!("id, rawId, and the credential id in the attested credential data to all match: {:?}", [0u8; 16]).as_str(),
    816         )
    817         .to_string().into_bytes();
    818         assert_eq!(
    819             serde_json::from_str::<RegistrationRelaxed>(
    820                 serde_json::json!({
    821                     "id": "ABABABABABABABABABABAA",
    822                     "rawId": "ABABABABABABABABABABAA",
    823                     "response": {
    824                         "clientDataJSON": b64_cdata_json,
    825                         "authenticatorData": b64_adata,
    826                         "transports": [],
    827                         "publicKey": b64_key,
    828                         "publicKeyAlgorithm": -8i8,
    829                         "attestationObject": b64_aobj,
    830                     },
    831                     "clientExtensionResults": {},
    832                     "type": "public-key"
    833                 })
    834                 .to_string()
    835                 .as_str()
    836             )
    837             .unwrap_err()
    838             .to_string()
    839             .into_bytes()
    840             .get(..err.len()),
    841             Some(err.as_slice())
    842         );
    843         // `authenticatorData` mismatches `authData` in attestation object.
    844         let mut bad_auth = [0; 113];
    845         let bad_auth_len = bad_auth.len();
    846         bad_auth.copy_from_slice(&att_obj[auth_data_start..]);
    847         bad_auth[bad_auth_len - 32..].copy_from_slice([0; 32].as_slice());
    848         err = Error::invalid_value(
    849             Unexpected::Bytes(bad_auth.as_slice()),
    850             &format!("authenticator data to match the authenticator data portion of attestation object: {:?}", &att_obj[att_obj_len - bad_auth_len..]).as_str(),
    851         )
    852         .to_string().into_bytes();
    853         assert_eq!(
    854             serde_json::from_str::<RegistrationRelaxed>(
    855                 serde_json::json!({
    856                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
    857                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    858                     "response": {
    859                         "clientDataJSON": b64_cdata_json,
    860                         "authenticatorData": base64url_nopad::encode(bad_auth.as_slice()),
    861                         "transports": [],
    862                         "publicKey": b64_key,
    863                         "publicKeyAlgorithm": -8i8,
    864                         "attestationObject": b64_aobj,
    865                     },
    866                     "clientExtensionResults": {},
    867                     "type": "public-key"
    868                 })
    869                 .to_string()
    870                 .as_str()
    871             )
    872             .unwrap_err()
    873             .to_string()
    874             .into_bytes()
    875             .get(..err.len()),
    876             Some(err.as_slice())
    877         );
    878         // Missing `authenticatorData`.
    879         drop(
    880             serde_json::from_str::<RegistrationRelaxed>(
    881                 serde_json::json!({
    882                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
    883                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    884                     "response": {
    885                         "clientDataJSON": b64_cdata_json,
    886                         "transports": [],
    887                         "publicKey": b64_key,
    888                         "publicKeyAlgorithm": -8i8,
    889                         "attestationObject": b64_aobj,
    890                     },
    891                     "clientExtensionResults": {},
    892                     "type": "public-key"
    893                 })
    894                 .to_string()
    895                 .as_str(),
    896             )
    897             .unwrap(),
    898         );
    899         // `null `authenticatorData`.
    900         drop(
    901             serde_json::from_str::<RegistrationRelaxed>(
    902                 serde_json::json!({
    903                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
    904                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    905                     "response": {
    906                         "clientDataJSON": b64_cdata_json,
    907                         "transports": [],
    908                         "authenticatorData": null,
    909                         "publicKey": b64_key,
    910                         "publicKeyAlgorithm": -8i8,
    911                         "attestationObject": b64_aobj,
    912                     },
    913                     "clientExtensionResults": {},
    914                     "type": "public-key"
    915                 })
    916                 .to_string()
    917                 .as_str(),
    918             )
    919             .unwrap(),
    920         );
    921         // `publicKeyAlgorithm` mismatch.
    922         err = Error::invalid_value(
    923             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
    924             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Eddsa).as_str()
    925         )
    926         .to_string().into_bytes();
    927         assert_eq!(
    928             serde_json::from_str::<RegistrationRelaxed>(
    929                 serde_json::json!({
    930                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
    931                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    932                     "response": {
    933                         "clientDataJSON": b64_cdata_json,
    934                         "authenticatorData": b64_adata,
    935                         "transports": [],
    936                         "publicKey": b64_key,
    937                         "publicKeyAlgorithm": -7i8,
    938                         "attestationObject": b64_aobj,
    939                     },
    940                     "clientExtensionResults": {},
    941                     "type": "public-key"
    942                 })
    943                 .to_string()
    944                 .as_str()
    945             )
    946             .unwrap_err()
    947             .to_string()
    948             .into_bytes()
    949             .get(..err.len()),
    950             Some(err.as_slice())
    951         );
    952         // Missing `publicKeyAlgorithm`.
    953         drop(
    954             serde_json::from_str::<RegistrationRelaxed>(
    955                 serde_json::json!({
    956                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
    957                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    958                     "response": {
    959                         "clientDataJSON": b64_cdata_json,
    960                         "authenticatorData": b64_adata,
    961                         "transports": [],
    962                         "publicKey": b64_key,
    963                         "attestationObject": b64_aobj,
    964                     },
    965                     "clientExtensionResults": {},
    966                     "type": "public-key"
    967                 })
    968                 .to_string()
    969                 .as_str(),
    970             )
    971             .unwrap(),
    972         );
    973         // `null` `publicKeyAlgorithm`.
    974         drop(
    975             serde_json::from_str::<RegistrationRelaxed>(
    976                 serde_json::json!({
    977                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
    978                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    979                     "response": {
    980                         "clientDataJSON": b64_cdata_json,
    981                         "authenticatorData": b64_adata,
    982                         "transports": [],
    983                         "publicKey": b64_key,
    984                         "publicKeyAlgorithm": null,
    985                         "attestationObject": b64_aobj,
    986                     },
    987                     "clientExtensionResults": {},
    988                     "type": "public-key"
    989                 })
    990                 .to_string()
    991                 .as_str(),
    992             )
    993             .unwrap(),
    994         );
    995         // `publicKey` mismatch.
    996         err = Error::invalid_value(
    997             Unexpected::Bytes([0; 32].as_slice()),
    998             &format!(
    999                 "DER-encoded public key to match the public key within the attestation object: Ed25519(Ed25519PubKey({:?}))",
   1000                 &att_obj[att_obj_len - 32..],
   1001             )
   1002             .as_str(),
   1003         )
   1004         .to_string().into_bytes();
   1005         assert_eq!(serde_json::from_str::<RegistrationRelaxed>(
   1006             serde_json::json!({
   1007                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1008                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1009                 "response": {
   1010                     "clientDataJSON": b64_cdata_json,
   1011                     "authenticatorData": b64_adata,
   1012                     "transports": [],
   1013                     "publicKey": base64url_nopad::encode(VerifyingKey::from_bytes(&[0; 32]).unwrap().to_public_key_der().unwrap().as_bytes()),
   1014                     "publicKeyAlgorithm": -8i8,
   1015                     "attestationObject": b64_aobj,
   1016                 },
   1017                 "clientExtensionResults": {},
   1018                 "type": "public-key"
   1019             })
   1020             .to_string()
   1021             .as_str()
   1022             )
   1023             .unwrap_err().to_string().into_bytes().get(..err.len()),
   1024             Some(err.as_slice())
   1025         );
   1026         // Missing `publicKey`.
   1027         drop(
   1028             serde_json::from_str::<RegistrationRelaxed>(
   1029                 serde_json::json!({
   1030                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1031                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1032                     "response": {
   1033                         "clientDataJSON": b64_cdata_json,
   1034                         "authenticatorData": b64_adata,
   1035                         "transports": [],
   1036                         "publicKeyAlgorithm": -8i8,
   1037                         "attestationObject": b64_aobj,
   1038                     },
   1039                     "clientExtensionResults": {},
   1040                     "type": "public-key"
   1041                 })
   1042                 .to_string()
   1043                 .as_str(),
   1044             )
   1045             .unwrap(),
   1046         );
   1047         // `null` `publicKey`.
   1048         drop(
   1049             serde_json::from_str::<RegistrationRelaxed>(
   1050                 serde_json::json!({
   1051                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1052                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1053                     "response": {
   1054                         "clientDataJSON": b64_cdata_json,
   1055                         "authenticatorData": b64_adata,
   1056                         "transports": [],
   1057                         "publicKey": null,
   1058                         "publicKeyAlgorithm": -8i8,
   1059                         "attestationObject": b64_aobj,
   1060                     },
   1061                     "clientExtensionResults": {},
   1062                     "type": "public-key"
   1063                 })
   1064                 .to_string()
   1065                 .as_str(),
   1066             )
   1067             .unwrap(),
   1068         );
   1069         // Missing `transports`.
   1070         drop(
   1071             serde_json::from_str::<RegistrationRelaxed>(
   1072                 serde_json::json!({
   1073                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1074                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1075                     "response": {
   1076                         "clientDataJSON": b64_cdata_json,
   1077                         "authenticatorData": b64_adata,
   1078                         "publicKey": b64_key,
   1079                         "publicKeyAlgorithm": -8i8,
   1080                         "attestationObject": b64_aobj,
   1081                     },
   1082                     "clientExtensionResults": {},
   1083                     "type": "public-key"
   1084                 })
   1085                 .to_string()
   1086                 .as_str(),
   1087             )
   1088             .unwrap(),
   1089         );
   1090         // Duplicate `transports` are allowed.
   1091         assert!(
   1092             serde_json::from_str::<RegistrationRelaxed>(
   1093                 serde_json::json!({
   1094                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1095                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1096                     "response": {
   1097                         "clientDataJSON": b64_cdata_json,
   1098                         "authenticatorData": b64_adata,
   1099                         "transports": ["usb", "usb"],
   1100                         "publicKey": b64_key,
   1101                         "publicKeyAlgorithm": -8i8,
   1102                         "attestationObject": b64_aobj,
   1103                     },
   1104                     "clientExtensionResults": {},
   1105                     "type": "public-key"
   1106                 })
   1107                 .to_string()
   1108                 .as_str()
   1109             )
   1110             .is_ok_and(|reg| reg.0.response.transports.count() == 1)
   1111         );
   1112         // `null` `transports`.
   1113         drop(
   1114             serde_json::from_str::<RegistrationRelaxed>(
   1115                 serde_json::json!({
   1116                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1117                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1118                     "response": {
   1119                         "clientDataJSON": b64_cdata_json,
   1120                         "authenticatorData": b64_adata,
   1121                         "transports": null,
   1122                         "publicKey": b64_key,
   1123                         "publicKeyAlgorithm": -8i8,
   1124                         "attestationObject": b64_aobj,
   1125                     },
   1126                     "clientExtensionResults": {},
   1127                     "type": "public-key"
   1128                 })
   1129                 .to_string()
   1130                 .as_str(),
   1131             )
   1132             .unwrap(),
   1133         );
   1134         // Unknown `transports`.
   1135         err = Error::invalid_value(
   1136             Unexpected::Str("Usb"),
   1137             &"'ble', 'cable', 'hybrid', 'internal', 'nfc', 'smart-card', or 'usb'",
   1138         )
   1139         .to_string()
   1140         .into_bytes();
   1141         assert_eq!(
   1142             serde_json::from_str::<RegistrationRelaxed>(
   1143                 serde_json::json!({
   1144                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1145                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1146                     "response": {
   1147                         "clientDataJSON": b64_cdata_json,
   1148                         "authenticatorData": b64_adata,
   1149                         "transports": ["Usb"],
   1150                         "publicKey": b64_key,
   1151                         "publicKeyAlgorithm": -8i8,
   1152                         "attestationObject": b64_aobj,
   1153                     },
   1154                     "clientExtensionResults": {},
   1155                     "type": "public-key"
   1156                 })
   1157                 .to_string()
   1158                 .as_str()
   1159             )
   1160             .unwrap_err()
   1161             .to_string()
   1162             .into_bytes()
   1163             .get(..err.len()),
   1164             Some(err.as_slice())
   1165         );
   1166         // `null` `authenticatorAttachment`.
   1167         assert!(
   1168             serde_json::from_str::<RegistrationRelaxed>(
   1169                 serde_json::json!({
   1170                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1171                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1172                     "response": {
   1173                         "clientDataJSON": b64_cdata_json,
   1174                         "authenticatorData": b64_adata,
   1175                         "transports": [],
   1176                         "publicKey": b64_key,
   1177                         "publicKeyAlgorithm": -8i8,
   1178                         "attestationObject": b64_aobj,
   1179                     },
   1180                     "authenticatorAttachment": null,
   1181                     "clientExtensionResults": {},
   1182                     "type": "public-key"
   1183                 })
   1184                 .to_string()
   1185                 .as_str()
   1186             )
   1187             .is_ok_and(|reg| matches!(
   1188                 reg.0.authenticator_attachment,
   1189                 AuthenticatorAttachment::None
   1190             ))
   1191         );
   1192         // Unknown `authenticatorAttachment`.
   1193         err = Error::invalid_value(
   1194             Unexpected::Str("Platform"),
   1195             &"'platform' or 'cross-platform'",
   1196         )
   1197         .to_string()
   1198         .into_bytes();
   1199         assert_eq!(
   1200             serde_json::from_str::<RegistrationRelaxed>(
   1201                 serde_json::json!({
   1202                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1203                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1204                     "response": {
   1205                         "clientDataJSON": b64_cdata_json,
   1206                         "authenticatorData": b64_adata,
   1207                         "transports": [],
   1208                         "publicKey": b64_key,
   1209                         "publicKeyAlgorithm": -8i8,
   1210                         "attestationObject": b64_aobj,
   1211                     },
   1212                     "authenticatorAttachment": "Platform",
   1213                     "clientExtensionResults": {},
   1214                     "type": "public-key"
   1215                 })
   1216                 .to_string()
   1217                 .as_str()
   1218             )
   1219             .unwrap_err()
   1220             .to_string()
   1221             .into_bytes()
   1222             .get(..err.len()),
   1223             Some(err.as_slice())
   1224         );
   1225         // Missing `clientDataJSON`.
   1226         err = Error::missing_field("clientDataJSON")
   1227             .to_string()
   1228             .into_bytes();
   1229         assert_eq!(
   1230             serde_json::from_str::<RegistrationRelaxed>(
   1231                 serde_json::json!({
   1232                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1233                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1234                     "response": {
   1235                         "authenticatorData": b64_adata,
   1236                         "transports": [],
   1237                         "publicKey": b64_key,
   1238                         "publicKeyAlgorithm": -8i8,
   1239                         "attestationObject": b64_aobj,
   1240                     },
   1241                     "clientExtensionResults": {},
   1242                     "type": "public-key"
   1243                 })
   1244                 .to_string()
   1245                 .as_str()
   1246             )
   1247             .unwrap_err()
   1248             .to_string()
   1249             .into_bytes()
   1250             .get(..err.len()),
   1251             Some(err.as_slice())
   1252         );
   1253         // `null` `clientDataJSON`.
   1254         err = Error::invalid_type(Unexpected::Other("null"), &"base64url-encoded data")
   1255             .to_string()
   1256             .into_bytes();
   1257         assert_eq!(
   1258             serde_json::from_str::<RegistrationRelaxed>(
   1259                 serde_json::json!({
   1260                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1261                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1262                     "response": {
   1263                         "clientDataJSON": null,
   1264                         "authenticatorData": b64_adata,
   1265                         "transports": [],
   1266                         "publicKey": b64_key,
   1267                         "publicKeyAlgorithm": -8i8,
   1268                         "attestationObject": b64_aobj,
   1269                     },
   1270                     "clientExtensionResults": {},
   1271                     "type": "public-key"
   1272                 })
   1273                 .to_string()
   1274                 .as_str()
   1275             )
   1276             .unwrap_err()
   1277             .to_string()
   1278             .into_bytes()
   1279             .get(..err.len()),
   1280             Some(err.as_slice())
   1281         );
   1282         // Missing `attestationObject`.
   1283         err = Error::missing_field("attestationObject")
   1284             .to_string()
   1285             .into_bytes();
   1286         assert_eq!(
   1287             serde_json::from_str::<RegistrationRelaxed>(
   1288                 serde_json::json!({
   1289                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1290                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1291                     "response": {
   1292                         "clientDataJSON": b64_cdata_json,
   1293                         "authenticatorData": b64_adata,
   1294                         "transports": [],
   1295                         "publicKey": b64_key,
   1296                         "publicKeyAlgorithm": -8i8,
   1297                     },
   1298                     "clientExtensionResults": {},
   1299                     "type": "public-key"
   1300                 })
   1301                 .to_string()
   1302                 .as_str()
   1303             )
   1304             .unwrap_err()
   1305             .to_string()
   1306             .into_bytes()
   1307             .get(..err.len()),
   1308             Some(err.as_slice())
   1309         );
   1310         // `null` `attestationObject`.
   1311         err = Error::invalid_type(
   1312             Unexpected::Other("null"),
   1313             &"base64url-encoded attestation object",
   1314         )
   1315         .to_string()
   1316         .into_bytes();
   1317         assert_eq!(
   1318             serde_json::from_str::<RegistrationRelaxed>(
   1319                 serde_json::json!({
   1320                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1321                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1322                     "response": {
   1323                         "clientDataJSON": b64_cdata_json,
   1324                         "authenticatorData": b64_adata,
   1325                         "transports": [],
   1326                         "publicKey": b64_key,
   1327                         "publicKeyAlgorithm": -8i8,
   1328                         "attestationObject": null,
   1329                     },
   1330                     "clientExtensionResults": {},
   1331                     "type": "public-key"
   1332                 })
   1333                 .to_string()
   1334                 .as_str()
   1335             )
   1336             .unwrap_err()
   1337             .to_string()
   1338             .into_bytes()
   1339             .get(..err.len()),
   1340             Some(err.as_slice())
   1341         );
   1342         // Missing `response`.
   1343         err = Error::missing_field("response").to_string().into_bytes();
   1344         assert_eq!(
   1345             serde_json::from_str::<RegistrationRelaxed>(
   1346                 serde_json::json!({
   1347                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1348                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1349                     "clientExtensionResults": {},
   1350                     "type": "public-key"
   1351                 })
   1352                 .to_string()
   1353                 .as_str()
   1354             )
   1355             .unwrap_err()
   1356             .to_string()
   1357             .into_bytes()
   1358             .get(..err.len()),
   1359             Some(err.as_slice())
   1360         );
   1361         // `null` `response`.
   1362         err = Error::invalid_type(Unexpected::Other("null"), &"AuthenticatorAttestation")
   1363             .to_string()
   1364             .into_bytes();
   1365         assert_eq!(
   1366             serde_json::from_str::<RegistrationRelaxed>(
   1367                 serde_json::json!({
   1368                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1369                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1370                     "response": null,
   1371                     "clientExtensionResults": {},
   1372                     "type": "public-key"
   1373                 })
   1374                 .to_string()
   1375                 .as_str()
   1376             )
   1377             .unwrap_err()
   1378             .to_string()
   1379             .into_bytes()
   1380             .get(..err.len()),
   1381             Some(err.as_slice())
   1382         );
   1383         // Empty `response`.
   1384         err = Error::missing_field("clientDataJSON")
   1385             .to_string()
   1386             .into_bytes();
   1387         assert_eq!(
   1388             serde_json::from_str::<RegistrationRelaxed>(
   1389                 serde_json::json!({
   1390                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1391                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1392                     "response": {},
   1393                     "clientExtensionResults": {},
   1394                     "type": "public-key"
   1395                 })
   1396                 .to_string()
   1397                 .as_str()
   1398             )
   1399             .unwrap_err()
   1400             .to_string()
   1401             .into_bytes()
   1402             .get(..err.len()),
   1403             Some(err.as_slice())
   1404         );
   1405         // Missing `clientExtensionResults`.
   1406         drop(
   1407             serde_json::from_str::<RegistrationRelaxed>(
   1408                 serde_json::json!({
   1409                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1410                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1411                     "response": {
   1412                         "clientDataJSON": b64_cdata_json,
   1413                         "authenticatorData": b64_adata,
   1414                         "transports": [],
   1415                         "publicKey": b64_key,
   1416                         "publicKeyAlgorithm": -8i8,
   1417                         "attestationObject": b64_aobj,
   1418                     },
   1419                     "type": "public-key"
   1420                 })
   1421                 .to_string()
   1422                 .as_str(),
   1423             )
   1424             .unwrap(),
   1425         );
   1426         // `null` `clientExtensionResults`.
   1427         drop(
   1428             serde_json::from_str::<RegistrationRelaxed>(
   1429                 serde_json::json!({
   1430                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1431                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1432                     "response": {
   1433                         "clientDataJSON": b64_cdata_json,
   1434                         "authenticatorData": b64_adata,
   1435                         "transports": [],
   1436                         "publicKey": b64_key,
   1437                         "publicKeyAlgorithm": -8i8,
   1438                         "attestationObject": b64_aobj,
   1439                     },
   1440                     "clientExtensionResults": null,
   1441                     "type": "public-key"
   1442                 })
   1443                 .to_string()
   1444                 .as_str(),
   1445             )
   1446             .unwrap(),
   1447         );
   1448         // Missing `type`.
   1449         drop(
   1450             serde_json::from_str::<RegistrationRelaxed>(
   1451                 serde_json::json!({
   1452                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1453                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1454                     "response": {
   1455                         "clientDataJSON": b64_cdata_json,
   1456                         "authenticatorData": b64_adata,
   1457                         "transports": [],
   1458                         "publicKey": b64_key,
   1459                         "publicKeyAlgorithm": -8i8,
   1460                         "attestationObject": b64_aobj,
   1461                     },
   1462                     "clientExtensionResults": {},
   1463                 })
   1464                 .to_string()
   1465                 .as_str(),
   1466             )
   1467             .unwrap(),
   1468         );
   1469         // `null` `type`.
   1470         err = Error::invalid_type(Unexpected::Other("null"), &"public-key")
   1471             .to_string()
   1472             .into_bytes();
   1473         assert_eq!(
   1474             serde_json::from_str::<RegistrationRelaxed>(
   1475                 serde_json::json!({
   1476                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1477                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1478                     "response": {
   1479                         "clientDataJSON": b64_cdata_json,
   1480                         "authenticatorData": b64_adata,
   1481                         "transports": [],
   1482                         "publicKey": b64_key,
   1483                         "publicKeyAlgorithm": -8i8,
   1484                         "attestationObject": b64_aobj,
   1485                     },
   1486                     "clientExtensionResults": {},
   1487                     "type": null
   1488                 })
   1489                 .to_string()
   1490                 .as_str()
   1491             )
   1492             .unwrap_err()
   1493             .to_string()
   1494             .into_bytes()
   1495             .get(..err.len()),
   1496             Some(err.as_slice())
   1497         );
   1498         // Not exactly `public-type` `type`.
   1499         err = Error::invalid_value(Unexpected::Str("Public-key"), &"public-key")
   1500             .to_string()
   1501             .into_bytes();
   1502         assert_eq!(
   1503             serde_json::from_str::<RegistrationRelaxed>(
   1504                 serde_json::json!({
   1505                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1506                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1507                     "response": {
   1508                         "clientDataJSON": b64_cdata_json,
   1509                         "authenticatorData": b64_adata,
   1510                         "transports": [],
   1511                         "publicKey": b64_key,
   1512                         "publicKeyAlgorithm": -8i8,
   1513                         "attestationObject": b64_aobj,
   1514                     },
   1515                     "clientExtensionResults": {},
   1516                     "type": "Public-key"
   1517                 })
   1518                 .to_string()
   1519                 .as_str()
   1520             )
   1521             .unwrap_err()
   1522             .to_string()
   1523             .into_bytes()
   1524             .get(..err.len()),
   1525             Some(err.as_slice())
   1526         );
   1527         // `null`.
   1528         err = Error::invalid_type(Unexpected::Other("null"), &"PublicKeyCredential")
   1529             .to_string()
   1530             .into_bytes();
   1531         assert_eq!(
   1532             serde_json::from_str::<RegistrationRelaxed>(
   1533                 serde_json::json!(null).to_string().as_str()
   1534             )
   1535             .unwrap_err()
   1536             .to_string()
   1537             .into_bytes()
   1538             .get(..err.len()),
   1539             Some(err.as_slice())
   1540         );
   1541         // Empty.
   1542         err = Error::missing_field("response").to_string().into_bytes();
   1543         assert_eq!(
   1544             serde_json::from_str::<RegistrationRelaxed>(serde_json::json!({}).to_string().as_str())
   1545                 .unwrap_err()
   1546                 .to_string()
   1547                 .into_bytes()
   1548                 .get(..err.len()),
   1549             Some(err.as_slice())
   1550         );
   1551         // Unknown field in `response`.
   1552         drop(
   1553             serde_json::from_str::<RegistrationRelaxed>(
   1554                 serde_json::json!({
   1555                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1556                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1557                     "response": {
   1558                         "clientDataJSON": b64_cdata_json,
   1559                         "authenticatorData": b64_adata,
   1560                         "transports": [],
   1561                         "publicKey": b64_key,
   1562                         "publicKeyAlgorithm": -8i8,
   1563                         "attestationObject": b64_aobj,
   1564                         "foo": true,
   1565                     },
   1566                     "clientExtensionResults": {},
   1567                     "type": "public-key"
   1568                 })
   1569                 .to_string()
   1570                 .as_str(),
   1571             )
   1572             .unwrap(),
   1573         );
   1574         // Duplicate field in `response`.
   1575         err = Error::duplicate_field("transports")
   1576             .to_string()
   1577             .into_bytes();
   1578         assert_eq!(
   1579             serde_json::from_str::<RegistrationRelaxed>(
   1580                 format!(
   1581                     "{{
   1582                        \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   1583                        \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   1584                        \"response\": {{
   1585                            \"clientDataJSON\": \"{b64_cdata_json}\",
   1586                            \"authenticatorData\": \"{b64_adata}\",
   1587                            \"transports\": [],
   1588                            \"publicKey\": \"{b64_key}\",
   1589                            \"publicKeyAlgorithm\": -8,
   1590                            \"attestationObject\": \"{b64_aobj}\",
   1591                            \"transports\": []
   1592                        }},
   1593                        \"clientExtensionResults\": {{}},
   1594                        \"type\": \"public-key\"
   1595 
   1596                      }}"
   1597                 )
   1598                 .as_str()
   1599             )
   1600             .unwrap_err()
   1601             .to_string()
   1602             .into_bytes()
   1603             .get(..err.len()),
   1604             Some(err.as_slice())
   1605         );
   1606         // Unknown field in `PublicKeyCredential`.
   1607         drop(
   1608             serde_json::from_str::<RegistrationRelaxed>(
   1609                 serde_json::json!({
   1610                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1611                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1612                     "response": {
   1613                         "clientDataJSON": b64_cdata_json,
   1614                         "authenticatorData": b64_adata,
   1615                         "transports": [],
   1616                         "publicKey": b64_key,
   1617                         "publicKeyAlgorithm": -8i8,
   1618                         "attestationObject": b64_aobj
   1619                     },
   1620                     "clientExtensionResults": {},
   1621                     "type": "public-key",
   1622                     "foo": true,
   1623                 })
   1624                 .to_string()
   1625                 .as_str(),
   1626             )
   1627             .unwrap(),
   1628         );
   1629         // Duplicate field in `PublicKeyCredential`.
   1630         err = Error::duplicate_field("id").to_string().into_bytes();
   1631         assert_eq!(
   1632             serde_json::from_str::<RegistrationRelaxed>(
   1633                 format!(
   1634                     "{{
   1635                        \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   1636                        \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   1637                        \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   1638                        \"response\": {{
   1639                            \"clientDataJSON\": \"{b64_cdata_json}\",
   1640                            \"authenticatorData\": \"{b64_adata}\",
   1641                            \"transports\": [],
   1642                            \"publicKey\": \"{b64_key}\",
   1643                            \"publicKeyAlgorithm\": -8,
   1644                            \"attestationObject\": \"{b64_aobj}\"
   1645                        }},
   1646                        \"clientExtensionResults\": {{}},
   1647                        \"type\": \"public-key\"
   1648 
   1649                      }}"
   1650                 )
   1651                 .as_str()
   1652             )
   1653             .unwrap_err()
   1654             .to_string()
   1655             .into_bytes()
   1656             .get(..err.len()),
   1657             Some(err.as_slice())
   1658         );
   1659         // Base case is correct.
   1660         assert!(
   1661             serde_json::from_str::<CustomRegistration>(
   1662                 serde_json::json!({
   1663                     "attestationObject": b64_aobj,
   1664                     "authenticatorAttachment": "cross-platform",
   1665                     "clientDataJSON": b64_cdata_json,
   1666                     "clientExtensionResults": {},
   1667                     "transports": ["ble", "usb", "hybrid", "internal", "nfc", "smart-card"],
   1668                     "type": "public-key"
   1669                 })
   1670                 .to_string()
   1671                 .as_str()
   1672             )
   1673             .is_ok_and(
   1674                 |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
   1675                     && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
   1676                     && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
   1677                         == *Sha256::digest(c_data_json.as_bytes())
   1678                     && reg.0.response.transports.count() == 6
   1679                     && matches!(
   1680                         reg.0.authenticator_attachment,
   1681                         AuthenticatorAttachment::CrossPlatform
   1682                     )
   1683                     && reg.0.client_extension_results.cred_props.is_none()
   1684                     && reg.0.client_extension_results.prf.is_none()
   1685             )
   1686         );
   1687         // Missing `transports`.
   1688         err = Error::missing_field("transports").to_string().into_bytes();
   1689         assert_eq!(
   1690             serde_json::from_str::<CustomRegistration>(
   1691                 serde_json::json!({
   1692                     "attestationObject": b64_aobj,
   1693                     "authenticatorAttachment": "cross-platform",
   1694                     "clientDataJSON": b64_cdata_json,
   1695                     "clientExtensionResults": {},
   1696                     "type": "public-key"
   1697                 })
   1698                 .to_string()
   1699                 .as_str()
   1700             )
   1701             .unwrap_err()
   1702             .to_string()
   1703             .into_bytes()
   1704             .get(..err.len()),
   1705             Some(err.as_slice())
   1706         );
   1707         // Duplicate `transports` are allowed.
   1708         assert!(
   1709             serde_json::from_str::<CustomRegistration>(
   1710                 serde_json::json!({
   1711                     "attestationObject": b64_aobj,
   1712                     "authenticatorAttachment": "cross-platform",
   1713                     "clientDataJSON": b64_cdata_json,
   1714                     "clientExtensionResults": {},
   1715                     "transports": ["usb", "usb"],
   1716                     "type": "public-key"
   1717                 })
   1718                 .to_string()
   1719                 .as_str()
   1720             )
   1721             .is_ok_and(|reg| reg.0.response.transports.count() == 1)
   1722         );
   1723         // `null` `transports`.
   1724         err = Error::invalid_type(Unexpected::Other("null"), &"AuthTransports")
   1725             .to_string()
   1726             .into_bytes();
   1727         assert_eq!(
   1728             serde_json::from_str::<CustomRegistration>(
   1729                 serde_json::json!({
   1730                     "clientDataJSON": b64_cdata_json,
   1731                     "transports": null,
   1732                     "attestationObject": b64_aobj,
   1733                     "clientExtensionResults": {},
   1734                     "type": "public-key"
   1735                 })
   1736                 .to_string()
   1737                 .as_str()
   1738             )
   1739             .unwrap_err()
   1740             .to_string()
   1741             .into_bytes()
   1742             .get(..err.len()),
   1743             Some(err.as_slice())
   1744         );
   1745         // Unknown `transports`.
   1746         err = Error::invalid_value(
   1747             Unexpected::Str("Usb"),
   1748             &"'ble', 'cable', 'hybrid', 'internal', 'nfc', 'smart-card', or 'usb'",
   1749         )
   1750         .to_string()
   1751         .into_bytes();
   1752         assert_eq!(
   1753             serde_json::from_str::<CustomRegistration>(
   1754                 serde_json::json!({
   1755                     "attestationObject": b64_aobj,
   1756                     "authenticatorAttachment": "cross-platform",
   1757                     "clientDataJSON": b64_cdata_json,
   1758                     "clientExtensionResults": {},
   1759                     "transports": ["Usb"],
   1760                     "type": "public-key"
   1761                 })
   1762                 .to_string()
   1763                 .as_str()
   1764             )
   1765             .unwrap_err()
   1766             .to_string()
   1767             .into_bytes()
   1768             .get(..err.len()),
   1769             Some(err.as_slice())
   1770         );
   1771         // `null` `authenticatorAttachment`.
   1772         assert!(
   1773             serde_json::from_str::<CustomRegistration>(
   1774                 serde_json::json!({
   1775                     "attestationObject": b64_aobj,
   1776                     "authenticatorAttachment": null,
   1777                     "clientDataJSON": b64_cdata_json,
   1778                     "clientExtensionResults": {},
   1779                     "transports": [],
   1780                     "type": "public-key"
   1781                 })
   1782                 .to_string()
   1783                 .as_str()
   1784             )
   1785             .is_ok_and(|reg| matches!(
   1786                 reg.0.authenticator_attachment,
   1787                 AuthenticatorAttachment::None
   1788             ))
   1789         );
   1790         // Unknown `authenticatorAttachment`.
   1791         err = Error::invalid_value(
   1792             Unexpected::Str("Platform"),
   1793             &"'platform' or 'cross-platform'",
   1794         )
   1795         .to_string()
   1796         .into_bytes();
   1797         assert_eq!(
   1798             serde_json::from_str::<CustomRegistration>(
   1799                 serde_json::json!({
   1800                     "attestationObject": b64_aobj,
   1801                     "authenticatorAttachment": "Platform",
   1802                     "clientDataJSON": b64_cdata_json,
   1803                     "clientExtensionResults": {},
   1804                     "transports": [],
   1805                     "type": "public-key"
   1806                 })
   1807                 .to_string()
   1808                 .as_str()
   1809             )
   1810             .unwrap_err()
   1811             .to_string()
   1812             .into_bytes()
   1813             .get(..err.len()),
   1814             Some(err.as_slice())
   1815         );
   1816         // Missing `clientDataJSON`.
   1817         err = Error::missing_field("clientDataJSON")
   1818             .to_string()
   1819             .into_bytes();
   1820         assert_eq!(
   1821             serde_json::from_str::<CustomRegistration>(
   1822                 serde_json::json!({
   1823                     "transports": [],
   1824                     "attestationObject": b64_aobj,
   1825                     "clientExtensionResults": {},
   1826                     "type": "public-key"
   1827                 })
   1828                 .to_string()
   1829                 .as_str()
   1830             )
   1831             .unwrap_err()
   1832             .to_string()
   1833             .into_bytes()
   1834             .get(..err.len()),
   1835             Some(err.as_slice())
   1836         );
   1837         // `null` `clientDataJSON`.
   1838         err = Error::invalid_type(Unexpected::Other("null"), &"base64url-encoded data")
   1839             .to_string()
   1840             .into_bytes();
   1841         assert_eq!(
   1842             serde_json::from_str::<CustomRegistration>(
   1843                 serde_json::json!({
   1844                     "clientDataJSON": null,
   1845                     "transports": [],
   1846                     "attestationObject": b64_aobj,
   1847                 })
   1848                 .to_string()
   1849                 .as_str()
   1850             )
   1851             .unwrap_err()
   1852             .to_string()
   1853             .into_bytes()
   1854             .get(..err.len()),
   1855             Some(err.as_slice())
   1856         );
   1857         // Missing `attestationObject`.
   1858         err = Error::missing_field("attestationObject")
   1859             .to_string()
   1860             .into_bytes();
   1861         assert_eq!(
   1862             serde_json::from_str::<CustomRegistration>(
   1863                 serde_json::json!({
   1864                     "clientDataJSON": b64_cdata_json,
   1865                     "transports": [],
   1866                     "clientExtensionResults": {},
   1867                     "type": "public-key"
   1868                 })
   1869                 .to_string()
   1870                 .as_str()
   1871             )
   1872             .unwrap_err()
   1873             .to_string()
   1874             .into_bytes()
   1875             .get(..err.len()),
   1876             Some(err.as_slice())
   1877         );
   1878         // `null` `attestationObject`.
   1879         err = Error::invalid_type(
   1880             Unexpected::Other("null"),
   1881             &"base64url-encoded attestation object",
   1882         )
   1883         .to_string()
   1884         .into_bytes();
   1885         assert_eq!(
   1886             serde_json::from_str::<CustomRegistration>(
   1887                 serde_json::json!({
   1888                     "clientDataJSON": b64_cdata_json,
   1889                     "transports": [],
   1890                     "attestationObject": null,
   1891                     "clientExtensionResults": {},
   1892                     "type": "public-key"
   1893                 })
   1894                 .to_string()
   1895                 .as_str()
   1896             )
   1897             .unwrap_err()
   1898             .to_string()
   1899             .into_bytes()
   1900             .get(..err.len()),
   1901             Some(err.as_slice())
   1902         );
   1903         // Missing `clientExtensionResults`.
   1904         err = Error::missing_field("clientExtensionResults")
   1905             .to_string()
   1906             .into_bytes();
   1907         assert_eq!(
   1908             serde_json::from_str::<CustomRegistration>(
   1909                 serde_json::json!({
   1910                     "clientDataJSON": b64_cdata_json,
   1911                     "transports": [],
   1912                     "attestationObject": b64_aobj,
   1913                     "type": "public-key"
   1914                 })
   1915                 .to_string()
   1916                 .as_str()
   1917             )
   1918             .unwrap_err()
   1919             .to_string()
   1920             .into_bytes()
   1921             .get(..err.len()),
   1922             Some(err.as_slice())
   1923         );
   1924         // `null` `clientExtensionResults`.
   1925         err = Error::invalid_type(Unexpected::Other("null"), &"ClientExtensionsOutputs")
   1926             .to_string()
   1927             .into_bytes();
   1928         assert_eq!(
   1929             serde_json::from_str::<CustomRegistration>(
   1930                 serde_json::json!({
   1931                     "clientDataJSON": b64_cdata_json,
   1932                     "transports": [],
   1933                     "attestationObject": b64_aobj,
   1934                     "clientExtensionResults": null,
   1935                     "type": "public-key"
   1936                 })
   1937                 .to_string()
   1938                 .as_str()
   1939             )
   1940             .unwrap_err()
   1941             .to_string()
   1942             .into_bytes()
   1943             .get(..err.len()),
   1944             Some(err.as_slice())
   1945         );
   1946         // Missing `type`.
   1947         assert!(
   1948             serde_json::from_str::<CustomRegistration>(
   1949                 serde_json::json!({
   1950                     "attestationObject": b64_aobj,
   1951                     "clientDataJSON": b64_cdata_json,
   1952                     "clientExtensionResults": {},
   1953                     "transports": []
   1954                 })
   1955                 .to_string()
   1956                 .as_str()
   1957             )
   1958             .is_ok_and(|_| true)
   1959         );
   1960         // `null` `type`.
   1961         err = Error::invalid_type(Unexpected::Other("null"), &"public-key")
   1962             .to_string()
   1963             .into_bytes();
   1964         assert_eq!(
   1965             serde_json::from_str::<CustomRegistration>(
   1966                 serde_json::json!({
   1967                     "attestationObject": b64_aobj,
   1968                     "clientDataJSON": b64_cdata_json,
   1969                     "clientExtensionResults": {},
   1970                     "transports": [],
   1971                     "type": null
   1972                 })
   1973                 .to_string()
   1974                 .as_str()
   1975             )
   1976             .unwrap_err()
   1977             .to_string()
   1978             .into_bytes()
   1979             .get(..err.len()),
   1980             Some(err.as_slice())
   1981         );
   1982         // Not exactly `public-type` `type`.
   1983         err = Error::invalid_value(Unexpected::Str("Public-key"), &"public-key")
   1984             .to_string()
   1985             .into_bytes();
   1986         assert_eq!(
   1987             serde_json::from_str::<CustomRegistration>(
   1988                 serde_json::json!({
   1989                     "clientDataJSON": b64_cdata_json,
   1990                     "transports": [],
   1991                     "attestationObject": b64_aobj,
   1992                     "clientExtensionResults": {},
   1993                     "type": "Public-key"
   1994                 })
   1995                 .to_string()
   1996                 .as_str()
   1997             )
   1998             .unwrap_err()
   1999             .to_string()
   2000             .into_bytes()
   2001             .get(..err.len()),
   2002             Some(err.as_slice())
   2003         );
   2004         // `null`.
   2005         err = Error::invalid_type(Unexpected::Other("null"), &"CustomRegistration")
   2006             .to_string()
   2007             .into_bytes();
   2008         assert_eq!(
   2009             serde_json::from_str::<CustomRegistration>(
   2010                 serde_json::json!(null).to_string().as_str()
   2011             )
   2012             .unwrap_err()
   2013             .to_string()
   2014             .into_bytes()
   2015             .get(..err.len()),
   2016             Some(err.as_slice())
   2017         );
   2018         // Empty.
   2019         err = Error::missing_field("attestationObject")
   2020             .to_string()
   2021             .into_bytes();
   2022         assert_eq!(
   2023             serde_json::from_str::<CustomRegistration>(serde_json::json!({}).to_string().as_str())
   2024                 .unwrap_err()
   2025                 .to_string()
   2026                 .into_bytes()
   2027                 .get(..err.len()),
   2028             Some(err.as_slice())
   2029         );
   2030         // Unknown field.
   2031         err = Error::unknown_field(
   2032             "foo",
   2033             [
   2034                 "attestationObject",
   2035                 "authenticatorAttachment",
   2036                 "clientDataJSON",
   2037                 "clientExtensionResults",
   2038                 "transports",
   2039                 "type",
   2040             ]
   2041             .as_slice(),
   2042         )
   2043         .to_string()
   2044         .into_bytes();
   2045         assert_eq!(
   2046             serde_json::from_str::<CustomRegistration>(
   2047                 serde_json::json!({
   2048                     "clientDataJSON": b64_cdata_json,
   2049                     "transports": [],
   2050                     "attestationObject": b64_aobj,
   2051                     "foo": true,
   2052                     "clientExtensionResults": {},
   2053                     "type": "public-key"
   2054                 })
   2055                 .to_string()
   2056                 .as_str()
   2057             )
   2058             .unwrap_err()
   2059             .to_string()
   2060             .into_bytes()
   2061             .get(..err.len()),
   2062             Some(err.as_slice())
   2063         );
   2064         // Duplicate field.
   2065         err = Error::duplicate_field("transports")
   2066             .to_string()
   2067             .into_bytes();
   2068         assert_eq!(
   2069             serde_json::from_str::<CustomRegistration>(
   2070                 format!(
   2071                     "{{
   2072                        \"clientDataJSON\": \"{b64_cdata_json}\",
   2073                        \"transports\": [],
   2074                        \"attestationObject\": \"{b64_aobj}\",
   2075                        \"transports\": []
   2076                        \"clientExtensionResults\": {{}},
   2077                        \"type\": \"public-key\"
   2078                      }}"
   2079                 )
   2080                 .as_str()
   2081             )
   2082             .unwrap_err()
   2083             .to_string()
   2084             .into_bytes()
   2085             .get(..err.len()),
   2086             Some(err.as_slice())
   2087         );
   2088     }
   2089     #[expect(clippy::unwrap_used, reason = "OK in tests")]
   2090     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
   2091     #[expect(clippy::too_many_lines, reason = "a lot to test")]
   2092     #[test]
   2093     fn client_extensions() {
   2094         let c_data_json = serde_json::json!({}).to_string();
   2095         let att_obj: [u8; 143] = [
   2096             cbor::MAP_3,
   2097             cbor::TEXT_3,
   2098             b'f',
   2099             b'm',
   2100             b't',
   2101             cbor::TEXT_4,
   2102             b'n',
   2103             b'o',
   2104             b'n',
   2105             b'e',
   2106             cbor::TEXT_7,
   2107             b'a',
   2108             b't',
   2109             b't',
   2110             b'S',
   2111             b't',
   2112             b'm',
   2113             b't',
   2114             cbor::MAP_0,
   2115             cbor::TEXT_8,
   2116             b'a',
   2117             b'u',
   2118             b't',
   2119             b'h',
   2120             b'D',
   2121             b'a',
   2122             b't',
   2123             b'a',
   2124             cbor::BYTES_INFO_24,
   2125             113,
   2126             // `rpIdHash`.
   2127             0,
   2128             0,
   2129             0,
   2130             0,
   2131             0,
   2132             0,
   2133             0,
   2134             0,
   2135             0,
   2136             0,
   2137             0,
   2138             0,
   2139             0,
   2140             0,
   2141             0,
   2142             0,
   2143             0,
   2144             0,
   2145             0,
   2146             0,
   2147             0,
   2148             0,
   2149             0,
   2150             0,
   2151             0,
   2152             0,
   2153             0,
   2154             0,
   2155             0,
   2156             0,
   2157             0,
   2158             0,
   2159             // `flags`.
   2160             0b0100_0101,
   2161             // `signCount`.
   2162             0,
   2163             0,
   2164             0,
   2165             0,
   2166             // `aaguid`.
   2167             0,
   2168             0,
   2169             0,
   2170             0,
   2171             0,
   2172             0,
   2173             0,
   2174             0,
   2175             0,
   2176             0,
   2177             0,
   2178             0,
   2179             0,
   2180             0,
   2181             0,
   2182             0,
   2183             // `credentialIdLength`.
   2184             0,
   2185             16,
   2186             // `credentialId`.
   2187             0,
   2188             0,
   2189             0,
   2190             0,
   2191             0,
   2192             0,
   2193             0,
   2194             0,
   2195             0,
   2196             0,
   2197             0,
   2198             0,
   2199             0,
   2200             0,
   2201             0,
   2202             0,
   2203             // Ed25519 COSE key.
   2204             cbor::MAP_4,
   2205             KTY,
   2206             OKP,
   2207             ALG,
   2208             EDDSA,
   2209             // `crv`.
   2210             cbor::NEG_ONE,
   2211             // `Ed25519`.
   2212             cbor::SIX,
   2213             // `x`.
   2214             cbor::NEG_TWO,
   2215             cbor::BYTES_INFO_24,
   2216             32,
   2217             // Compressed y-coordinate.
   2218             1,
   2219             1,
   2220             1,
   2221             1,
   2222             1,
   2223             1,
   2224             1,
   2225             1,
   2226             1,
   2227             1,
   2228             1,
   2229             1,
   2230             1,
   2231             1,
   2232             1,
   2233             1,
   2234             1,
   2235             1,
   2236             1,
   2237             1,
   2238             1,
   2239             1,
   2240             1,
   2241             1,
   2242             1,
   2243             1,
   2244             1,
   2245             1,
   2246             1,
   2247             1,
   2248             1,
   2249             1,
   2250         ];
   2251         let pub_key = VerifyingKey::from_bytes(&[1; 32])
   2252             .unwrap()
   2253             .to_public_key_der()
   2254             .unwrap();
   2255         let att_obj_len = att_obj.len();
   2256         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
   2257         let auth_data_start = att_obj_len - 113;
   2258         let b64_adata = base64url_nopad::encode(&att_obj[auth_data_start..]);
   2259         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
   2260         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
   2261         // Base case is valid.
   2262         assert!(
   2263             serde_json::from_str::<RegistrationRelaxed>(
   2264                 serde_json::json!({
   2265                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2266                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2267                     "response": {
   2268                         "clientDataJSON": b64_cdata_json,
   2269                         "authenticatorData": b64_adata,
   2270                         "transports": [],
   2271                         "publicKey": b64_key,
   2272                         "publicKeyAlgorithm": -8i8,
   2273                         "attestationObject": b64_aobj,
   2274                     },
   2275                     "clientExtensionResults": {},
   2276                     "type": "public-key"
   2277                 })
   2278                 .to_string()
   2279                 .as_str()
   2280             )
   2281             .is_ok_and(
   2282                 |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
   2283                     && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
   2284                     && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
   2285                         == *Sha256::digest(c_data_json.as_bytes())
   2286                     && reg.0.response.transports.is_empty()
   2287                     && matches!(
   2288                         reg.0.authenticator_attachment,
   2289                         AuthenticatorAttachment::None
   2290                     )
   2291                     && reg.0.client_extension_results.cred_props.is_none()
   2292                     && reg.0.client_extension_results.prf.is_none()
   2293             )
   2294         );
   2295         // `null` `credProps`.
   2296         assert!(
   2297             serde_json::from_str::<RegistrationRelaxed>(
   2298                 serde_json::json!({
   2299                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2300                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2301                     "response": {
   2302                         "clientDataJSON": b64_cdata_json,
   2303                         "authenticatorData": b64_adata,
   2304                         "transports": [],
   2305                         "publicKey": b64_key,
   2306                         "publicKeyAlgorithm": -8i8,
   2307                         "attestationObject": b64_aobj,
   2308                     },
   2309                     "clientExtensionResults": {
   2310                         "credProps": null
   2311                     },
   2312                     "type": "public-key"
   2313                 })
   2314                 .to_string()
   2315                 .as_str()
   2316             )
   2317             .is_ok_and(|reg| reg.0.client_extension_results.cred_props.is_none()
   2318                 && reg.0.client_extension_results.prf.is_none())
   2319         );
   2320         // `null` `prf`.
   2321         assert!(
   2322             serde_json::from_str::<RegistrationRelaxed>(
   2323                 serde_json::json!({
   2324                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2325                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2326                     "response": {
   2327                         "clientDataJSON": b64_cdata_json,
   2328                         "authenticatorData": b64_adata,
   2329                         "transports": [],
   2330                         "publicKey": b64_key,
   2331                         "publicKeyAlgorithm": -8i8,
   2332                         "attestationObject": b64_aobj,
   2333                     },
   2334                     "clientExtensionResults": {
   2335                         "prf": null
   2336                     },
   2337                     "type": "public-key"
   2338                 })
   2339                 .to_string()
   2340                 .as_str()
   2341             )
   2342             .is_ok_and(|reg| reg.0.client_extension_results.cred_props.is_none()
   2343                 && reg.0.client_extension_results.prf.is_none())
   2344         );
   2345         // Unknown `clientExtensionResults`.
   2346         drop(
   2347             serde_json::from_str::<RegistrationRelaxed>(
   2348                 serde_json::json!({
   2349                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2350                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2351                     "response": {
   2352                         "clientDataJSON": b64_cdata_json,
   2353                         "authenticatorData": b64_adata,
   2354                         "transports": [],
   2355                         "publicKey": b64_key,
   2356                         "publicKeyAlgorithm": -8i8,
   2357                         "attestationObject": b64_aobj,
   2358                     },
   2359                     "clientExtensionResults": {
   2360                         "CredProps": {
   2361                             "rk": true
   2362                         }
   2363                     },
   2364                     "type": "public-key"
   2365                 })
   2366                 .to_string()
   2367                 .as_str(),
   2368             )
   2369             .unwrap(),
   2370         );
   2371         // Duplicate field.
   2372         let mut err = Error::duplicate_field("credProps").to_string().into_bytes();
   2373         assert_eq!(
   2374             serde_json::from_str::<RegistrationRelaxed>(
   2375                 format!(
   2376                     "{{
   2377                        \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   2378                        \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   2379                        \"response\": {{
   2380                            \"clientDataJSON\": \"{b64_cdata_json}\",
   2381                            \"authenticatorData\": \"{b64_adata}\",
   2382                            \"transports\": [],
   2383                            \"publicKey\": \"{b64_key}\",
   2384                            \"publicKeyAlgorithm\": -8,
   2385                            \"attestationObject\": \"{b64_aobj}\"
   2386                        }},
   2387                        \"clientExtensionResults\": {{
   2388                            \"credProps\": null,
   2389                            \"credProps\": null
   2390                        }},
   2391                        \"type\": \"public-key\"
   2392                      }}"
   2393                 )
   2394                 .as_str()
   2395             )
   2396             .unwrap_err()
   2397             .to_string()
   2398             .into_bytes()
   2399             .get(..err.len()),
   2400             Some(err.as_slice())
   2401         );
   2402         // `null` `rk`.
   2403         assert!(
   2404             serde_json::from_str::<RegistrationRelaxed>(
   2405                 serde_json::json!({
   2406                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2407                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2408                     "response": {
   2409                         "clientDataJSON": b64_cdata_json,
   2410                         "authenticatorData": b64_adata,
   2411                         "transports": [],
   2412                         "publicKey": b64_key,
   2413                         "publicKeyAlgorithm": -8i8,
   2414                         "attestationObject": b64_aobj,
   2415                     },
   2416                     "clientExtensionResults": {
   2417                         "credProps": {
   2418                             "rk": null
   2419                         }
   2420                     },
   2421                     "type": "public-key"
   2422                 })
   2423                 .to_string()
   2424                 .as_str()
   2425             )
   2426             .is_ok_and(|reg| reg
   2427                 .0
   2428                 .client_extension_results
   2429                 .cred_props
   2430                 .is_some_and(|props| props.rk.is_none())
   2431                 && reg.0.client_extension_results.prf.is_none())
   2432         );
   2433         // Missing `rk`.
   2434         assert!(
   2435             serde_json::from_str::<RegistrationRelaxed>(
   2436                 serde_json::json!({
   2437                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2438                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2439                     "response": {
   2440                         "clientDataJSON": b64_cdata_json,
   2441                         "authenticatorData": b64_adata,
   2442                         "transports": [],
   2443                         "publicKey": b64_key,
   2444                         "publicKeyAlgorithm": -8i8,
   2445                         "attestationObject": b64_aobj,
   2446                     },
   2447                     "clientExtensionResults": {
   2448                         "credProps": {}
   2449                     },
   2450                     "type": "public-key"
   2451                 })
   2452                 .to_string()
   2453                 .as_str()
   2454             )
   2455             .is_ok_and(|reg| reg
   2456                 .0
   2457                 .client_extension_results
   2458                 .cred_props
   2459                 .is_some_and(|props| props.rk.is_none())
   2460                 && reg.0.client_extension_results.prf.is_none())
   2461         );
   2462         // `true` rk`.
   2463         assert!(
   2464             serde_json::from_str::<RegistrationRelaxed>(
   2465                 serde_json::json!({
   2466                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2467                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2468                     "response": {
   2469                         "clientDataJSON": b64_cdata_json,
   2470                         "authenticatorData": b64_adata,
   2471                         "transports": [],
   2472                         "publicKey": b64_key,
   2473                         "publicKeyAlgorithm": -8i8,
   2474                         "attestationObject": b64_aobj,
   2475                     },
   2476                     "clientExtensionResults": {
   2477                         "credProps": {
   2478                             "rk": true
   2479                         }
   2480                     },
   2481                     "type": "public-key"
   2482                 })
   2483                 .to_string()
   2484                 .as_str()
   2485             )
   2486             .is_ok_and(|reg| reg
   2487                 .0
   2488                 .client_extension_results
   2489                 .cred_props
   2490                 .is_some_and(|props| props.rk.unwrap_or_default())
   2491                 && reg.0.client_extension_results.prf.is_none())
   2492         );
   2493         // `false` rk`.
   2494         assert!(
   2495             serde_json::from_str::<RegistrationRelaxed>(
   2496                 serde_json::json!({
   2497                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2498                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2499                     "response": {
   2500                         "clientDataJSON": b64_cdata_json,
   2501                         "authenticatorData": b64_adata,
   2502                         "transports": [],
   2503                         "publicKey": b64_key,
   2504                         "publicKeyAlgorithm": -8i8,
   2505                         "attestationObject": b64_aobj,
   2506                     },
   2507                     "clientExtensionResults": {
   2508                         "credProps": {
   2509                             "rk": false
   2510                         }
   2511                     },
   2512                     "type": "public-key"
   2513                 })
   2514                 .to_string()
   2515                 .as_str()
   2516             )
   2517             .is_ok_and(|reg| reg
   2518                 .0
   2519                 .client_extension_results
   2520                 .cred_props
   2521                 .is_some_and(|props| props.rk.is_some_and(|rk| !rk))
   2522                 && reg.0.client_extension_results.prf.is_none())
   2523         );
   2524         // Invalid `rk`.
   2525         err = Error::invalid_type(Unexpected::Unsigned(3), &"a boolean")
   2526             .to_string()
   2527             .into_bytes();
   2528         assert_eq!(
   2529             serde_json::from_str::<RegistrationRelaxed>(
   2530                 serde_json::json!({
   2531                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2532                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2533                     "response": {
   2534                         "clientDataJSON": b64_cdata_json,
   2535                         "authenticatorData": b64_adata,
   2536                         "transports": [],
   2537                         "publicKey": b64_key,
   2538                         "publicKeyAlgorithm": -8i8,
   2539                         "attestationObject": b64_aobj,
   2540                     },
   2541                     "clientExtensionResults": {
   2542                         "credProps": {
   2543                             "rk": 3u8
   2544                         }
   2545                     },
   2546                     "type": "public-key"
   2547                 })
   2548                 .to_string()
   2549                 .as_str()
   2550             )
   2551             .unwrap_err()
   2552             .to_string()
   2553             .into_bytes()
   2554             .get(..err.len()),
   2555             Some(err.as_slice())
   2556         );
   2557         // Unknown `credProps` field.
   2558         drop(
   2559             serde_json::from_str::<RegistrationRelaxed>(
   2560                 serde_json::json!({
   2561                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2562                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2563                     "response": {
   2564                         "clientDataJSON": b64_cdata_json,
   2565                         "authenticatorData": b64_adata,
   2566                         "transports": [],
   2567                         "publicKey": b64_key,
   2568                         "publicKeyAlgorithm": -8i8,
   2569                         "attestationObject": b64_aobj,
   2570                     },
   2571                     "clientExtensionResults": {
   2572                         "credProps": {
   2573                             "Rk": true,
   2574                         }
   2575                     },
   2576                     "type": "public-key"
   2577                 })
   2578                 .to_string()
   2579                 .as_str(),
   2580             )
   2581             .unwrap(),
   2582         );
   2583         // Duplicate field in `credProps`.
   2584         err = Error::duplicate_field("rk").to_string().into_bytes();
   2585         assert_eq!(
   2586             serde_json::from_str::<RegistrationRelaxed>(
   2587                 format!(
   2588                     "{{
   2589                        \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   2590                        \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   2591                        \"response\": {{
   2592                            \"clientDataJSON\": \"{b64_cdata_json}\",
   2593                            \"authenticatorData\": \"{b64_adata}\",
   2594                            \"transports\": [],
   2595                            \"publicKey\": \"{b64_key}\",
   2596                            \"publicKeyAlgorithm\": -8,
   2597                            \"attestationObject\": \"{b64_aobj}\"
   2598                        }},
   2599                        \"clientExtensionResults\": {{
   2600                            \"credProps\": {{
   2601                                \"rk\": true,
   2602                                \"rk\": true
   2603                            }}
   2604                        }},
   2605                        \"type\": \"public-key\"
   2606                      }}"
   2607                 )
   2608                 .as_str()
   2609             )
   2610             .unwrap_err()
   2611             .to_string()
   2612             .into_bytes()
   2613             .get(..err.len()),
   2614             Some(err.as_slice())
   2615         );
   2616         // `null` `enabled`.
   2617         err = Error::invalid_type(Unexpected::Other("null"), &"a boolean")
   2618             .to_string()
   2619             .into_bytes();
   2620         assert_eq!(
   2621             serde_json::from_str::<RegistrationRelaxed>(
   2622                 serde_json::json!({
   2623                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2624                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2625                     "response": {
   2626                         "clientDataJSON": b64_cdata_json,
   2627                         "authenticatorData": b64_adata,
   2628                         "transports": [],
   2629                         "publicKey": b64_key,
   2630                         "publicKeyAlgorithm": -8i8,
   2631                         "attestationObject": b64_aobj,
   2632                     },
   2633                     "clientExtensionResults": {
   2634                         "prf": {
   2635                             "enabled": null
   2636                         }
   2637                     },
   2638                     "type": "public-key"
   2639                 })
   2640                 .to_string()
   2641                 .as_str()
   2642             )
   2643             .unwrap_err()
   2644             .to_string()
   2645             .into_bytes()
   2646             .get(..err.len()),
   2647             Some(err.as_slice())
   2648         );
   2649         // Missing `enabled`.
   2650         err = Error::missing_field("enabled").to_string().into_bytes();
   2651         assert_eq!(
   2652             serde_json::from_str::<RegistrationRelaxed>(
   2653                 serde_json::json!({
   2654                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2655                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2656                     "response": {
   2657                         "clientDataJSON": b64_cdata_json,
   2658                         "authenticatorData": b64_adata,
   2659                         "transports": [],
   2660                         "publicKey": b64_key,
   2661                         "publicKeyAlgorithm": -8i8,
   2662                         "attestationObject": b64_aobj,
   2663                     },
   2664                     "clientExtensionResults": {
   2665                         "prf": {}
   2666                     },
   2667                     "type": "public-key"
   2668                 })
   2669                 .to_string()
   2670                 .as_str()
   2671             )
   2672             .unwrap_err()
   2673             .to_string()
   2674             .into_bytes()
   2675             .get(..err.len()),
   2676             Some(err.as_slice())
   2677         );
   2678         // `true` `enabled`.
   2679         assert!(
   2680             serde_json::from_str::<RegistrationRelaxed>(
   2681                 serde_json::json!({
   2682                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2683                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2684                     "response": {
   2685                         "clientDataJSON": b64_cdata_json,
   2686                         "authenticatorData": b64_adata,
   2687                         "transports": [],
   2688                         "publicKey": b64_key,
   2689                         "publicKeyAlgorithm": -8i8,
   2690                         "attestationObject": b64_aobj,
   2691                     },
   2692                     "clientExtensionResults": {
   2693                         "prf": {
   2694                             "enabled": true
   2695                         }
   2696                     },
   2697                     "type": "public-key"
   2698                 })
   2699                 .to_string()
   2700                 .as_str()
   2701             )
   2702             .is_ok_and(|reg| reg.0.client_extension_results.cred_props.is_none()
   2703                 && reg
   2704                     .0
   2705                     .client_extension_results
   2706                     .prf
   2707                     .is_some_and(|prf| prf.enabled))
   2708         );
   2709         // `false` `enabled`.
   2710         assert!(
   2711             serde_json::from_str::<RegistrationRelaxed>(
   2712                 serde_json::json!({
   2713                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2714                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2715                     "response": {
   2716                         "clientDataJSON": b64_cdata_json,
   2717                         "authenticatorData": b64_adata,
   2718                         "transports": [],
   2719                         "publicKey": b64_key,
   2720                         "publicKeyAlgorithm": -8i8,
   2721                         "attestationObject": b64_aobj,
   2722                     },
   2723                     "clientExtensionResults": {
   2724                         "prf": {
   2725                             "enabled": false,
   2726                         }
   2727                     },
   2728                     "type": "public-key"
   2729                 })
   2730                 .to_string()
   2731                 .as_str()
   2732             )
   2733             .is_ok_and(|reg| reg.0.client_extension_results.cred_props.is_none()
   2734                 && reg
   2735                     .0
   2736                     .client_extension_results
   2737                     .prf
   2738                     .is_some_and(|prf| !prf.enabled))
   2739         );
   2740         // Invalid `enabled`.
   2741         err = Error::invalid_type(Unexpected::Unsigned(3), &"a boolean")
   2742             .to_string()
   2743             .into_bytes();
   2744         assert_eq!(
   2745             serde_json::from_str::<RegistrationRelaxed>(
   2746                 serde_json::json!({
   2747                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2748                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2749                     "response": {
   2750                         "clientDataJSON": b64_cdata_json,
   2751                         "authenticatorData": b64_adata,
   2752                         "transports": [],
   2753                         "publicKey": b64_key,
   2754                         "publicKeyAlgorithm": -8i8,
   2755                         "attestationObject": b64_aobj,
   2756                     },
   2757                     "clientExtensionResults": {
   2758                         "prf": {
   2759                             "enabled": 3u8
   2760                         }
   2761                     },
   2762                     "type": "public-key"
   2763                 })
   2764                 .to_string()
   2765                 .as_str()
   2766             )
   2767             .unwrap_err()
   2768             .to_string()
   2769             .into_bytes()
   2770             .get(..err.len()),
   2771             Some(err.as_slice())
   2772         );
   2773         // `null` `results` with `enabled` `true`.
   2774         assert!(
   2775             serde_json::from_str::<RegistrationRelaxed>(
   2776                 serde_json::json!({
   2777                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2778                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2779                     "response": {
   2780                         "clientDataJSON": b64_cdata_json,
   2781                         "authenticatorData": b64_adata,
   2782                         "transports": [],
   2783                         "publicKey": b64_key,
   2784                         "publicKeyAlgorithm": -8i8,
   2785                         "attestationObject": b64_aobj,
   2786                     },
   2787                     "clientExtensionResults": {
   2788                         "prf": {
   2789                             "enabled": true,
   2790                             "results": null,
   2791                         }
   2792                     },
   2793                     "type": "public-key"
   2794                 })
   2795                 .to_string()
   2796                 .as_str()
   2797             )
   2798             .is_ok_and(|reg| reg.0.client_extension_results.cred_props.is_none()
   2799                 && reg
   2800                     .0
   2801                     .client_extension_results
   2802                     .prf
   2803                     .is_some_and(|prf| prf.enabled))
   2804         );
   2805         // `null` `results` with `enabled` `false`.
   2806         err = Error::custom(
   2807             "prf must not have 'results', including a null 'results', if 'enabled' is false",
   2808         )
   2809         .to_string()
   2810         .into_bytes();
   2811         assert_eq!(
   2812             serde_json::from_str::<RegistrationRelaxed>(
   2813                 serde_json::json!({
   2814                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2815                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2816                     "response": {
   2817                         "clientDataJSON": b64_cdata_json,
   2818                         "authenticatorData": b64_adata,
   2819                         "transports": [],
   2820                         "publicKey": b64_key,
   2821                         "publicKeyAlgorithm": -8i8,
   2822                         "attestationObject": b64_aobj,
   2823                     },
   2824                     "clientExtensionResults": {
   2825                         "prf": {
   2826                             "enabled": false,
   2827                             "results": null
   2828                         }
   2829                     },
   2830                     "type": "public-key"
   2831                 })
   2832                 .to_string()
   2833                 .as_str()
   2834             )
   2835             .unwrap_err()
   2836             .to_string()
   2837             .into_bytes()
   2838             .get(..err.len()),
   2839             Some(err.as_slice())
   2840         );
   2841         // Duplicate field in `prf`.
   2842         err = Error::duplicate_field("enabled").to_string().into_bytes();
   2843         assert_eq!(
   2844             serde_json::from_str::<RegistrationRelaxed>(
   2845                 format!(
   2846                     "{{
   2847                        \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   2848                        \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   2849                        \"response\": {{
   2850                            \"clientDataJSON\": \"{b64_cdata_json}\",
   2851                            \"authenticatorData\": \"{b64_adata}\",
   2852                            \"transports\": [],
   2853                            \"publicKey\": \"{b64_key}\",
   2854                            \"publicKeyAlgorithm\": -8,
   2855                            \"attestationObject\": \"{b64_aobj}\"
   2856                        }},
   2857                        \"clientExtensionResults\": {{
   2858                            \"prf\": {{
   2859                                \"enabled\": true,
   2860                                \"enabled\": true
   2861                            }}
   2862                        }},
   2863                        \"type\": \"public-key\"
   2864                      }}"
   2865                 )
   2866                 .as_str()
   2867             )
   2868             .unwrap_err()
   2869             .to_string()
   2870             .into_bytes()
   2871             .get(..err.len()),
   2872             Some(err.as_slice())
   2873         );
   2874         // Missing `first`.
   2875         drop(
   2876             serde_json::from_str::<RegistrationRelaxed>(
   2877                 serde_json::json!({
   2878                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2879                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2880                     "response": {
   2881                         "clientDataJSON": b64_cdata_json,
   2882                         "authenticatorData": b64_adata,
   2883                         "transports": [],
   2884                         "publicKey": b64_key,
   2885                         "publicKeyAlgorithm": -8i8,
   2886                         "attestationObject": b64_aobj,
   2887                     },
   2888                     "clientExtensionResults": {
   2889                         "prf": {
   2890                             "enabled": true,
   2891                             "results": {},
   2892                         }
   2893                     },
   2894                     "type": "public-key"
   2895                 })
   2896                 .to_string()
   2897                 .as_str(),
   2898             )
   2899             .unwrap(),
   2900         );
   2901         // `null` `first`.
   2902         assert!(
   2903             serde_json::from_str::<RegistrationRelaxed>(
   2904                 serde_json::json!({
   2905                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2906                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2907                     "response": {
   2908                         "clientDataJSON": b64_cdata_json,
   2909                         "authenticatorData": b64_adata,
   2910                         "transports": [],
   2911                         "publicKey": b64_key,
   2912                         "publicKeyAlgorithm": -8i8,
   2913                         "attestationObject": b64_aobj,
   2914                     },
   2915                     "clientExtensionResults": {
   2916                         "prf": {
   2917                             "enabled": true,
   2918                             "results": {
   2919                                 "first": null
   2920                             },
   2921                         }
   2922                     },
   2923                     "type": "public-key"
   2924                 })
   2925                 .to_string()
   2926                 .as_str()
   2927             )
   2928             .is_ok_and(|reg| reg.0.client_extension_results.cred_props.is_none()
   2929                 && reg
   2930                     .0
   2931                     .client_extension_results
   2932                     .prf
   2933                     .is_some_and(|prf| prf.enabled))
   2934         );
   2935         // `null` `second`.
   2936         assert!(
   2937             serde_json::from_str::<RegistrationRelaxed>(
   2938                 serde_json::json!({
   2939                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2940                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2941                     "response": {
   2942                         "clientDataJSON": b64_cdata_json,
   2943                         "authenticatorData": b64_adata,
   2944                         "transports": [],
   2945                         "publicKey": b64_key,
   2946                         "publicKeyAlgorithm": -8i8,
   2947                         "attestationObject": b64_aobj,
   2948                     },
   2949                     "clientExtensionResults": {
   2950                         "prf": {
   2951                             "enabled": true,
   2952                             "results": {
   2953                                 "first": null,
   2954                                 "second": null
   2955                             },
   2956                         }
   2957                     },
   2958                     "type": "public-key"
   2959                 })
   2960                 .to_string()
   2961                 .as_str()
   2962             )
   2963             .is_ok_and(|reg| reg.0.client_extension_results.cred_props.is_none()
   2964                 && reg
   2965                     .0
   2966                     .client_extension_results
   2967                     .prf
   2968                     .is_some_and(|prf| prf.enabled))
   2969         );
   2970         // Non-`null` `first`.
   2971         err = Error::invalid_type(Unexpected::Option, &"null")
   2972             .to_string()
   2973             .into_bytes();
   2974         assert_eq!(
   2975             serde_json::from_str::<RegistrationRelaxed>(
   2976                 serde_json::json!({
   2977                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2978                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2979                     "response": {
   2980                         "clientDataJSON": b64_cdata_json,
   2981                         "authenticatorData": b64_adata,
   2982                         "transports": [],
   2983                         "publicKey": b64_key,
   2984                         "publicKeyAlgorithm": -8i8,
   2985                         "attestationObject": b64_aobj,
   2986                     },
   2987                     "clientExtensionResults": {
   2988                         "prf": {
   2989                             "enabled": true,
   2990                             "results": {
   2991                                 "first": ""
   2992                             },
   2993                         }
   2994                     },
   2995                     "type": "public-key"
   2996                 })
   2997                 .to_string()
   2998                 .as_str()
   2999             )
   3000             .unwrap_err()
   3001             .to_string()
   3002             .into_bytes()
   3003             .get(..err.len()),
   3004             Some(err.as_slice())
   3005         );
   3006         // Non-`null` `second`.
   3007         err = Error::invalid_type(Unexpected::Option, &"null")
   3008             .to_string()
   3009             .into_bytes();
   3010         assert_eq!(
   3011             serde_json::from_str::<RegistrationRelaxed>(
   3012                 serde_json::json!({
   3013                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3014                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3015                     "response": {
   3016                         "clientDataJSON": b64_cdata_json,
   3017                         "authenticatorData": b64_adata,
   3018                         "transports": [],
   3019                         "publicKey": b64_key,
   3020                         "publicKeyAlgorithm": -8i8,
   3021                         "attestationObject": b64_aobj,
   3022                     },
   3023                     "clientExtensionResults": {
   3024                         "prf": {
   3025                             "enabled": true,
   3026                             "results": {
   3027                                 "first": null,
   3028                                 "second": ""
   3029                             },
   3030                         }
   3031                     },
   3032                     "type": "public-key"
   3033                 })
   3034                 .to_string()
   3035                 .as_str()
   3036             )
   3037             .unwrap_err()
   3038             .to_string()
   3039             .into_bytes()
   3040             .get(..err.len()),
   3041             Some(err.as_slice())
   3042         );
   3043         // Unknown `prf` field.
   3044         drop(
   3045             serde_json::from_str::<RegistrationRelaxed>(
   3046                 serde_json::json!({
   3047                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3048                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3049                     "response": {
   3050                         "clientDataJSON": b64_cdata_json,
   3051                         "authenticatorData": b64_adata,
   3052                         "transports": [],
   3053                         "publicKey": b64_key,
   3054                         "publicKeyAlgorithm": -8i8,
   3055                         "attestationObject": b64_aobj,
   3056                     },
   3057                     "clientExtensionResults": {
   3058                         "prf": {
   3059                             "enabled": true,
   3060                             "Results": null
   3061                         }
   3062                     },
   3063                     "type": "public-key"
   3064                 })
   3065                 .to_string()
   3066                 .as_str(),
   3067             )
   3068             .unwrap(),
   3069         );
   3070         // Unknown `results` field.
   3071         drop(
   3072             serde_json::from_str::<RegistrationRelaxed>(
   3073                 serde_json::json!({
   3074                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3075                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3076                     "response": {
   3077                         "clientDataJSON": b64_cdata_json,
   3078                         "authenticatorData": b64_adata,
   3079                         "transports": [],
   3080                         "publicKey": b64_key,
   3081                         "publicKeyAlgorithm": -8i8,
   3082                         "attestationObject": b64_aobj,
   3083                     },
   3084                     "clientExtensionResults": {
   3085                         "prf": {
   3086                             "enabled": true,
   3087                             "results": {
   3088                                 "first": null,
   3089                                 "Second": null
   3090                             }
   3091                         }
   3092                     },
   3093                     "type": "public-key"
   3094                 })
   3095                 .to_string()
   3096                 .as_str(),
   3097             )
   3098             .unwrap(),
   3099         );
   3100         // Duplicate field in `results`.
   3101         err = Error::duplicate_field("first").to_string().into_bytes();
   3102         assert_eq!(
   3103             serde_json::from_str::<RegistrationRelaxed>(
   3104                 format!(
   3105                     "{{
   3106                        \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   3107                        \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   3108                        \"response\": {{
   3109                            \"clientDataJSON\": \"{b64_cdata_json}\",
   3110                            \"authenticatorData\": \"{b64_adata}\",
   3111                            \"transports\": [],
   3112                            \"publicKey\": \"{b64_key}\",
   3113                            \"publicKeyAlgorithm\": -8,
   3114                            \"attestationObject\": \"{b64_aobj}\"
   3115                        }},
   3116                        \"clientExtensionResults\": {{
   3117                            \"prf\": {{
   3118                                \"enabled\": true,
   3119                                \"results\": {{
   3120                                    \"first\": null,
   3121                                    \"first\": null
   3122                                }}
   3123                            }}
   3124                        }},
   3125                        \"type\": \"public-key\"
   3126                      }}"
   3127                 )
   3128                 .as_str()
   3129             )
   3130             .unwrap_err()
   3131             .to_string()
   3132             .into_bytes()
   3133             .get(..err.len()),
   3134             Some(err.as_slice())
   3135         );
   3136     }
   3137     #[expect(
   3138         clippy::assertions_on_result_states,
   3139         clippy::unwrap_used,
   3140         reason = "OK in tests"
   3141     )]
   3142     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
   3143     #[expect(clippy::too_many_lines, reason = "a lot to test")]
   3144     #[test]
   3145     fn mldsa87_registration_deserialize_data_mismatch() {
   3146         let c_data_json = serde_json::json!({}).to_string();
   3147         let att_obj: [u8; 2704] = [
   3148             cbor::MAP_3,
   3149             cbor::TEXT_3,
   3150             b'f',
   3151             b'm',
   3152             b't',
   3153             cbor::TEXT_4,
   3154             b'n',
   3155             b'o',
   3156             b'n',
   3157             b'e',
   3158             cbor::TEXT_7,
   3159             b'a',
   3160             b't',
   3161             b't',
   3162             b'S',
   3163             b't',
   3164             b'm',
   3165             b't',
   3166             cbor::MAP_0,
   3167             cbor::TEXT_8,
   3168             b'a',
   3169             b'u',
   3170             b't',
   3171             b'h',
   3172             b'D',
   3173             b'a',
   3174             b't',
   3175             b'a',
   3176             cbor::BYTES_INFO_25,
   3177             10,
   3178             113,
   3179             // `rpIdHash`.
   3180             0,
   3181             0,
   3182             0,
   3183             0,
   3184             0,
   3185             0,
   3186             0,
   3187             0,
   3188             0,
   3189             0,
   3190             0,
   3191             0,
   3192             0,
   3193             0,
   3194             0,
   3195             0,
   3196             0,
   3197             0,
   3198             0,
   3199             0,
   3200             0,
   3201             0,
   3202             0,
   3203             0,
   3204             0,
   3205             0,
   3206             0,
   3207             0,
   3208             0,
   3209             0,
   3210             0,
   3211             0,
   3212             // `flags`.
   3213             0b0100_0101,
   3214             // `signCount`.
   3215             0,
   3216             0,
   3217             0,
   3218             0,
   3219             // `aaguid`.
   3220             0,
   3221             0,
   3222             0,
   3223             0,
   3224             0,
   3225             0,
   3226             0,
   3227             0,
   3228             0,
   3229             0,
   3230             0,
   3231             0,
   3232             0,
   3233             0,
   3234             0,
   3235             0,
   3236             // `credentialIdLength`.
   3237             0,
   3238             16,
   3239             // `credentialId`.
   3240             0,
   3241             0,
   3242             0,
   3243             0,
   3244             0,
   3245             0,
   3246             0,
   3247             0,
   3248             0,
   3249             0,
   3250             0,
   3251             0,
   3252             0,
   3253             0,
   3254             0,
   3255             0,
   3256             // ML-DSA-87 COSE key.
   3257             cbor::MAP_3,
   3258             KTY,
   3259             AKP,
   3260             ALG,
   3261             cbor::NEG_INFO_24,
   3262             MLDSA87,
   3263             // `pub`.
   3264             cbor::NEG_ONE,
   3265             cbor::BYTES_INFO_25,
   3266             10,
   3267             32,
   3268             // Encoded key.
   3269             1,
   3270             1,
   3271             1,
   3272             1,
   3273             1,
   3274             1,
   3275             1,
   3276             1,
   3277             1,
   3278             1,
   3279             1,
   3280             1,
   3281             1,
   3282             1,
   3283             1,
   3284             1,
   3285             1,
   3286             1,
   3287             1,
   3288             1,
   3289             1,
   3290             1,
   3291             1,
   3292             1,
   3293             1,
   3294             1,
   3295             1,
   3296             1,
   3297             1,
   3298             1,
   3299             1,
   3300             1,
   3301             1,
   3302             1,
   3303             1,
   3304             1,
   3305             1,
   3306             1,
   3307             1,
   3308             1,
   3309             1,
   3310             1,
   3311             1,
   3312             1,
   3313             1,
   3314             1,
   3315             1,
   3316             1,
   3317             1,
   3318             1,
   3319             1,
   3320             1,
   3321             1,
   3322             1,
   3323             1,
   3324             1,
   3325             1,
   3326             1,
   3327             1,
   3328             1,
   3329             1,
   3330             1,
   3331             1,
   3332             1,
   3333             1,
   3334             1,
   3335             1,
   3336             1,
   3337             1,
   3338             1,
   3339             1,
   3340             1,
   3341             1,
   3342             1,
   3343             1,
   3344             1,
   3345             1,
   3346             1,
   3347             1,
   3348             1,
   3349             1,
   3350             1,
   3351             1,
   3352             1,
   3353             1,
   3354             1,
   3355             1,
   3356             1,
   3357             1,
   3358             1,
   3359             1,
   3360             1,
   3361             1,
   3362             1,
   3363             1,
   3364             1,
   3365             1,
   3366             1,
   3367             1,
   3368             1,
   3369             1,
   3370             1,
   3371             1,
   3372             1,
   3373             1,
   3374             1,
   3375             1,
   3376             1,
   3377             1,
   3378             1,
   3379             1,
   3380             1,
   3381             1,
   3382             1,
   3383             1,
   3384             1,
   3385             1,
   3386             1,
   3387             1,
   3388             1,
   3389             1,
   3390             1,
   3391             1,
   3392             1,
   3393             1,
   3394             1,
   3395             1,
   3396             1,
   3397             1,
   3398             1,
   3399             1,
   3400             1,
   3401             1,
   3402             1,
   3403             1,
   3404             1,
   3405             1,
   3406             1,
   3407             1,
   3408             1,
   3409             1,
   3410             1,
   3411             1,
   3412             1,
   3413             1,
   3414             1,
   3415             1,
   3416             1,
   3417             1,
   3418             1,
   3419             1,
   3420             1,
   3421             1,
   3422             1,
   3423             1,
   3424             1,
   3425             1,
   3426             1,
   3427             1,
   3428             1,
   3429             1,
   3430             1,
   3431             1,
   3432             1,
   3433             1,
   3434             1,
   3435             1,
   3436             1,
   3437             1,
   3438             1,
   3439             1,
   3440             1,
   3441             1,
   3442             1,
   3443             1,
   3444             1,
   3445             1,
   3446             1,
   3447             1,
   3448             1,
   3449             1,
   3450             1,
   3451             1,
   3452             1,
   3453             1,
   3454             1,
   3455             1,
   3456             1,
   3457             1,
   3458             1,
   3459             1,
   3460             1,
   3461             1,
   3462             1,
   3463             1,
   3464             1,
   3465             1,
   3466             1,
   3467             1,
   3468             1,
   3469             1,
   3470             1,
   3471             1,
   3472             1,
   3473             1,
   3474             1,
   3475             1,
   3476             1,
   3477             1,
   3478             1,
   3479             1,
   3480             1,
   3481             1,
   3482             1,
   3483             1,
   3484             1,
   3485             1,
   3486             1,
   3487             1,
   3488             1,
   3489             1,
   3490             1,
   3491             1,
   3492             1,
   3493             1,
   3494             1,
   3495             1,
   3496             1,
   3497             1,
   3498             1,
   3499             1,
   3500             1,
   3501             1,
   3502             1,
   3503             1,
   3504             1,
   3505             1,
   3506             1,
   3507             1,
   3508             1,
   3509             1,
   3510             1,
   3511             1,
   3512             1,
   3513             1,
   3514             1,
   3515             1,
   3516             1,
   3517             1,
   3518             1,
   3519             1,
   3520             1,
   3521             1,
   3522             1,
   3523             1,
   3524             1,
   3525             1,
   3526             1,
   3527             1,
   3528             1,
   3529             1,
   3530             1,
   3531             1,
   3532             1,
   3533             1,
   3534             1,
   3535             1,
   3536             1,
   3537             1,
   3538             1,
   3539             1,
   3540             1,
   3541             1,
   3542             1,
   3543             1,
   3544             1,
   3545             1,
   3546             1,
   3547             1,
   3548             1,
   3549             1,
   3550             1,
   3551             1,
   3552             1,
   3553             1,
   3554             1,
   3555             1,
   3556             1,
   3557             1,
   3558             1,
   3559             1,
   3560             1,
   3561             1,
   3562             1,
   3563             1,
   3564             1,
   3565             1,
   3566             1,
   3567             1,
   3568             1,
   3569             1,
   3570             1,
   3571             1,
   3572             1,
   3573             1,
   3574             1,
   3575             1,
   3576             1,
   3577             1,
   3578             1,
   3579             1,
   3580             1,
   3581             1,
   3582             1,
   3583             1,
   3584             1,
   3585             1,
   3586             1,
   3587             1,
   3588             1,
   3589             1,
   3590             1,
   3591             1,
   3592             1,
   3593             1,
   3594             1,
   3595             1,
   3596             1,
   3597             1,
   3598             1,
   3599             1,
   3600             1,
   3601             1,
   3602             1,
   3603             1,
   3604             1,
   3605             1,
   3606             1,
   3607             1,
   3608             1,
   3609             1,
   3610             1,
   3611             1,
   3612             1,
   3613             1,
   3614             1,
   3615             1,
   3616             1,
   3617             1,
   3618             1,
   3619             1,
   3620             1,
   3621             1,
   3622             1,
   3623             1,
   3624             1,
   3625             1,
   3626             1,
   3627             1,
   3628             1,
   3629             1,
   3630             1,
   3631             1,
   3632             1,
   3633             1,
   3634             1,
   3635             1,
   3636             1,
   3637             1,
   3638             1,
   3639             1,
   3640             1,
   3641             1,
   3642             1,
   3643             1,
   3644             1,
   3645             1,
   3646             1,
   3647             1,
   3648             1,
   3649             1,
   3650             1,
   3651             1,
   3652             1,
   3653             1,
   3654             1,
   3655             1,
   3656             1,
   3657             1,
   3658             1,
   3659             1,
   3660             1,
   3661             1,
   3662             1,
   3663             1,
   3664             1,
   3665             1,
   3666             1,
   3667             1,
   3668             1,
   3669             1,
   3670             1,
   3671             1,
   3672             1,
   3673             1,
   3674             1,
   3675             1,
   3676             1,
   3677             1,
   3678             1,
   3679             1,
   3680             1,
   3681             1,
   3682             1,
   3683             1,
   3684             1,
   3685             1,
   3686             1,
   3687             1,
   3688             1,
   3689             1,
   3690             1,
   3691             1,
   3692             1,
   3693             1,
   3694             1,
   3695             1,
   3696             1,
   3697             1,
   3698             1,
   3699             1,
   3700             1,
   3701             1,
   3702             1,
   3703             1,
   3704             1,
   3705             1,
   3706             1,
   3707             1,
   3708             1,
   3709             1,
   3710             1,
   3711             1,
   3712             1,
   3713             1,
   3714             1,
   3715             1,
   3716             1,
   3717             1,
   3718             1,
   3719             1,
   3720             1,
   3721             1,
   3722             1,
   3723             1,
   3724             1,
   3725             1,
   3726             1,
   3727             1,
   3728             1,
   3729             1,
   3730             1,
   3731             1,
   3732             1,
   3733             1,
   3734             1,
   3735             1,
   3736             1,
   3737             1,
   3738             1,
   3739             1,
   3740             1,
   3741             1,
   3742             1,
   3743             1,
   3744             1,
   3745             1,
   3746             1,
   3747             1,
   3748             1,
   3749             1,
   3750             1,
   3751             1,
   3752             1,
   3753             1,
   3754             1,
   3755             1,
   3756             1,
   3757             1,
   3758             1,
   3759             1,
   3760             1,
   3761             1,
   3762             1,
   3763             1,
   3764             1,
   3765             1,
   3766             1,
   3767             1,
   3768             1,
   3769             1,
   3770             1,
   3771             1,
   3772             1,
   3773             1,
   3774             1,
   3775             1,
   3776             1,
   3777             1,
   3778             1,
   3779             1,
   3780             1,
   3781             1,
   3782             1,
   3783             1,
   3784             1,
   3785             1,
   3786             1,
   3787             1,
   3788             1,
   3789             1,
   3790             1,
   3791             1,
   3792             1,
   3793             1,
   3794             1,
   3795             1,
   3796             1,
   3797             1,
   3798             1,
   3799             1,
   3800             1,
   3801             1,
   3802             1,
   3803             1,
   3804             1,
   3805             1,
   3806             1,
   3807             1,
   3808             1,
   3809             1,
   3810             1,
   3811             1,
   3812             1,
   3813             1,
   3814             1,
   3815             1,
   3816             1,
   3817             1,
   3818             1,
   3819             1,
   3820             1,
   3821             1,
   3822             1,
   3823             1,
   3824             1,
   3825             1,
   3826             1,
   3827             1,
   3828             1,
   3829             1,
   3830             1,
   3831             1,
   3832             1,
   3833             1,
   3834             1,
   3835             1,
   3836             1,
   3837             1,
   3838             1,
   3839             1,
   3840             1,
   3841             1,
   3842             1,
   3843             1,
   3844             1,
   3845             1,
   3846             1,
   3847             1,
   3848             1,
   3849             1,
   3850             1,
   3851             1,
   3852             1,
   3853             1,
   3854             1,
   3855             1,
   3856             1,
   3857             1,
   3858             1,
   3859             1,
   3860             1,
   3861             1,
   3862             1,
   3863             1,
   3864             1,
   3865             1,
   3866             1,
   3867             1,
   3868             1,
   3869             1,
   3870             1,
   3871             1,
   3872             1,
   3873             1,
   3874             1,
   3875             1,
   3876             1,
   3877             1,
   3878             1,
   3879             1,
   3880             1,
   3881             1,
   3882             1,
   3883             1,
   3884             1,
   3885             1,
   3886             1,
   3887             1,
   3888             1,
   3889             1,
   3890             1,
   3891             1,
   3892             1,
   3893             1,
   3894             1,
   3895             1,
   3896             1,
   3897             1,
   3898             1,
   3899             1,
   3900             1,
   3901             1,
   3902             1,
   3903             1,
   3904             1,
   3905             1,
   3906             1,
   3907             1,
   3908             1,
   3909             1,
   3910             1,
   3911             1,
   3912             1,
   3913             1,
   3914             1,
   3915             1,
   3916             1,
   3917             1,
   3918             1,
   3919             1,
   3920             1,
   3921             1,
   3922             1,
   3923             1,
   3924             1,
   3925             1,
   3926             1,
   3927             1,
   3928             1,
   3929             1,
   3930             1,
   3931             1,
   3932             1,
   3933             1,
   3934             1,
   3935             1,
   3936             1,
   3937             1,
   3938             1,
   3939             1,
   3940             1,
   3941             1,
   3942             1,
   3943             1,
   3944             1,
   3945             1,
   3946             1,
   3947             1,
   3948             1,
   3949             1,
   3950             1,
   3951             1,
   3952             1,
   3953             1,
   3954             1,
   3955             1,
   3956             1,
   3957             1,
   3958             1,
   3959             1,
   3960             1,
   3961             1,
   3962             1,
   3963             1,
   3964             1,
   3965             1,
   3966             1,
   3967             1,
   3968             1,
   3969             1,
   3970             1,
   3971             1,
   3972             1,
   3973             1,
   3974             1,
   3975             1,
   3976             1,
   3977             1,
   3978             1,
   3979             1,
   3980             1,
   3981             1,
   3982             1,
   3983             1,
   3984             1,
   3985             1,
   3986             1,
   3987             1,
   3988             1,
   3989             1,
   3990             1,
   3991             1,
   3992             1,
   3993             1,
   3994             1,
   3995             1,
   3996             1,
   3997             1,
   3998             1,
   3999             1,
   4000             1,
   4001             1,
   4002             1,
   4003             1,
   4004             1,
   4005             1,
   4006             1,
   4007             1,
   4008             1,
   4009             1,
   4010             1,
   4011             1,
   4012             1,
   4013             1,
   4014             1,
   4015             1,
   4016             1,
   4017             1,
   4018             1,
   4019             1,
   4020             1,
   4021             1,
   4022             1,
   4023             1,
   4024             1,
   4025             1,
   4026             1,
   4027             1,
   4028             1,
   4029             1,
   4030             1,
   4031             1,
   4032             1,
   4033             1,
   4034             1,
   4035             1,
   4036             1,
   4037             1,
   4038             1,
   4039             1,
   4040             1,
   4041             1,
   4042             1,
   4043             1,
   4044             1,
   4045             1,
   4046             1,
   4047             1,
   4048             1,
   4049             1,
   4050             1,
   4051             1,
   4052             1,
   4053             1,
   4054             1,
   4055             1,
   4056             1,
   4057             1,
   4058             1,
   4059             1,
   4060             1,
   4061             1,
   4062             1,
   4063             1,
   4064             1,
   4065             1,
   4066             1,
   4067             1,
   4068             1,
   4069             1,
   4070             1,
   4071             1,
   4072             1,
   4073             1,
   4074             1,
   4075             1,
   4076             1,
   4077             1,
   4078             1,
   4079             1,
   4080             1,
   4081             1,
   4082             1,
   4083             1,
   4084             1,
   4085             1,
   4086             1,
   4087             1,
   4088             1,
   4089             1,
   4090             1,
   4091             1,
   4092             1,
   4093             1,
   4094             1,
   4095             1,
   4096             1,
   4097             1,
   4098             1,
   4099             1,
   4100             1,
   4101             1,
   4102             1,
   4103             1,
   4104             1,
   4105             1,
   4106             1,
   4107             1,
   4108             1,
   4109             1,
   4110             1,
   4111             1,
   4112             1,
   4113             1,
   4114             1,
   4115             1,
   4116             1,
   4117             1,
   4118             1,
   4119             1,
   4120             1,
   4121             1,
   4122             1,
   4123             1,
   4124             1,
   4125             1,
   4126             1,
   4127             1,
   4128             1,
   4129             1,
   4130             1,
   4131             1,
   4132             1,
   4133             1,
   4134             1,
   4135             1,
   4136             1,
   4137             1,
   4138             1,
   4139             1,
   4140             1,
   4141             1,
   4142             1,
   4143             1,
   4144             1,
   4145             1,
   4146             1,
   4147             1,
   4148             1,
   4149             1,
   4150             1,
   4151             1,
   4152             1,
   4153             1,
   4154             1,
   4155             1,
   4156             1,
   4157             1,
   4158             1,
   4159             1,
   4160             1,
   4161             1,
   4162             1,
   4163             1,
   4164             1,
   4165             1,
   4166             1,
   4167             1,
   4168             1,
   4169             1,
   4170             1,
   4171             1,
   4172             1,
   4173             1,
   4174             1,
   4175             1,
   4176             1,
   4177             1,
   4178             1,
   4179             1,
   4180             1,
   4181             1,
   4182             1,
   4183             1,
   4184             1,
   4185             1,
   4186             1,
   4187             1,
   4188             1,
   4189             1,
   4190             1,
   4191             1,
   4192             1,
   4193             1,
   4194             1,
   4195             1,
   4196             1,
   4197             1,
   4198             1,
   4199             1,
   4200             1,
   4201             1,
   4202             1,
   4203             1,
   4204             1,
   4205             1,
   4206             1,
   4207             1,
   4208             1,
   4209             1,
   4210             1,
   4211             1,
   4212             1,
   4213             1,
   4214             1,
   4215             1,
   4216             1,
   4217             1,
   4218             1,
   4219             1,
   4220             1,
   4221             1,
   4222             1,
   4223             1,
   4224             1,
   4225             1,
   4226             1,
   4227             1,
   4228             1,
   4229             1,
   4230             1,
   4231             1,
   4232             1,
   4233             1,
   4234             1,
   4235             1,
   4236             1,
   4237             1,
   4238             1,
   4239             1,
   4240             1,
   4241             1,
   4242             1,
   4243             1,
   4244             1,
   4245             1,
   4246             1,
   4247             1,
   4248             1,
   4249             1,
   4250             1,
   4251             1,
   4252             1,
   4253             1,
   4254             1,
   4255             1,
   4256             1,
   4257             1,
   4258             1,
   4259             1,
   4260             1,
   4261             1,
   4262             1,
   4263             1,
   4264             1,
   4265             1,
   4266             1,
   4267             1,
   4268             1,
   4269             1,
   4270             1,
   4271             1,
   4272             1,
   4273             1,
   4274             1,
   4275             1,
   4276             1,
   4277             1,
   4278             1,
   4279             1,
   4280             1,
   4281             1,
   4282             1,
   4283             1,
   4284             1,
   4285             1,
   4286             1,
   4287             1,
   4288             1,
   4289             1,
   4290             1,
   4291             1,
   4292             1,
   4293             1,
   4294             1,
   4295             1,
   4296             1,
   4297             1,
   4298             1,
   4299             1,
   4300             1,
   4301             1,
   4302             1,
   4303             1,
   4304             1,
   4305             1,
   4306             1,
   4307             1,
   4308             1,
   4309             1,
   4310             1,
   4311             1,
   4312             1,
   4313             1,
   4314             1,
   4315             1,
   4316             1,
   4317             1,
   4318             1,
   4319             1,
   4320             1,
   4321             1,
   4322             1,
   4323             1,
   4324             1,
   4325             1,
   4326             1,
   4327             1,
   4328             1,
   4329             1,
   4330             1,
   4331             1,
   4332             1,
   4333             1,
   4334             1,
   4335             1,
   4336             1,
   4337             1,
   4338             1,
   4339             1,
   4340             1,
   4341             1,
   4342             1,
   4343             1,
   4344             1,
   4345             1,
   4346             1,
   4347             1,
   4348             1,
   4349             1,
   4350             1,
   4351             1,
   4352             1,
   4353             1,
   4354             1,
   4355             1,
   4356             1,
   4357             1,
   4358             1,
   4359             1,
   4360             1,
   4361             1,
   4362             1,
   4363             1,
   4364             1,
   4365             1,
   4366             1,
   4367             1,
   4368             1,
   4369             1,
   4370             1,
   4371             1,
   4372             1,
   4373             1,
   4374             1,
   4375             1,
   4376             1,
   4377             1,
   4378             1,
   4379             1,
   4380             1,
   4381             1,
   4382             1,
   4383             1,
   4384             1,
   4385             1,
   4386             1,
   4387             1,
   4388             1,
   4389             1,
   4390             1,
   4391             1,
   4392             1,
   4393             1,
   4394             1,
   4395             1,
   4396             1,
   4397             1,
   4398             1,
   4399             1,
   4400             1,
   4401             1,
   4402             1,
   4403             1,
   4404             1,
   4405             1,
   4406             1,
   4407             1,
   4408             1,
   4409             1,
   4410             1,
   4411             1,
   4412             1,
   4413             1,
   4414             1,
   4415             1,
   4416             1,
   4417             1,
   4418             1,
   4419             1,
   4420             1,
   4421             1,
   4422             1,
   4423             1,
   4424             1,
   4425             1,
   4426             1,
   4427             1,
   4428             1,
   4429             1,
   4430             1,
   4431             1,
   4432             1,
   4433             1,
   4434             1,
   4435             1,
   4436             1,
   4437             1,
   4438             1,
   4439             1,
   4440             1,
   4441             1,
   4442             1,
   4443             1,
   4444             1,
   4445             1,
   4446             1,
   4447             1,
   4448             1,
   4449             1,
   4450             1,
   4451             1,
   4452             1,
   4453             1,
   4454             1,
   4455             1,
   4456             1,
   4457             1,
   4458             1,
   4459             1,
   4460             1,
   4461             1,
   4462             1,
   4463             1,
   4464             1,
   4465             1,
   4466             1,
   4467             1,
   4468             1,
   4469             1,
   4470             1,
   4471             1,
   4472             1,
   4473             1,
   4474             1,
   4475             1,
   4476             1,
   4477             1,
   4478             1,
   4479             1,
   4480             1,
   4481             1,
   4482             1,
   4483             1,
   4484             1,
   4485             1,
   4486             1,
   4487             1,
   4488             1,
   4489             1,
   4490             1,
   4491             1,
   4492             1,
   4493             1,
   4494             1,
   4495             1,
   4496             1,
   4497             1,
   4498             1,
   4499             1,
   4500             1,
   4501             1,
   4502             1,
   4503             1,
   4504             1,
   4505             1,
   4506             1,
   4507             1,
   4508             1,
   4509             1,
   4510             1,
   4511             1,
   4512             1,
   4513             1,
   4514             1,
   4515             1,
   4516             1,
   4517             1,
   4518             1,
   4519             1,
   4520             1,
   4521             1,
   4522             1,
   4523             1,
   4524             1,
   4525             1,
   4526             1,
   4527             1,
   4528             1,
   4529             1,
   4530             1,
   4531             1,
   4532             1,
   4533             1,
   4534             1,
   4535             1,
   4536             1,
   4537             1,
   4538             1,
   4539             1,
   4540             1,
   4541             1,
   4542             1,
   4543             1,
   4544             1,
   4545             1,
   4546             1,
   4547             1,
   4548             1,
   4549             1,
   4550             1,
   4551             1,
   4552             1,
   4553             1,
   4554             1,
   4555             1,
   4556             1,
   4557             1,
   4558             1,
   4559             1,
   4560             1,
   4561             1,
   4562             1,
   4563             1,
   4564             1,
   4565             1,
   4566             1,
   4567             1,
   4568             1,
   4569             1,
   4570             1,
   4571             1,
   4572             1,
   4573             1,
   4574             1,
   4575             1,
   4576             1,
   4577             1,
   4578             1,
   4579             1,
   4580             1,
   4581             1,
   4582             1,
   4583             1,
   4584             1,
   4585             1,
   4586             1,
   4587             1,
   4588             1,
   4589             1,
   4590             1,
   4591             1,
   4592             1,
   4593             1,
   4594             1,
   4595             1,
   4596             1,
   4597             1,
   4598             1,
   4599             1,
   4600             1,
   4601             1,
   4602             1,
   4603             1,
   4604             1,
   4605             1,
   4606             1,
   4607             1,
   4608             1,
   4609             1,
   4610             1,
   4611             1,
   4612             1,
   4613             1,
   4614             1,
   4615             1,
   4616             1,
   4617             1,
   4618             1,
   4619             1,
   4620             1,
   4621             1,
   4622             1,
   4623             1,
   4624             1,
   4625             1,
   4626             1,
   4627             1,
   4628             1,
   4629             1,
   4630             1,
   4631             1,
   4632             1,
   4633             1,
   4634             1,
   4635             1,
   4636             1,
   4637             1,
   4638             1,
   4639             1,
   4640             1,
   4641             1,
   4642             1,
   4643             1,
   4644             1,
   4645             1,
   4646             1,
   4647             1,
   4648             1,
   4649             1,
   4650             1,
   4651             1,
   4652             1,
   4653             1,
   4654             1,
   4655             1,
   4656             1,
   4657             1,
   4658             1,
   4659             1,
   4660             1,
   4661             1,
   4662             1,
   4663             1,
   4664             1,
   4665             1,
   4666             1,
   4667             1,
   4668             1,
   4669             1,
   4670             1,
   4671             1,
   4672             1,
   4673             1,
   4674             1,
   4675             1,
   4676             1,
   4677             1,
   4678             1,
   4679             1,
   4680             1,
   4681             1,
   4682             1,
   4683             1,
   4684             1,
   4685             1,
   4686             1,
   4687             1,
   4688             1,
   4689             1,
   4690             1,
   4691             1,
   4692             1,
   4693             1,
   4694             1,
   4695             1,
   4696             1,
   4697             1,
   4698             1,
   4699             1,
   4700             1,
   4701             1,
   4702             1,
   4703             1,
   4704             1,
   4705             1,
   4706             1,
   4707             1,
   4708             1,
   4709             1,
   4710             1,
   4711             1,
   4712             1,
   4713             1,
   4714             1,
   4715             1,
   4716             1,
   4717             1,
   4718             1,
   4719             1,
   4720             1,
   4721             1,
   4722             1,
   4723             1,
   4724             1,
   4725             1,
   4726             1,
   4727             1,
   4728             1,
   4729             1,
   4730             1,
   4731             1,
   4732             1,
   4733             1,
   4734             1,
   4735             1,
   4736             1,
   4737             1,
   4738             1,
   4739             1,
   4740             1,
   4741             1,
   4742             1,
   4743             1,
   4744             1,
   4745             1,
   4746             1,
   4747             1,
   4748             1,
   4749             1,
   4750             1,
   4751             1,
   4752             1,
   4753             1,
   4754             1,
   4755             1,
   4756             1,
   4757             1,
   4758             1,
   4759             1,
   4760             1,
   4761             1,
   4762             1,
   4763             1,
   4764             1,
   4765             1,
   4766             1,
   4767             1,
   4768             1,
   4769             1,
   4770             1,
   4771             1,
   4772             1,
   4773             1,
   4774             1,
   4775             1,
   4776             1,
   4777             1,
   4778             1,
   4779             1,
   4780             1,
   4781             1,
   4782             1,
   4783             1,
   4784             1,
   4785             1,
   4786             1,
   4787             1,
   4788             1,
   4789             1,
   4790             1,
   4791             1,
   4792             1,
   4793             1,
   4794             1,
   4795             1,
   4796             1,
   4797             1,
   4798             1,
   4799             1,
   4800             1,
   4801             1,
   4802             1,
   4803             1,
   4804             1,
   4805             1,
   4806             1,
   4807             1,
   4808             1,
   4809             1,
   4810             1,
   4811             1,
   4812             1,
   4813             1,
   4814             1,
   4815             1,
   4816             1,
   4817             1,
   4818             1,
   4819             1,
   4820             1,
   4821             1,
   4822             1,
   4823             1,
   4824             1,
   4825             1,
   4826             1,
   4827             1,
   4828             1,
   4829             1,
   4830             1,
   4831             1,
   4832             1,
   4833             1,
   4834             1,
   4835             1,
   4836             1,
   4837             1,
   4838             1,
   4839             1,
   4840             1,
   4841             1,
   4842             1,
   4843             1,
   4844             1,
   4845             1,
   4846             1,
   4847             1,
   4848             1,
   4849             1,
   4850             1,
   4851             1,
   4852             1,
   4853             1,
   4854             1,
   4855             1,
   4856             1,
   4857             1,
   4858             1,
   4859             1,
   4860             1,
   4861             1,
   4862             1,
   4863             1,
   4864             1,
   4865             1,
   4866             1,
   4867             1,
   4868             1,
   4869             1,
   4870             1,
   4871             1,
   4872             1,
   4873             1,
   4874             1,
   4875             1,
   4876             1,
   4877             1,
   4878             1,
   4879             1,
   4880             1,
   4881             1,
   4882             1,
   4883             1,
   4884             1,
   4885             1,
   4886             1,
   4887             1,
   4888             1,
   4889             1,
   4890             1,
   4891             1,
   4892             1,
   4893             1,
   4894             1,
   4895             1,
   4896             1,
   4897             1,
   4898             1,
   4899             1,
   4900             1,
   4901             1,
   4902             1,
   4903             1,
   4904             1,
   4905             1,
   4906             1,
   4907             1,
   4908             1,
   4909             1,
   4910             1,
   4911             1,
   4912             1,
   4913             1,
   4914             1,
   4915             1,
   4916             1,
   4917             1,
   4918             1,
   4919             1,
   4920             1,
   4921             1,
   4922             1,
   4923             1,
   4924             1,
   4925             1,
   4926             1,
   4927             1,
   4928             1,
   4929             1,
   4930             1,
   4931             1,
   4932             1,
   4933             1,
   4934             1,
   4935             1,
   4936             1,
   4937             1,
   4938             1,
   4939             1,
   4940             1,
   4941             1,
   4942             1,
   4943             1,
   4944             1,
   4945             1,
   4946             1,
   4947             1,
   4948             1,
   4949             1,
   4950             1,
   4951             1,
   4952             1,
   4953             1,
   4954             1,
   4955             1,
   4956             1,
   4957             1,
   4958             1,
   4959             1,
   4960             1,
   4961             1,
   4962             1,
   4963             1,
   4964             1,
   4965             1,
   4966             1,
   4967             1,
   4968             1,
   4969             1,
   4970             1,
   4971             1,
   4972             1,
   4973             1,
   4974             1,
   4975             1,
   4976             1,
   4977             1,
   4978             1,
   4979             1,
   4980             1,
   4981             1,
   4982             1,
   4983             1,
   4984             1,
   4985             1,
   4986             1,
   4987             1,
   4988             1,
   4989             1,
   4990             1,
   4991             1,
   4992             1,
   4993             1,
   4994             1,
   4995             1,
   4996             1,
   4997             1,
   4998             1,
   4999             1,
   5000             1,
   5001             1,
   5002             1,
   5003             1,
   5004             1,
   5005             1,
   5006             1,
   5007             1,
   5008             1,
   5009             1,
   5010             1,
   5011             1,
   5012             1,
   5013             1,
   5014             1,
   5015             1,
   5016             1,
   5017             1,
   5018             1,
   5019             1,
   5020             1,
   5021             1,
   5022             1,
   5023             1,
   5024             1,
   5025             1,
   5026             1,
   5027             1,
   5028             1,
   5029             1,
   5030             1,
   5031             1,
   5032             1,
   5033             1,
   5034             1,
   5035             1,
   5036             1,
   5037             1,
   5038             1,
   5039             1,
   5040             1,
   5041             1,
   5042             1,
   5043             1,
   5044             1,
   5045             1,
   5046             1,
   5047             1,
   5048             1,
   5049             1,
   5050             1,
   5051             1,
   5052             1,
   5053             1,
   5054             1,
   5055             1,
   5056             1,
   5057             1,
   5058             1,
   5059             1,
   5060             1,
   5061             1,
   5062             1,
   5063             1,
   5064             1,
   5065             1,
   5066             1,
   5067             1,
   5068             1,
   5069             1,
   5070             1,
   5071             1,
   5072             1,
   5073             1,
   5074             1,
   5075             1,
   5076             1,
   5077             1,
   5078             1,
   5079             1,
   5080             1,
   5081             1,
   5082             1,
   5083             1,
   5084             1,
   5085             1,
   5086             1,
   5087             1,
   5088             1,
   5089             1,
   5090             1,
   5091             1,
   5092             1,
   5093             1,
   5094             1,
   5095             1,
   5096             1,
   5097             1,
   5098             1,
   5099             1,
   5100             1,
   5101             1,
   5102             1,
   5103             1,
   5104             1,
   5105             1,
   5106             1,
   5107             1,
   5108             1,
   5109             1,
   5110             1,
   5111             1,
   5112             1,
   5113             1,
   5114             1,
   5115             1,
   5116             1,
   5117             1,
   5118             1,
   5119             1,
   5120             1,
   5121             1,
   5122             1,
   5123             1,
   5124             1,
   5125             1,
   5126             1,
   5127             1,
   5128             1,
   5129             1,
   5130             1,
   5131             1,
   5132             1,
   5133             1,
   5134             1,
   5135             1,
   5136             1,
   5137             1,
   5138             1,
   5139             1,
   5140             1,
   5141             1,
   5142             1,
   5143             1,
   5144             1,
   5145             1,
   5146             1,
   5147             1,
   5148             1,
   5149             1,
   5150             1,
   5151             1,
   5152             1,
   5153             1,
   5154             1,
   5155             1,
   5156             1,
   5157             1,
   5158             1,
   5159             1,
   5160             1,
   5161             1,
   5162             1,
   5163             1,
   5164             1,
   5165             1,
   5166             1,
   5167             1,
   5168             1,
   5169             1,
   5170             1,
   5171             1,
   5172             1,
   5173             1,
   5174             1,
   5175             1,
   5176             1,
   5177             1,
   5178             1,
   5179             1,
   5180             1,
   5181             1,
   5182             1,
   5183             1,
   5184             1,
   5185             1,
   5186             1,
   5187             1,
   5188             1,
   5189             1,
   5190             1,
   5191             1,
   5192             1,
   5193             1,
   5194             1,
   5195             1,
   5196             1,
   5197             1,
   5198             1,
   5199             1,
   5200             1,
   5201             1,
   5202             1,
   5203             1,
   5204             1,
   5205             1,
   5206             1,
   5207             1,
   5208             1,
   5209             1,
   5210             1,
   5211             1,
   5212             1,
   5213             1,
   5214             1,
   5215             1,
   5216             1,
   5217             1,
   5218             1,
   5219             1,
   5220             1,
   5221             1,
   5222             1,
   5223             1,
   5224             1,
   5225             1,
   5226             1,
   5227             1,
   5228             1,
   5229             1,
   5230             1,
   5231             1,
   5232             1,
   5233             1,
   5234             1,
   5235             1,
   5236             1,
   5237             1,
   5238             1,
   5239             1,
   5240             1,
   5241             1,
   5242             1,
   5243             1,
   5244             1,
   5245             1,
   5246             1,
   5247             1,
   5248             1,
   5249             1,
   5250             1,
   5251             1,
   5252             1,
   5253             1,
   5254             1,
   5255             1,
   5256             1,
   5257             1,
   5258             1,
   5259             1,
   5260             1,
   5261             1,
   5262             1,
   5263             1,
   5264             1,
   5265             1,
   5266             1,
   5267             1,
   5268             1,
   5269             1,
   5270             1,
   5271             1,
   5272             1,
   5273             1,
   5274             1,
   5275             1,
   5276             1,
   5277             1,
   5278             1,
   5279             1,
   5280             1,
   5281             1,
   5282             1,
   5283             1,
   5284             1,
   5285             1,
   5286             1,
   5287             1,
   5288             1,
   5289             1,
   5290             1,
   5291             1,
   5292             1,
   5293             1,
   5294             1,
   5295             1,
   5296             1,
   5297             1,
   5298             1,
   5299             1,
   5300             1,
   5301             1,
   5302             1,
   5303             1,
   5304             1,
   5305             1,
   5306             1,
   5307             1,
   5308             1,
   5309             1,
   5310             1,
   5311             1,
   5312             1,
   5313             1,
   5314             1,
   5315             1,
   5316             1,
   5317             1,
   5318             1,
   5319             1,
   5320             1,
   5321             1,
   5322             1,
   5323             1,
   5324             1,
   5325             1,
   5326             1,
   5327             1,
   5328             1,
   5329             1,
   5330             1,
   5331             1,
   5332             1,
   5333             1,
   5334             1,
   5335             1,
   5336             1,
   5337             1,
   5338             1,
   5339             1,
   5340             1,
   5341             1,
   5342             1,
   5343             1,
   5344             1,
   5345             1,
   5346             1,
   5347             1,
   5348             1,
   5349             1,
   5350             1,
   5351             1,
   5352             1,
   5353             1,
   5354             1,
   5355             1,
   5356             1,
   5357             1,
   5358             1,
   5359             1,
   5360             1,
   5361             1,
   5362             1,
   5363             1,
   5364             1,
   5365             1,
   5366             1,
   5367             1,
   5368             1,
   5369             1,
   5370             1,
   5371             1,
   5372             1,
   5373             1,
   5374             1,
   5375             1,
   5376             1,
   5377             1,
   5378             1,
   5379             1,
   5380             1,
   5381             1,
   5382             1,
   5383             1,
   5384             1,
   5385             1,
   5386             1,
   5387             1,
   5388             1,
   5389             1,
   5390             1,
   5391             1,
   5392             1,
   5393             1,
   5394             1,
   5395             1,
   5396             1,
   5397             1,
   5398             1,
   5399             1,
   5400             1,
   5401             1,
   5402             1,
   5403             1,
   5404             1,
   5405             1,
   5406             1,
   5407             1,
   5408             1,
   5409             1,
   5410             1,
   5411             1,
   5412             1,
   5413             1,
   5414             1,
   5415             1,
   5416             1,
   5417             1,
   5418             1,
   5419             1,
   5420             1,
   5421             1,
   5422             1,
   5423             1,
   5424             1,
   5425             1,
   5426             1,
   5427             1,
   5428             1,
   5429             1,
   5430             1,
   5431             1,
   5432             1,
   5433             1,
   5434             1,
   5435             1,
   5436             1,
   5437             1,
   5438             1,
   5439             1,
   5440             1,
   5441             1,
   5442             1,
   5443             1,
   5444             1,
   5445             1,
   5446             1,
   5447             1,
   5448             1,
   5449             1,
   5450             1,
   5451             1,
   5452             1,
   5453             1,
   5454             1,
   5455             1,
   5456             1,
   5457             1,
   5458             1,
   5459             1,
   5460             1,
   5461             1,
   5462             1,
   5463             1,
   5464             1,
   5465             1,
   5466             1,
   5467             1,
   5468             1,
   5469             1,
   5470             1,
   5471             1,
   5472             1,
   5473             1,
   5474             1,
   5475             1,
   5476             1,
   5477             1,
   5478             1,
   5479             1,
   5480             1,
   5481             1,
   5482             1,
   5483             1,
   5484             1,
   5485             1,
   5486             1,
   5487             1,
   5488             1,
   5489             1,
   5490             1,
   5491             1,
   5492             1,
   5493             1,
   5494             1,
   5495             1,
   5496             1,
   5497             1,
   5498             1,
   5499             1,
   5500             1,
   5501             1,
   5502             1,
   5503             1,
   5504             1,
   5505             1,
   5506             1,
   5507             1,
   5508             1,
   5509             1,
   5510             1,
   5511             1,
   5512             1,
   5513             1,
   5514             1,
   5515             1,
   5516             1,
   5517             1,
   5518             1,
   5519             1,
   5520             1,
   5521             1,
   5522             1,
   5523             1,
   5524             1,
   5525             1,
   5526             1,
   5527             1,
   5528             1,
   5529             1,
   5530             1,
   5531             1,
   5532             1,
   5533             1,
   5534             1,
   5535             1,
   5536             1,
   5537             1,
   5538             1,
   5539             1,
   5540             1,
   5541             1,
   5542             1,
   5543             1,
   5544             1,
   5545             1,
   5546             1,
   5547             1,
   5548             1,
   5549             1,
   5550             1,
   5551             1,
   5552             1,
   5553             1,
   5554             1,
   5555             1,
   5556             1,
   5557             1,
   5558             1,
   5559             1,
   5560             1,
   5561             1,
   5562             1,
   5563             1,
   5564             1,
   5565             1,
   5566             1,
   5567             1,
   5568             1,
   5569             1,
   5570             1,
   5571             1,
   5572             1,
   5573             1,
   5574             1,
   5575             1,
   5576             1,
   5577             1,
   5578             1,
   5579             1,
   5580             1,
   5581             1,
   5582             1,
   5583             1,
   5584             1,
   5585             1,
   5586             1,
   5587             1,
   5588             1,
   5589             1,
   5590             1,
   5591             1,
   5592             1,
   5593             1,
   5594             1,
   5595             1,
   5596             1,
   5597             1,
   5598             1,
   5599             1,
   5600             1,
   5601             1,
   5602             1,
   5603             1,
   5604             1,
   5605             1,
   5606             1,
   5607             1,
   5608             1,
   5609             1,
   5610             1,
   5611             1,
   5612             1,
   5613             1,
   5614             1,
   5615             1,
   5616             1,
   5617             1,
   5618             1,
   5619             1,
   5620             1,
   5621             1,
   5622             1,
   5623             1,
   5624             1,
   5625             1,
   5626             1,
   5627             1,
   5628             1,
   5629             1,
   5630             1,
   5631             1,
   5632             1,
   5633             1,
   5634             1,
   5635             1,
   5636             1,
   5637             1,
   5638             1,
   5639             1,
   5640             1,
   5641             1,
   5642             1,
   5643             1,
   5644             1,
   5645             1,
   5646             1,
   5647             1,
   5648             1,
   5649             1,
   5650             1,
   5651             1,
   5652             1,
   5653             1,
   5654             1,
   5655             1,
   5656             1,
   5657             1,
   5658             1,
   5659             1,
   5660             1,
   5661             1,
   5662             1,
   5663             1,
   5664             1,
   5665             1,
   5666             1,
   5667             1,
   5668             1,
   5669             1,
   5670             1,
   5671             1,
   5672             1,
   5673             1,
   5674             1,
   5675             1,
   5676             1,
   5677             1,
   5678             1,
   5679             1,
   5680             1,
   5681             1,
   5682             1,
   5683             1,
   5684             1,
   5685             1,
   5686             1,
   5687             1,
   5688             1,
   5689             1,
   5690             1,
   5691             1,
   5692             1,
   5693             1,
   5694             1,
   5695             1,
   5696             1,
   5697             1,
   5698             1,
   5699             1,
   5700             1,
   5701             1,
   5702             1,
   5703             1,
   5704             1,
   5705             1,
   5706             1,
   5707             1,
   5708             1,
   5709             1,
   5710             1,
   5711             1,
   5712             1,
   5713             1,
   5714             1,
   5715             1,
   5716             1,
   5717             1,
   5718             1,
   5719             1,
   5720             1,
   5721             1,
   5722             1,
   5723             1,
   5724             1,
   5725             1,
   5726             1,
   5727             1,
   5728             1,
   5729             1,
   5730             1,
   5731             1,
   5732             1,
   5733             1,
   5734             1,
   5735             1,
   5736             1,
   5737             1,
   5738             1,
   5739             1,
   5740             1,
   5741             1,
   5742             1,
   5743             1,
   5744             1,
   5745             1,
   5746             1,
   5747             1,
   5748             1,
   5749             1,
   5750             1,
   5751             1,
   5752             1,
   5753             1,
   5754             1,
   5755             1,
   5756             1,
   5757             1,
   5758             1,
   5759             1,
   5760             1,
   5761             1,
   5762             1,
   5763             1,
   5764             1,
   5765             1,
   5766             1,
   5767             1,
   5768             1,
   5769             1,
   5770             1,
   5771             1,
   5772             1,
   5773             1,
   5774             1,
   5775             1,
   5776             1,
   5777             1,
   5778             1,
   5779             1,
   5780             1,
   5781             1,
   5782             1,
   5783             1,
   5784             1,
   5785             1,
   5786             1,
   5787             1,
   5788             1,
   5789             1,
   5790             1,
   5791             1,
   5792             1,
   5793             1,
   5794             1,
   5795             1,
   5796             1,
   5797             1,
   5798             1,
   5799             1,
   5800             1,
   5801             1,
   5802             1,
   5803             1,
   5804             1,
   5805             1,
   5806             1,
   5807             1,
   5808             1,
   5809             1,
   5810             1,
   5811             1,
   5812             1,
   5813             1,
   5814             1,
   5815             1,
   5816             1,
   5817             1,
   5818             1,
   5819             1,
   5820             1,
   5821             1,
   5822             1,
   5823             1,
   5824             1,
   5825             1,
   5826             1,
   5827             1,
   5828             1,
   5829             1,
   5830             1,
   5831             1,
   5832             1,
   5833             1,
   5834             1,
   5835             1,
   5836             1,
   5837             1,
   5838             1,
   5839             1,
   5840             1,
   5841             1,
   5842             1,
   5843             1,
   5844             1,
   5845             1,
   5846             1,
   5847             1,
   5848             1,
   5849             1,
   5850             1,
   5851             1,
   5852             1,
   5853             1,
   5854             1,
   5855             1,
   5856             1,
   5857             1,
   5858             1,
   5859             1,
   5860             1,
   5861         ];
   5862         let pub_key = MlDsaVerKey::<MlDsa87>::decode(&[1u8; 2592].into())
   5863             .to_public_key_der()
   5864             .unwrap();
   5865         let att_obj_len = att_obj.len();
   5866         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
   5867         let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 2673..]);
   5868         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
   5869         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
   5870         // Base case is valid.
   5871         assert!(
   5872             serde_json::from_str::<RegistrationRelaxed>(
   5873                 serde_json::json!({
   5874                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   5875                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   5876                     "response": {
   5877                         "clientDataJSON": b64_cdata_json,
   5878                         "authenticatorData": b64_adata,
   5879                         "transports": [],
   5880                         "publicKey": b64_key,
   5881                         "publicKeyAlgorithm": -50i8,
   5882                         "attestationObject": b64_aobj,
   5883                     },
   5884                     "clientExtensionResults": {},
   5885                     "type": "public-key"
   5886                 })
   5887                 .to_string()
   5888                 .as_str()
   5889             )
   5890             .is_ok_and(
   5891                 |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
   5892                     && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
   5893                     && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
   5894                         == *Sha256::digest(c_data_json.as_bytes())
   5895                     && reg.0.response.transports.is_empty()
   5896                     && matches!(
   5897                         reg.0.authenticator_attachment,
   5898                         AuthenticatorAttachment::None
   5899                     )
   5900                     && reg.0.client_extension_results.cred_props.is_none()
   5901                     && reg.0.client_extension_results.prf.is_none()
   5902             )
   5903         );
   5904         // `publicKeyAlgorithm` mismatch.
   5905         let mut err = Error::invalid_value(
   5906             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
   5907             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa87).as_str()
   5908         )
   5909         .to_string().into_bytes();
   5910         assert_eq!(
   5911             serde_json::from_str::<RegistrationRelaxed>(
   5912                 serde_json::json!({
   5913                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   5914                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   5915                     "response": {
   5916                         "clientDataJSON": b64_cdata_json,
   5917                         "authenticatorData": b64_adata,
   5918                         "transports": [],
   5919                         "publicKey": b64_key,
   5920                         "publicKeyAlgorithm": -8i8,
   5921                         "attestationObject": b64_aobj,
   5922                     },
   5923                     "clientExtensionResults": {},
   5924                     "type": "public-key"
   5925                 })
   5926                 .to_string()
   5927                 .as_str()
   5928             )
   5929             .unwrap_err()
   5930             .to_string()
   5931             .into_bytes()
   5932             .get(..err.len()),
   5933             Some(err.as_slice())
   5934         );
   5935         // Missing `publicKeyAlgorithm`.
   5936         drop(
   5937             serde_json::from_str::<RegistrationRelaxed>(
   5938                 serde_json::json!({
   5939                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   5940                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   5941                     "response": {
   5942                         "clientDataJSON": b64_cdata_json,
   5943                         "authenticatorData": b64_adata,
   5944                         "transports": [],
   5945                         "publicKey": b64_key,
   5946                         "attestationObject": b64_aobj,
   5947                     },
   5948                     "clientExtensionResults": {},
   5949                     "type": "public-key"
   5950                 })
   5951                 .to_string()
   5952                 .as_str(),
   5953             )
   5954             .unwrap(),
   5955         );
   5956         // `null` `publicKeyAlgorithm`.
   5957         drop(
   5958             serde_json::from_str::<RegistrationRelaxed>(
   5959                 serde_json::json!({
   5960                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   5961                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   5962                     "response": {
   5963                         "clientDataJSON": b64_cdata_json,
   5964                         "authenticatorData": b64_adata,
   5965                         "transports": [],
   5966                         "publicKey": b64_key,
   5967                         "publicKeyAlgorithm": null,
   5968                         "attestationObject": b64_aobj,
   5969                     },
   5970                     "clientExtensionResults": {},
   5971                     "type": "public-key"
   5972                 })
   5973                 .to_string()
   5974                 .as_str(),
   5975             )
   5976             .unwrap(),
   5977         );
   5978         // `publicKey` mismatch.
   5979         let bad_pub_key = MlDsaVerKey::<MlDsa87>::decode(&[2; 2592].into());
   5980         err = Error::invalid_value(
   5981             Unexpected::Bytes([0; 32].as_slice()),
   5982             &format!(
   5983                 "DER-encoded public key to match the public key within the attestation object: MlDsa87(MlDsa87PubKey({:?}))",
   5984                 &[1u8; 2592]
   5985             )
   5986             .as_str(),
   5987         )
   5988         .to_string().into_bytes();
   5989         assert_eq!(serde_json::from_str::<RegistrationRelaxed>(
   5990             serde_json::json!({
   5991                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   5992                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   5993                 "response": {
   5994                     "clientDataJSON": b64_cdata_json,
   5995                     "authenticatorData": b64_adata,
   5996                     "transports": [],
   5997                     "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
   5998                     "publicKeyAlgorithm": -50i8,
   5999                     "attestationObject": b64_aobj,
   6000                 },
   6001                 "clientExtensionResults": {},
   6002                 "type": "public-key"
   6003             })
   6004             .to_string()
   6005             .as_str()
   6006             )
   6007             .unwrap_err().to_string().into_bytes().get(..err.len()),
   6008             Some(err.as_slice())
   6009         );
   6010         // Missing `publicKey` is allowed when not using EdDSA, ES256, or RS256.
   6011         assert!(
   6012             serde_json::from_str::<RegistrationRelaxed>(
   6013                 serde_json::json!({
   6014                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   6015                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   6016                     "response": {
   6017                         "clientDataJSON": b64_cdata_json,
   6018                         "authenticatorData": b64_adata,
   6019                         "transports": [],
   6020                         "publicKeyAlgorithm": -50i8,
   6021                         "attestationObject": b64_aobj,
   6022                     },
   6023                     "clientExtensionResults": {},
   6024                     "type": "public-key"
   6025                 })
   6026                 .to_string()
   6027                 .as_str()
   6028             )
   6029             .is_ok()
   6030         );
   6031         // `publicKeyAlgorithm` mismatch when `publicKey` does not exist.
   6032         err = Error::invalid_value(
   6033             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   6034             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa87).as_str()
   6035         )
   6036         .to_string().into_bytes();
   6037         assert_eq!(
   6038             serde_json::from_str::<RegistrationRelaxed>(
   6039                 serde_json::json!({
   6040                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   6041                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   6042                     "response": {
   6043                         "clientDataJSON": b64_cdata_json,
   6044                         "authenticatorData": b64_adata,
   6045                         "transports": [],
   6046                         "publicKeyAlgorithm": -7i8,
   6047                         "attestationObject": b64_aobj,
   6048                     },
   6049                     "clientExtensionResults": {},
   6050                     "type": "public-key"
   6051                 })
   6052                 .to_string()
   6053                 .as_str()
   6054             )
   6055             .unwrap_err()
   6056             .to_string()
   6057             .into_bytes()
   6058             .get(..err.len()),
   6059             Some(err.as_slice())
   6060         );
   6061         // `null` `publicKey` is allowed when not using EdDSA, ES256, or RS256.
   6062         assert!(
   6063             serde_json::from_str::<RegistrationRelaxed>(
   6064                 serde_json::json!({
   6065                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   6066                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   6067                     "response": {
   6068                         "clientDataJSON": b64_cdata_json,
   6069                         "authenticatorData": b64_adata,
   6070                         "transports": [],
   6071                         "publicKey": null,
   6072                         "publicKeyAlgorithm": -50i8,
   6073                         "attestationObject": b64_aobj,
   6074                     },
   6075                     "clientExtensionResults": {},
   6076                     "type": "public-key"
   6077                 })
   6078                 .to_string()
   6079                 .as_str()
   6080             )
   6081             .is_ok()
   6082         );
   6083         // `publicKeyAlgorithm` mismatch when `publicKey` is null.
   6084         err = Error::invalid_value(
   6085             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   6086             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa87).as_str()
   6087         )
   6088         .to_string().into_bytes();
   6089         assert_eq!(
   6090             serde_json::from_str::<RegistrationRelaxed>(
   6091                 serde_json::json!({
   6092                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   6093                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   6094                     "response": {
   6095                         "clientDataJSON": b64_cdata_json,
   6096                         "authenticatorData": b64_adata,
   6097                         "transports": [],
   6098                         "publicKey": null,
   6099                         "publicKeyAlgorithm": -7i8,
   6100                         "attestationObject": b64_aobj,
   6101                     },
   6102                     "clientExtensionResults": {},
   6103                     "type": "public-key"
   6104                 })
   6105                 .to_string()
   6106                 .as_str()
   6107             )
   6108             .unwrap_err()
   6109             .to_string()
   6110             .into_bytes()
   6111             .get(..err.len()),
   6112             Some(err.as_slice())
   6113         );
   6114     }
   6115     #[expect(
   6116         clippy::assertions_on_result_states,
   6117         clippy::unwrap_used,
   6118         reason = "OK in tests"
   6119     )]
   6120     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
   6121     #[expect(clippy::too_many_lines, reason = "a lot to test")]
   6122     #[test]
   6123     fn mldsa65_registration_deserialize_data_mismatch() {
   6124         let c_data_json = serde_json::json!({}).to_string();
   6125         let att_obj: [u8; 2064] = [
   6126             cbor::MAP_3,
   6127             cbor::TEXT_3,
   6128             b'f',
   6129             b'm',
   6130             b't',
   6131             cbor::TEXT_4,
   6132             b'n',
   6133             b'o',
   6134             b'n',
   6135             b'e',
   6136             cbor::TEXT_7,
   6137             b'a',
   6138             b't',
   6139             b't',
   6140             b'S',
   6141             b't',
   6142             b'm',
   6143             b't',
   6144             cbor::MAP_0,
   6145             cbor::TEXT_8,
   6146             b'a',
   6147             b'u',
   6148             b't',
   6149             b'h',
   6150             b'D',
   6151             b'a',
   6152             b't',
   6153             b'a',
   6154             cbor::BYTES_INFO_25,
   6155             7,
   6156             241,
   6157             // `rpIdHash`.
   6158             0,
   6159             0,
   6160             0,
   6161             0,
   6162             0,
   6163             0,
   6164             0,
   6165             0,
   6166             0,
   6167             0,
   6168             0,
   6169             0,
   6170             0,
   6171             0,
   6172             0,
   6173             0,
   6174             0,
   6175             0,
   6176             0,
   6177             0,
   6178             0,
   6179             0,
   6180             0,
   6181             0,
   6182             0,
   6183             0,
   6184             0,
   6185             0,
   6186             0,
   6187             0,
   6188             0,
   6189             0,
   6190             // `flags`.
   6191             0b0100_0101,
   6192             // `signCount`.
   6193             0,
   6194             0,
   6195             0,
   6196             0,
   6197             // `aaguid`.
   6198             0,
   6199             0,
   6200             0,
   6201             0,
   6202             0,
   6203             0,
   6204             0,
   6205             0,
   6206             0,
   6207             0,
   6208             0,
   6209             0,
   6210             0,
   6211             0,
   6212             0,
   6213             0,
   6214             // `credentialIdLength`.
   6215             0,
   6216             16,
   6217             // `credentialId`.
   6218             0,
   6219             0,
   6220             0,
   6221             0,
   6222             0,
   6223             0,
   6224             0,
   6225             0,
   6226             0,
   6227             0,
   6228             0,
   6229             0,
   6230             0,
   6231             0,
   6232             0,
   6233             0,
   6234             // ML-DSA-65 COSE key.
   6235             cbor::MAP_3,
   6236             KTY,
   6237             AKP,
   6238             ALG,
   6239             cbor::NEG_INFO_24,
   6240             MLDSA65,
   6241             // `pub`.
   6242             cbor::NEG_ONE,
   6243             cbor::BYTES_INFO_25,
   6244             7,
   6245             160,
   6246             // Encoded key.
   6247             1,
   6248             1,
   6249             1,
   6250             1,
   6251             1,
   6252             1,
   6253             1,
   6254             1,
   6255             1,
   6256             1,
   6257             1,
   6258             1,
   6259             1,
   6260             1,
   6261             1,
   6262             1,
   6263             1,
   6264             1,
   6265             1,
   6266             1,
   6267             1,
   6268             1,
   6269             1,
   6270             1,
   6271             1,
   6272             1,
   6273             1,
   6274             1,
   6275             1,
   6276             1,
   6277             1,
   6278             1,
   6279             1,
   6280             1,
   6281             1,
   6282             1,
   6283             1,
   6284             1,
   6285             1,
   6286             1,
   6287             1,
   6288             1,
   6289             1,
   6290             1,
   6291             1,
   6292             1,
   6293             1,
   6294             1,
   6295             1,
   6296             1,
   6297             1,
   6298             1,
   6299             1,
   6300             1,
   6301             1,
   6302             1,
   6303             1,
   6304             1,
   6305             1,
   6306             1,
   6307             1,
   6308             1,
   6309             1,
   6310             1,
   6311             1,
   6312             1,
   6313             1,
   6314             1,
   6315             1,
   6316             1,
   6317             1,
   6318             1,
   6319             1,
   6320             1,
   6321             1,
   6322             1,
   6323             1,
   6324             1,
   6325             1,
   6326             1,
   6327             1,
   6328             1,
   6329             1,
   6330             1,
   6331             1,
   6332             1,
   6333             1,
   6334             1,
   6335             1,
   6336             1,
   6337             1,
   6338             1,
   6339             1,
   6340             1,
   6341             1,
   6342             1,
   6343             1,
   6344             1,
   6345             1,
   6346             1,
   6347             1,
   6348             1,
   6349             1,
   6350             1,
   6351             1,
   6352             1,
   6353             1,
   6354             1,
   6355             1,
   6356             1,
   6357             1,
   6358             1,
   6359             1,
   6360             1,
   6361             1,
   6362             1,
   6363             1,
   6364             1,
   6365             1,
   6366             1,
   6367             1,
   6368             1,
   6369             1,
   6370             1,
   6371             1,
   6372             1,
   6373             1,
   6374             1,
   6375             1,
   6376             1,
   6377             1,
   6378             1,
   6379             1,
   6380             1,
   6381             1,
   6382             1,
   6383             1,
   6384             1,
   6385             1,
   6386             1,
   6387             1,
   6388             1,
   6389             1,
   6390             1,
   6391             1,
   6392             1,
   6393             1,
   6394             1,
   6395             1,
   6396             1,
   6397             1,
   6398             1,
   6399             1,
   6400             1,
   6401             1,
   6402             1,
   6403             1,
   6404             1,
   6405             1,
   6406             1,
   6407             1,
   6408             1,
   6409             1,
   6410             1,
   6411             1,
   6412             1,
   6413             1,
   6414             1,
   6415             1,
   6416             1,
   6417             1,
   6418             1,
   6419             1,
   6420             1,
   6421             1,
   6422             1,
   6423             1,
   6424             1,
   6425             1,
   6426             1,
   6427             1,
   6428             1,
   6429             1,
   6430             1,
   6431             1,
   6432             1,
   6433             1,
   6434             1,
   6435             1,
   6436             1,
   6437             1,
   6438             1,
   6439             1,
   6440             1,
   6441             1,
   6442             1,
   6443             1,
   6444             1,
   6445             1,
   6446             1,
   6447             1,
   6448             1,
   6449             1,
   6450             1,
   6451             1,
   6452             1,
   6453             1,
   6454             1,
   6455             1,
   6456             1,
   6457             1,
   6458             1,
   6459             1,
   6460             1,
   6461             1,
   6462             1,
   6463             1,
   6464             1,
   6465             1,
   6466             1,
   6467             1,
   6468             1,
   6469             1,
   6470             1,
   6471             1,
   6472             1,
   6473             1,
   6474             1,
   6475             1,
   6476             1,
   6477             1,
   6478             1,
   6479             1,
   6480             1,
   6481             1,
   6482             1,
   6483             1,
   6484             1,
   6485             1,
   6486             1,
   6487             1,
   6488             1,
   6489             1,
   6490             1,
   6491             1,
   6492             1,
   6493             1,
   6494             1,
   6495             1,
   6496             1,
   6497             1,
   6498             1,
   6499             1,
   6500             1,
   6501             1,
   6502             1,
   6503             1,
   6504             1,
   6505             1,
   6506             1,
   6507             1,
   6508             1,
   6509             1,
   6510             1,
   6511             1,
   6512             1,
   6513             1,
   6514             1,
   6515             1,
   6516             1,
   6517             1,
   6518             1,
   6519             1,
   6520             1,
   6521             1,
   6522             1,
   6523             1,
   6524             1,
   6525             1,
   6526             1,
   6527             1,
   6528             1,
   6529             1,
   6530             1,
   6531             1,
   6532             1,
   6533             1,
   6534             1,
   6535             1,
   6536             1,
   6537             1,
   6538             1,
   6539             1,
   6540             1,
   6541             1,
   6542             1,
   6543             1,
   6544             1,
   6545             1,
   6546             1,
   6547             1,
   6548             1,
   6549             1,
   6550             1,
   6551             1,
   6552             1,
   6553             1,
   6554             1,
   6555             1,
   6556             1,
   6557             1,
   6558             1,
   6559             1,
   6560             1,
   6561             1,
   6562             1,
   6563             1,
   6564             1,
   6565             1,
   6566             1,
   6567             1,
   6568             1,
   6569             1,
   6570             1,
   6571             1,
   6572             1,
   6573             1,
   6574             1,
   6575             1,
   6576             1,
   6577             1,
   6578             1,
   6579             1,
   6580             1,
   6581             1,
   6582             1,
   6583             1,
   6584             1,
   6585             1,
   6586             1,
   6587             1,
   6588             1,
   6589             1,
   6590             1,
   6591             1,
   6592             1,
   6593             1,
   6594             1,
   6595             1,
   6596             1,
   6597             1,
   6598             1,
   6599             1,
   6600             1,
   6601             1,
   6602             1,
   6603             1,
   6604             1,
   6605             1,
   6606             1,
   6607             1,
   6608             1,
   6609             1,
   6610             1,
   6611             1,
   6612             1,
   6613             1,
   6614             1,
   6615             1,
   6616             1,
   6617             1,
   6618             1,
   6619             1,
   6620             1,
   6621             1,
   6622             1,
   6623             1,
   6624             1,
   6625             1,
   6626             1,
   6627             1,
   6628             1,
   6629             1,
   6630             1,
   6631             1,
   6632             1,
   6633             1,
   6634             1,
   6635             1,
   6636             1,
   6637             1,
   6638             1,
   6639             1,
   6640             1,
   6641             1,
   6642             1,
   6643             1,
   6644             1,
   6645             1,
   6646             1,
   6647             1,
   6648             1,
   6649             1,
   6650             1,
   6651             1,
   6652             1,
   6653             1,
   6654             1,
   6655             1,
   6656             1,
   6657             1,
   6658             1,
   6659             1,
   6660             1,
   6661             1,
   6662             1,
   6663             1,
   6664             1,
   6665             1,
   6666             1,
   6667             1,
   6668             1,
   6669             1,
   6670             1,
   6671             1,
   6672             1,
   6673             1,
   6674             1,
   6675             1,
   6676             1,
   6677             1,
   6678             1,
   6679             1,
   6680             1,
   6681             1,
   6682             1,
   6683             1,
   6684             1,
   6685             1,
   6686             1,
   6687             1,
   6688             1,
   6689             1,
   6690             1,
   6691             1,
   6692             1,
   6693             1,
   6694             1,
   6695             1,
   6696             1,
   6697             1,
   6698             1,
   6699             1,
   6700             1,
   6701             1,
   6702             1,
   6703             1,
   6704             1,
   6705             1,
   6706             1,
   6707             1,
   6708             1,
   6709             1,
   6710             1,
   6711             1,
   6712             1,
   6713             1,
   6714             1,
   6715             1,
   6716             1,
   6717             1,
   6718             1,
   6719             1,
   6720             1,
   6721             1,
   6722             1,
   6723             1,
   6724             1,
   6725             1,
   6726             1,
   6727             1,
   6728             1,
   6729             1,
   6730             1,
   6731             1,
   6732             1,
   6733             1,
   6734             1,
   6735             1,
   6736             1,
   6737             1,
   6738             1,
   6739             1,
   6740             1,
   6741             1,
   6742             1,
   6743             1,
   6744             1,
   6745             1,
   6746             1,
   6747             1,
   6748             1,
   6749             1,
   6750             1,
   6751             1,
   6752             1,
   6753             1,
   6754             1,
   6755             1,
   6756             1,
   6757             1,
   6758             1,
   6759             1,
   6760             1,
   6761             1,
   6762             1,
   6763             1,
   6764             1,
   6765             1,
   6766             1,
   6767             1,
   6768             1,
   6769             1,
   6770             1,
   6771             1,
   6772             1,
   6773             1,
   6774             1,
   6775             1,
   6776             1,
   6777             1,
   6778             1,
   6779             1,
   6780             1,
   6781             1,
   6782             1,
   6783             1,
   6784             1,
   6785             1,
   6786             1,
   6787             1,
   6788             1,
   6789             1,
   6790             1,
   6791             1,
   6792             1,
   6793             1,
   6794             1,
   6795             1,
   6796             1,
   6797             1,
   6798             1,
   6799             1,
   6800             1,
   6801             1,
   6802             1,
   6803             1,
   6804             1,
   6805             1,
   6806             1,
   6807             1,
   6808             1,
   6809             1,
   6810             1,
   6811             1,
   6812             1,
   6813             1,
   6814             1,
   6815             1,
   6816             1,
   6817             1,
   6818             1,
   6819             1,
   6820             1,
   6821             1,
   6822             1,
   6823             1,
   6824             1,
   6825             1,
   6826             1,
   6827             1,
   6828             1,
   6829             1,
   6830             1,
   6831             1,
   6832             1,
   6833             1,
   6834             1,
   6835             1,
   6836             1,
   6837             1,
   6838             1,
   6839             1,
   6840             1,
   6841             1,
   6842             1,
   6843             1,
   6844             1,
   6845             1,
   6846             1,
   6847             1,
   6848             1,
   6849             1,
   6850             1,
   6851             1,
   6852             1,
   6853             1,
   6854             1,
   6855             1,
   6856             1,
   6857             1,
   6858             1,
   6859             1,
   6860             1,
   6861             1,
   6862             1,
   6863             1,
   6864             1,
   6865             1,
   6866             1,
   6867             1,
   6868             1,
   6869             1,
   6870             1,
   6871             1,
   6872             1,
   6873             1,
   6874             1,
   6875             1,
   6876             1,
   6877             1,
   6878             1,
   6879             1,
   6880             1,
   6881             1,
   6882             1,
   6883             1,
   6884             1,
   6885             1,
   6886             1,
   6887             1,
   6888             1,
   6889             1,
   6890             1,
   6891             1,
   6892             1,
   6893             1,
   6894             1,
   6895             1,
   6896             1,
   6897             1,
   6898             1,
   6899             1,
   6900             1,
   6901             1,
   6902             1,
   6903             1,
   6904             1,
   6905             1,
   6906             1,
   6907             1,
   6908             1,
   6909             1,
   6910             1,
   6911             1,
   6912             1,
   6913             1,
   6914             1,
   6915             1,
   6916             1,
   6917             1,
   6918             1,
   6919             1,
   6920             1,
   6921             1,
   6922             1,
   6923             1,
   6924             1,
   6925             1,
   6926             1,
   6927             1,
   6928             1,
   6929             1,
   6930             1,
   6931             1,
   6932             1,
   6933             1,
   6934             1,
   6935             1,
   6936             1,
   6937             1,
   6938             1,
   6939             1,
   6940             1,
   6941             1,
   6942             1,
   6943             1,
   6944             1,
   6945             1,
   6946             1,
   6947             1,
   6948             1,
   6949             1,
   6950             1,
   6951             1,
   6952             1,
   6953             1,
   6954             1,
   6955             1,
   6956             1,
   6957             1,
   6958             1,
   6959             1,
   6960             1,
   6961             1,
   6962             1,
   6963             1,
   6964             1,
   6965             1,
   6966             1,
   6967             1,
   6968             1,
   6969             1,
   6970             1,
   6971             1,
   6972             1,
   6973             1,
   6974             1,
   6975             1,
   6976             1,
   6977             1,
   6978             1,
   6979             1,
   6980             1,
   6981             1,
   6982             1,
   6983             1,
   6984             1,
   6985             1,
   6986             1,
   6987             1,
   6988             1,
   6989             1,
   6990             1,
   6991             1,
   6992             1,
   6993             1,
   6994             1,
   6995             1,
   6996             1,
   6997             1,
   6998             1,
   6999             1,
   7000             1,
   7001             1,
   7002             1,
   7003             1,
   7004             1,
   7005             1,
   7006             1,
   7007             1,
   7008             1,
   7009             1,
   7010             1,
   7011             1,
   7012             1,
   7013             1,
   7014             1,
   7015             1,
   7016             1,
   7017             1,
   7018             1,
   7019             1,
   7020             1,
   7021             1,
   7022             1,
   7023             1,
   7024             1,
   7025             1,
   7026             1,
   7027             1,
   7028             1,
   7029             1,
   7030             1,
   7031             1,
   7032             1,
   7033             1,
   7034             1,
   7035             1,
   7036             1,
   7037             1,
   7038             1,
   7039             1,
   7040             1,
   7041             1,
   7042             1,
   7043             1,
   7044             1,
   7045             1,
   7046             1,
   7047             1,
   7048             1,
   7049             1,
   7050             1,
   7051             1,
   7052             1,
   7053             1,
   7054             1,
   7055             1,
   7056             1,
   7057             1,
   7058             1,
   7059             1,
   7060             1,
   7061             1,
   7062             1,
   7063             1,
   7064             1,
   7065             1,
   7066             1,
   7067             1,
   7068             1,
   7069             1,
   7070             1,
   7071             1,
   7072             1,
   7073             1,
   7074             1,
   7075             1,
   7076             1,
   7077             1,
   7078             1,
   7079             1,
   7080             1,
   7081             1,
   7082             1,
   7083             1,
   7084             1,
   7085             1,
   7086             1,
   7087             1,
   7088             1,
   7089             1,
   7090             1,
   7091             1,
   7092             1,
   7093             1,
   7094             1,
   7095             1,
   7096             1,
   7097             1,
   7098             1,
   7099             1,
   7100             1,
   7101             1,
   7102             1,
   7103             1,
   7104             1,
   7105             1,
   7106             1,
   7107             1,
   7108             1,
   7109             1,
   7110             1,
   7111             1,
   7112             1,
   7113             1,
   7114             1,
   7115             1,
   7116             1,
   7117             1,
   7118             1,
   7119             1,
   7120             1,
   7121             1,
   7122             1,
   7123             1,
   7124             1,
   7125             1,
   7126             1,
   7127             1,
   7128             1,
   7129             1,
   7130             1,
   7131             1,
   7132             1,
   7133             1,
   7134             1,
   7135             1,
   7136             1,
   7137             1,
   7138             1,
   7139             1,
   7140             1,
   7141             1,
   7142             1,
   7143             1,
   7144             1,
   7145             1,
   7146             1,
   7147             1,
   7148             1,
   7149             1,
   7150             1,
   7151             1,
   7152             1,
   7153             1,
   7154             1,
   7155             1,
   7156             1,
   7157             1,
   7158             1,
   7159             1,
   7160             1,
   7161             1,
   7162             1,
   7163             1,
   7164             1,
   7165             1,
   7166             1,
   7167             1,
   7168             1,
   7169             1,
   7170             1,
   7171             1,
   7172             1,
   7173             1,
   7174             1,
   7175             1,
   7176             1,
   7177             1,
   7178             1,
   7179             1,
   7180             1,
   7181             1,
   7182             1,
   7183             1,
   7184             1,
   7185             1,
   7186             1,
   7187             1,
   7188             1,
   7189             1,
   7190             1,
   7191             1,
   7192             1,
   7193             1,
   7194             1,
   7195             1,
   7196             1,
   7197             1,
   7198             1,
   7199             1,
   7200             1,
   7201             1,
   7202             1,
   7203             1,
   7204             1,
   7205             1,
   7206             1,
   7207             1,
   7208             1,
   7209             1,
   7210             1,
   7211             1,
   7212             1,
   7213             1,
   7214             1,
   7215             1,
   7216             1,
   7217             1,
   7218             1,
   7219             1,
   7220             1,
   7221             1,
   7222             1,
   7223             1,
   7224             1,
   7225             1,
   7226             1,
   7227             1,
   7228             1,
   7229             1,
   7230             1,
   7231             1,
   7232             1,
   7233             1,
   7234             1,
   7235             1,
   7236             1,
   7237             1,
   7238             1,
   7239             1,
   7240             1,
   7241             1,
   7242             1,
   7243             1,
   7244             1,
   7245             1,
   7246             1,
   7247             1,
   7248             1,
   7249             1,
   7250             1,
   7251             1,
   7252             1,
   7253             1,
   7254             1,
   7255             1,
   7256             1,
   7257             1,
   7258             1,
   7259             1,
   7260             1,
   7261             1,
   7262             1,
   7263             1,
   7264             1,
   7265             1,
   7266             1,
   7267             1,
   7268             1,
   7269             1,
   7270             1,
   7271             1,
   7272             1,
   7273             1,
   7274             1,
   7275             1,
   7276             1,
   7277             1,
   7278             1,
   7279             1,
   7280             1,
   7281             1,
   7282             1,
   7283             1,
   7284             1,
   7285             1,
   7286             1,
   7287             1,
   7288             1,
   7289             1,
   7290             1,
   7291             1,
   7292             1,
   7293             1,
   7294             1,
   7295             1,
   7296             1,
   7297             1,
   7298             1,
   7299             1,
   7300             1,
   7301             1,
   7302             1,
   7303             1,
   7304             1,
   7305             1,
   7306             1,
   7307             1,
   7308             1,
   7309             1,
   7310             1,
   7311             1,
   7312             1,
   7313             1,
   7314             1,
   7315             1,
   7316             1,
   7317             1,
   7318             1,
   7319             1,
   7320             1,
   7321             1,
   7322             1,
   7323             1,
   7324             1,
   7325             1,
   7326             1,
   7327             1,
   7328             1,
   7329             1,
   7330             1,
   7331             1,
   7332             1,
   7333             1,
   7334             1,
   7335             1,
   7336             1,
   7337             1,
   7338             1,
   7339             1,
   7340             1,
   7341             1,
   7342             1,
   7343             1,
   7344             1,
   7345             1,
   7346             1,
   7347             1,
   7348             1,
   7349             1,
   7350             1,
   7351             1,
   7352             1,
   7353             1,
   7354             1,
   7355             1,
   7356             1,
   7357             1,
   7358             1,
   7359             1,
   7360             1,
   7361             1,
   7362             1,
   7363             1,
   7364             1,
   7365             1,
   7366             1,
   7367             1,
   7368             1,
   7369             1,
   7370             1,
   7371             1,
   7372             1,
   7373             1,
   7374             1,
   7375             1,
   7376             1,
   7377             1,
   7378             1,
   7379             1,
   7380             1,
   7381             1,
   7382             1,
   7383             1,
   7384             1,
   7385             1,
   7386             1,
   7387             1,
   7388             1,
   7389             1,
   7390             1,
   7391             1,
   7392             1,
   7393             1,
   7394             1,
   7395             1,
   7396             1,
   7397             1,
   7398             1,
   7399             1,
   7400             1,
   7401             1,
   7402             1,
   7403             1,
   7404             1,
   7405             1,
   7406             1,
   7407             1,
   7408             1,
   7409             1,
   7410             1,
   7411             1,
   7412             1,
   7413             1,
   7414             1,
   7415             1,
   7416             1,
   7417             1,
   7418             1,
   7419             1,
   7420             1,
   7421             1,
   7422             1,
   7423             1,
   7424             1,
   7425             1,
   7426             1,
   7427             1,
   7428             1,
   7429             1,
   7430             1,
   7431             1,
   7432             1,
   7433             1,
   7434             1,
   7435             1,
   7436             1,
   7437             1,
   7438             1,
   7439             1,
   7440             1,
   7441             1,
   7442             1,
   7443             1,
   7444             1,
   7445             1,
   7446             1,
   7447             1,
   7448             1,
   7449             1,
   7450             1,
   7451             1,
   7452             1,
   7453             1,
   7454             1,
   7455             1,
   7456             1,
   7457             1,
   7458             1,
   7459             1,
   7460             1,
   7461             1,
   7462             1,
   7463             1,
   7464             1,
   7465             1,
   7466             1,
   7467             1,
   7468             1,
   7469             1,
   7470             1,
   7471             1,
   7472             1,
   7473             1,
   7474             1,
   7475             1,
   7476             1,
   7477             1,
   7478             1,
   7479             1,
   7480             1,
   7481             1,
   7482             1,
   7483             1,
   7484             1,
   7485             1,
   7486             1,
   7487             1,
   7488             1,
   7489             1,
   7490             1,
   7491             1,
   7492             1,
   7493             1,
   7494             1,
   7495             1,
   7496             1,
   7497             1,
   7498             1,
   7499             1,
   7500             1,
   7501             1,
   7502             1,
   7503             1,
   7504             1,
   7505             1,
   7506             1,
   7507             1,
   7508             1,
   7509             1,
   7510             1,
   7511             1,
   7512             1,
   7513             1,
   7514             1,
   7515             1,
   7516             1,
   7517             1,
   7518             1,
   7519             1,
   7520             1,
   7521             1,
   7522             1,
   7523             1,
   7524             1,
   7525             1,
   7526             1,
   7527             1,
   7528             1,
   7529             1,
   7530             1,
   7531             1,
   7532             1,
   7533             1,
   7534             1,
   7535             1,
   7536             1,
   7537             1,
   7538             1,
   7539             1,
   7540             1,
   7541             1,
   7542             1,
   7543             1,
   7544             1,
   7545             1,
   7546             1,
   7547             1,
   7548             1,
   7549             1,
   7550             1,
   7551             1,
   7552             1,
   7553             1,
   7554             1,
   7555             1,
   7556             1,
   7557             1,
   7558             1,
   7559             1,
   7560             1,
   7561             1,
   7562             1,
   7563             1,
   7564             1,
   7565             1,
   7566             1,
   7567             1,
   7568             1,
   7569             1,
   7570             1,
   7571             1,
   7572             1,
   7573             1,
   7574             1,
   7575             1,
   7576             1,
   7577             1,
   7578             1,
   7579             1,
   7580             1,
   7581             1,
   7582             1,
   7583             1,
   7584             1,
   7585             1,
   7586             1,
   7587             1,
   7588             1,
   7589             1,
   7590             1,
   7591             1,
   7592             1,
   7593             1,
   7594             1,
   7595             1,
   7596             1,
   7597             1,
   7598             1,
   7599             1,
   7600             1,
   7601             1,
   7602             1,
   7603             1,
   7604             1,
   7605             1,
   7606             1,
   7607             1,
   7608             1,
   7609             1,
   7610             1,
   7611             1,
   7612             1,
   7613             1,
   7614             1,
   7615             1,
   7616             1,
   7617             1,
   7618             1,
   7619             1,
   7620             1,
   7621             1,
   7622             1,
   7623             1,
   7624             1,
   7625             1,
   7626             1,
   7627             1,
   7628             1,
   7629             1,
   7630             1,
   7631             1,
   7632             1,
   7633             1,
   7634             1,
   7635             1,
   7636             1,
   7637             1,
   7638             1,
   7639             1,
   7640             1,
   7641             1,
   7642             1,
   7643             1,
   7644             1,
   7645             1,
   7646             1,
   7647             1,
   7648             1,
   7649             1,
   7650             1,
   7651             1,
   7652             1,
   7653             1,
   7654             1,
   7655             1,
   7656             1,
   7657             1,
   7658             1,
   7659             1,
   7660             1,
   7661             1,
   7662             1,
   7663             1,
   7664             1,
   7665             1,
   7666             1,
   7667             1,
   7668             1,
   7669             1,
   7670             1,
   7671             1,
   7672             1,
   7673             1,
   7674             1,
   7675             1,
   7676             1,
   7677             1,
   7678             1,
   7679             1,
   7680             1,
   7681             1,
   7682             1,
   7683             1,
   7684             1,
   7685             1,
   7686             1,
   7687             1,
   7688             1,
   7689             1,
   7690             1,
   7691             1,
   7692             1,
   7693             1,
   7694             1,
   7695             1,
   7696             1,
   7697             1,
   7698             1,
   7699             1,
   7700             1,
   7701             1,
   7702             1,
   7703             1,
   7704             1,
   7705             1,
   7706             1,
   7707             1,
   7708             1,
   7709             1,
   7710             1,
   7711             1,
   7712             1,
   7713             1,
   7714             1,
   7715             1,
   7716             1,
   7717             1,
   7718             1,
   7719             1,
   7720             1,
   7721             1,
   7722             1,
   7723             1,
   7724             1,
   7725             1,
   7726             1,
   7727             1,
   7728             1,
   7729             1,
   7730             1,
   7731             1,
   7732             1,
   7733             1,
   7734             1,
   7735             1,
   7736             1,
   7737             1,
   7738             1,
   7739             1,
   7740             1,
   7741             1,
   7742             1,
   7743             1,
   7744             1,
   7745             1,
   7746             1,
   7747             1,
   7748             1,
   7749             1,
   7750             1,
   7751             1,
   7752             1,
   7753             1,
   7754             1,
   7755             1,
   7756             1,
   7757             1,
   7758             1,
   7759             1,
   7760             1,
   7761             1,
   7762             1,
   7763             1,
   7764             1,
   7765             1,
   7766             1,
   7767             1,
   7768             1,
   7769             1,
   7770             1,
   7771             1,
   7772             1,
   7773             1,
   7774             1,
   7775             1,
   7776             1,
   7777             1,
   7778             1,
   7779             1,
   7780             1,
   7781             1,
   7782             1,
   7783             1,
   7784             1,
   7785             1,
   7786             1,
   7787             1,
   7788             1,
   7789             1,
   7790             1,
   7791             1,
   7792             1,
   7793             1,
   7794             1,
   7795             1,
   7796             1,
   7797             1,
   7798             1,
   7799             1,
   7800             1,
   7801             1,
   7802             1,
   7803             1,
   7804             1,
   7805             1,
   7806             1,
   7807             1,
   7808             1,
   7809             1,
   7810             1,
   7811             1,
   7812             1,
   7813             1,
   7814             1,
   7815             1,
   7816             1,
   7817             1,
   7818             1,
   7819             1,
   7820             1,
   7821             1,
   7822             1,
   7823             1,
   7824             1,
   7825             1,
   7826             1,
   7827             1,
   7828             1,
   7829             1,
   7830             1,
   7831             1,
   7832             1,
   7833             1,
   7834             1,
   7835             1,
   7836             1,
   7837             1,
   7838             1,
   7839             1,
   7840             1,
   7841             1,
   7842             1,
   7843             1,
   7844             1,
   7845             1,
   7846             1,
   7847             1,
   7848             1,
   7849             1,
   7850             1,
   7851             1,
   7852             1,
   7853             1,
   7854             1,
   7855             1,
   7856             1,
   7857             1,
   7858             1,
   7859             1,
   7860             1,
   7861             1,
   7862             1,
   7863             1,
   7864             1,
   7865             1,
   7866             1,
   7867             1,
   7868             1,
   7869             1,
   7870             1,
   7871             1,
   7872             1,
   7873             1,
   7874             1,
   7875             1,
   7876             1,
   7877             1,
   7878             1,
   7879             1,
   7880             1,
   7881             1,
   7882             1,
   7883             1,
   7884             1,
   7885             1,
   7886             1,
   7887             1,
   7888             1,
   7889             1,
   7890             1,
   7891             1,
   7892             1,
   7893             1,
   7894             1,
   7895             1,
   7896             1,
   7897             1,
   7898             1,
   7899             1,
   7900             1,
   7901             1,
   7902             1,
   7903             1,
   7904             1,
   7905             1,
   7906             1,
   7907             1,
   7908             1,
   7909             1,
   7910             1,
   7911             1,
   7912             1,
   7913             1,
   7914             1,
   7915             1,
   7916             1,
   7917             1,
   7918             1,
   7919             1,
   7920             1,
   7921             1,
   7922             1,
   7923             1,
   7924             1,
   7925             1,
   7926             1,
   7927             1,
   7928             1,
   7929             1,
   7930             1,
   7931             1,
   7932             1,
   7933             1,
   7934             1,
   7935             1,
   7936             1,
   7937             1,
   7938             1,
   7939             1,
   7940             1,
   7941             1,
   7942             1,
   7943             1,
   7944             1,
   7945             1,
   7946             1,
   7947             1,
   7948             1,
   7949             1,
   7950             1,
   7951             1,
   7952             1,
   7953             1,
   7954             1,
   7955             1,
   7956             1,
   7957             1,
   7958             1,
   7959             1,
   7960             1,
   7961             1,
   7962             1,
   7963             1,
   7964             1,
   7965             1,
   7966             1,
   7967             1,
   7968             1,
   7969             1,
   7970             1,
   7971             1,
   7972             1,
   7973             1,
   7974             1,
   7975             1,
   7976             1,
   7977             1,
   7978             1,
   7979             1,
   7980             1,
   7981             1,
   7982             1,
   7983             1,
   7984             1,
   7985             1,
   7986             1,
   7987             1,
   7988             1,
   7989             1,
   7990             1,
   7991             1,
   7992             1,
   7993             1,
   7994             1,
   7995             1,
   7996             1,
   7997             1,
   7998             1,
   7999             1,
   8000             1,
   8001             1,
   8002             1,
   8003             1,
   8004             1,
   8005             1,
   8006             1,
   8007             1,
   8008             1,
   8009             1,
   8010             1,
   8011             1,
   8012             1,
   8013             1,
   8014             1,
   8015             1,
   8016             1,
   8017             1,
   8018             1,
   8019             1,
   8020             1,
   8021             1,
   8022             1,
   8023             1,
   8024             1,
   8025             1,
   8026             1,
   8027             1,
   8028             1,
   8029             1,
   8030             1,
   8031             1,
   8032             1,
   8033             1,
   8034             1,
   8035             1,
   8036             1,
   8037             1,
   8038             1,
   8039             1,
   8040             1,
   8041             1,
   8042             1,
   8043             1,
   8044             1,
   8045             1,
   8046             1,
   8047             1,
   8048             1,
   8049             1,
   8050             1,
   8051             1,
   8052             1,
   8053             1,
   8054             1,
   8055             1,
   8056             1,
   8057             1,
   8058             1,
   8059             1,
   8060             1,
   8061             1,
   8062             1,
   8063             1,
   8064             1,
   8065             1,
   8066             1,
   8067             1,
   8068             1,
   8069             1,
   8070             1,
   8071             1,
   8072             1,
   8073             1,
   8074             1,
   8075             1,
   8076             1,
   8077             1,
   8078             1,
   8079             1,
   8080             1,
   8081             1,
   8082             1,
   8083             1,
   8084             1,
   8085             1,
   8086             1,
   8087             1,
   8088             1,
   8089             1,
   8090             1,
   8091             1,
   8092             1,
   8093             1,
   8094             1,
   8095             1,
   8096             1,
   8097             1,
   8098             1,
   8099             1,
   8100             1,
   8101             1,
   8102             1,
   8103             1,
   8104             1,
   8105             1,
   8106             1,
   8107             1,
   8108             1,
   8109             1,
   8110             1,
   8111             1,
   8112             1,
   8113             1,
   8114             1,
   8115             1,
   8116             1,
   8117             1,
   8118             1,
   8119             1,
   8120             1,
   8121             1,
   8122             1,
   8123             1,
   8124             1,
   8125             1,
   8126             1,
   8127             1,
   8128             1,
   8129             1,
   8130             1,
   8131             1,
   8132             1,
   8133             1,
   8134             1,
   8135             1,
   8136             1,
   8137             1,
   8138             1,
   8139             1,
   8140             1,
   8141             1,
   8142             1,
   8143             1,
   8144             1,
   8145             1,
   8146             1,
   8147             1,
   8148             1,
   8149             1,
   8150             1,
   8151             1,
   8152             1,
   8153             1,
   8154             1,
   8155             1,
   8156             1,
   8157             1,
   8158             1,
   8159             1,
   8160             1,
   8161             1,
   8162             1,
   8163             1,
   8164             1,
   8165             1,
   8166             1,
   8167             1,
   8168             1,
   8169             1,
   8170             1,
   8171             1,
   8172             1,
   8173             1,
   8174             1,
   8175             1,
   8176             1,
   8177             1,
   8178             1,
   8179             1,
   8180             1,
   8181             1,
   8182             1,
   8183             1,
   8184             1,
   8185             1,
   8186             1,
   8187             1,
   8188             1,
   8189             1,
   8190             1,
   8191             1,
   8192             1,
   8193             1,
   8194             1,
   8195             1,
   8196             1,
   8197             1,
   8198             1,
   8199         ];
   8200         let pub_key = MlDsaVerKey::<MlDsa65>::decode(&[1u8; 1952].into())
   8201             .to_public_key_der()
   8202             .unwrap();
   8203         let att_obj_len = att_obj.len();
   8204         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
   8205         let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 2033..]);
   8206         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
   8207         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
   8208         // Base case is valid.
   8209         assert!(
   8210             serde_json::from_str::<RegistrationRelaxed>(
   8211                 serde_json::json!({
   8212                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   8213                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   8214                     "response": {
   8215                         "clientDataJSON": b64_cdata_json,
   8216                         "authenticatorData": b64_adata,
   8217                         "transports": [],
   8218                         "publicKey": b64_key,
   8219                         "publicKeyAlgorithm": -49i8,
   8220                         "attestationObject": b64_aobj,
   8221                     },
   8222                     "clientExtensionResults": {},
   8223                     "type": "public-key"
   8224                 })
   8225                 .to_string()
   8226                 .as_str()
   8227             )
   8228             .is_ok_and(
   8229                 |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
   8230                     && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
   8231                     && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
   8232                         == *Sha256::digest(c_data_json.as_bytes())
   8233                     && reg.0.response.transports.is_empty()
   8234                     && matches!(
   8235                         reg.0.authenticator_attachment,
   8236                         AuthenticatorAttachment::None
   8237                     )
   8238                     && reg.0.client_extension_results.cred_props.is_none()
   8239                     && reg.0.client_extension_results.prf.is_none()
   8240             )
   8241         );
   8242         // `publicKeyAlgorithm` mismatch.
   8243         let mut err = Error::invalid_value(
   8244             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
   8245             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa65).as_str()
   8246         )
   8247         .to_string().into_bytes();
   8248         assert_eq!(
   8249             serde_json::from_str::<RegistrationRelaxed>(
   8250                 serde_json::json!({
   8251                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   8252                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   8253                     "response": {
   8254                         "clientDataJSON": b64_cdata_json,
   8255                         "authenticatorData": b64_adata,
   8256                         "transports": [],
   8257                         "publicKey": b64_key,
   8258                         "publicKeyAlgorithm": -8i8,
   8259                         "attestationObject": b64_aobj,
   8260                     },
   8261                     "clientExtensionResults": {},
   8262                     "type": "public-key"
   8263                 })
   8264                 .to_string()
   8265                 .as_str()
   8266             )
   8267             .unwrap_err()
   8268             .to_string()
   8269             .into_bytes()
   8270             .get(..err.len()),
   8271             Some(err.as_slice())
   8272         );
   8273         // Missing `publicKeyAlgorithm`.
   8274         drop(
   8275             serde_json::from_str::<RegistrationRelaxed>(
   8276                 serde_json::json!({
   8277                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   8278                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   8279                     "response": {
   8280                         "clientDataJSON": b64_cdata_json,
   8281                         "authenticatorData": b64_adata,
   8282                         "transports": [],
   8283                         "publicKey": b64_key,
   8284                         "attestationObject": b64_aobj,
   8285                     },
   8286                     "clientExtensionResults": {},
   8287                     "type": "public-key"
   8288                 })
   8289                 .to_string()
   8290                 .as_str(),
   8291             )
   8292             .unwrap(),
   8293         );
   8294         // `null` `publicKeyAlgorithm`.
   8295         drop(
   8296             serde_json::from_str::<RegistrationRelaxed>(
   8297                 serde_json::json!({
   8298                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   8299                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   8300                     "response": {
   8301                         "clientDataJSON": b64_cdata_json,
   8302                         "authenticatorData": b64_adata,
   8303                         "transports": [],
   8304                         "publicKey": b64_key,
   8305                         "publicKeyAlgorithm": null,
   8306                         "attestationObject": b64_aobj,
   8307                     },
   8308                     "clientExtensionResults": {},
   8309                     "type": "public-key"
   8310                 })
   8311                 .to_string()
   8312                 .as_str(),
   8313             )
   8314             .unwrap(),
   8315         );
   8316         // `publicKey` mismatch.
   8317         let bad_pub_key = MlDsaVerKey::<MlDsa65>::decode(&[2; 1952].into());
   8318         err = Error::invalid_value(
   8319             Unexpected::Bytes([0; 32].as_slice()),
   8320             &format!(
   8321                 "DER-encoded public key to match the public key within the attestation object: MlDsa65(MlDsa65PubKey({:?}))",
   8322                 &[1u8; 1952]
   8323             )
   8324             .as_str(),
   8325         )
   8326         .to_string().into_bytes();
   8327         assert_eq!(serde_json::from_str::<RegistrationRelaxed>(
   8328             serde_json::json!({
   8329                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   8330                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   8331                 "response": {
   8332                     "clientDataJSON": b64_cdata_json,
   8333                     "authenticatorData": b64_adata,
   8334                     "transports": [],
   8335                     "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
   8336                     "publicKeyAlgorithm": -49i8,
   8337                     "attestationObject": b64_aobj,
   8338                 },
   8339                 "clientExtensionResults": {},
   8340                 "type": "public-key"
   8341             })
   8342             .to_string()
   8343             .as_str()
   8344             )
   8345             .unwrap_err().to_string().into_bytes().get(..err.len()),
   8346             Some(err.as_slice())
   8347         );
   8348         // Missing `publicKey` is allowed when not using EdDSA, ES256, or RS256.
   8349         assert!(
   8350             serde_json::from_str::<RegistrationRelaxed>(
   8351                 serde_json::json!({
   8352                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   8353                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   8354                     "response": {
   8355                         "clientDataJSON": b64_cdata_json,
   8356                         "authenticatorData": b64_adata,
   8357                         "transports": [],
   8358                         "publicKeyAlgorithm": -49i8,
   8359                         "attestationObject": b64_aobj,
   8360                     },
   8361                     "clientExtensionResults": {},
   8362                     "type": "public-key"
   8363                 })
   8364                 .to_string()
   8365                 .as_str()
   8366             )
   8367             .is_ok()
   8368         );
   8369         // `publicKeyAlgorithm` mismatch when `publicKey` does not exist.
   8370         err = Error::invalid_value(
   8371             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   8372             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa65).as_str()
   8373         )
   8374         .to_string().into_bytes();
   8375         assert_eq!(
   8376             serde_json::from_str::<RegistrationRelaxed>(
   8377                 serde_json::json!({
   8378                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   8379                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   8380                     "response": {
   8381                         "clientDataJSON": b64_cdata_json,
   8382                         "authenticatorData": b64_adata,
   8383                         "transports": [],
   8384                         "publicKeyAlgorithm": -7i8,
   8385                         "attestationObject": b64_aobj,
   8386                     },
   8387                     "clientExtensionResults": {},
   8388                     "type": "public-key"
   8389                 })
   8390                 .to_string()
   8391                 .as_str()
   8392             )
   8393             .unwrap_err()
   8394             .to_string()
   8395             .into_bytes()
   8396             .get(..err.len()),
   8397             Some(err.as_slice())
   8398         );
   8399         // `null` `publicKey` is allowed when not using EdDSA, ES256, or RS256.
   8400         assert!(
   8401             serde_json::from_str::<RegistrationRelaxed>(
   8402                 serde_json::json!({
   8403                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   8404                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   8405                     "response": {
   8406                         "clientDataJSON": b64_cdata_json,
   8407                         "authenticatorData": b64_adata,
   8408                         "transports": [],
   8409                         "publicKey": null,
   8410                         "publicKeyAlgorithm": -49i8,
   8411                         "attestationObject": b64_aobj,
   8412                     },
   8413                     "clientExtensionResults": {},
   8414                     "type": "public-key"
   8415                 })
   8416                 .to_string()
   8417                 .as_str()
   8418             )
   8419             .is_ok()
   8420         );
   8421         // `publicKeyAlgorithm` mismatch when `publicKey` is null.
   8422         err = Error::invalid_value(
   8423             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   8424             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa65).as_str()
   8425         )
   8426         .to_string().into_bytes();
   8427         assert_eq!(
   8428             serde_json::from_str::<RegistrationRelaxed>(
   8429                 serde_json::json!({
   8430                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   8431                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   8432                     "response": {
   8433                         "clientDataJSON": b64_cdata_json,
   8434                         "authenticatorData": b64_adata,
   8435                         "transports": [],
   8436                         "publicKey": null,
   8437                         "publicKeyAlgorithm": -7i8,
   8438                         "attestationObject": b64_aobj,
   8439                     },
   8440                     "clientExtensionResults": {},
   8441                     "type": "public-key"
   8442                 })
   8443                 .to_string()
   8444                 .as_str()
   8445             )
   8446             .unwrap_err()
   8447             .to_string()
   8448             .into_bytes()
   8449             .get(..err.len()),
   8450             Some(err.as_slice())
   8451         );
   8452     }
   8453     #[expect(
   8454         clippy::assertions_on_result_states,
   8455         clippy::unwrap_used,
   8456         reason = "OK in tests"
   8457     )]
   8458     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
   8459     #[expect(clippy::too_many_lines, reason = "a lot to test")]
   8460     #[test]
   8461     fn mldsa44_registration_deserialize_data_mismatch() {
   8462         let c_data_json = serde_json::json!({}).to_string();
   8463         let att_obj: [u8; 1424] = [
   8464             cbor::MAP_3,
   8465             cbor::TEXT_3,
   8466             b'f',
   8467             b'm',
   8468             b't',
   8469             cbor::TEXT_4,
   8470             b'n',
   8471             b'o',
   8472             b'n',
   8473             b'e',
   8474             cbor::TEXT_7,
   8475             b'a',
   8476             b't',
   8477             b't',
   8478             b'S',
   8479             b't',
   8480             b'm',
   8481             b't',
   8482             cbor::MAP_0,
   8483             cbor::TEXT_8,
   8484             b'a',
   8485             b'u',
   8486             b't',
   8487             b'h',
   8488             b'D',
   8489             b'a',
   8490             b't',
   8491             b'a',
   8492             cbor::BYTES_INFO_25,
   8493             5,
   8494             113,
   8495             // `rpIdHash`.
   8496             0,
   8497             0,
   8498             0,
   8499             0,
   8500             0,
   8501             0,
   8502             0,
   8503             0,
   8504             0,
   8505             0,
   8506             0,
   8507             0,
   8508             0,
   8509             0,
   8510             0,
   8511             0,
   8512             0,
   8513             0,
   8514             0,
   8515             0,
   8516             0,
   8517             0,
   8518             0,
   8519             0,
   8520             0,
   8521             0,
   8522             0,
   8523             0,
   8524             0,
   8525             0,
   8526             0,
   8527             0,
   8528             // `flags`.
   8529             0b0100_0101,
   8530             // `signCount`.
   8531             0,
   8532             0,
   8533             0,
   8534             0,
   8535             // `aaguid`.
   8536             0,
   8537             0,
   8538             0,
   8539             0,
   8540             0,
   8541             0,
   8542             0,
   8543             0,
   8544             0,
   8545             0,
   8546             0,
   8547             0,
   8548             0,
   8549             0,
   8550             0,
   8551             0,
   8552             // `credentialIdLength`.
   8553             0,
   8554             16,
   8555             // `credentialId`.
   8556             0,
   8557             0,
   8558             0,
   8559             0,
   8560             0,
   8561             0,
   8562             0,
   8563             0,
   8564             0,
   8565             0,
   8566             0,
   8567             0,
   8568             0,
   8569             0,
   8570             0,
   8571             0,
   8572             // ML-DSA-44 COSE key.
   8573             cbor::MAP_3,
   8574             KTY,
   8575             AKP,
   8576             ALG,
   8577             cbor::NEG_INFO_24,
   8578             MLDSA44,
   8579             // `pub`.
   8580             cbor::NEG_ONE,
   8581             cbor::BYTES_INFO_25,
   8582             5,
   8583             32,
   8584             // Encoded key.
   8585             1,
   8586             1,
   8587             1,
   8588             1,
   8589             1,
   8590             1,
   8591             1,
   8592             1,
   8593             1,
   8594             1,
   8595             1,
   8596             1,
   8597             1,
   8598             1,
   8599             1,
   8600             1,
   8601             1,
   8602             1,
   8603             1,
   8604             1,
   8605             1,
   8606             1,
   8607             1,
   8608             1,
   8609             1,
   8610             1,
   8611             1,
   8612             1,
   8613             1,
   8614             1,
   8615             1,
   8616             1,
   8617             1,
   8618             1,
   8619             1,
   8620             1,
   8621             1,
   8622             1,
   8623             1,
   8624             1,
   8625             1,
   8626             1,
   8627             1,
   8628             1,
   8629             1,
   8630             1,
   8631             1,
   8632             1,
   8633             1,
   8634             1,
   8635             1,
   8636             1,
   8637             1,
   8638             1,
   8639             1,
   8640             1,
   8641             1,
   8642             1,
   8643             1,
   8644             1,
   8645             1,
   8646             1,
   8647             1,
   8648             1,
   8649             1,
   8650             1,
   8651             1,
   8652             1,
   8653             1,
   8654             1,
   8655             1,
   8656             1,
   8657             1,
   8658             1,
   8659             1,
   8660             1,
   8661             1,
   8662             1,
   8663             1,
   8664             1,
   8665             1,
   8666             1,
   8667             1,
   8668             1,
   8669             1,
   8670             1,
   8671             1,
   8672             1,
   8673             1,
   8674             1,
   8675             1,
   8676             1,
   8677             1,
   8678             1,
   8679             1,
   8680             1,
   8681             1,
   8682             1,
   8683             1,
   8684             1,
   8685             1,
   8686             1,
   8687             1,
   8688             1,
   8689             1,
   8690             1,
   8691             1,
   8692             1,
   8693             1,
   8694             1,
   8695             1,
   8696             1,
   8697             1,
   8698             1,
   8699             1,
   8700             1,
   8701             1,
   8702             1,
   8703             1,
   8704             1,
   8705             1,
   8706             1,
   8707             1,
   8708             1,
   8709             1,
   8710             1,
   8711             1,
   8712             1,
   8713             1,
   8714             1,
   8715             1,
   8716             1,
   8717             1,
   8718             1,
   8719             1,
   8720             1,
   8721             1,
   8722             1,
   8723             1,
   8724             1,
   8725             1,
   8726             1,
   8727             1,
   8728             1,
   8729             1,
   8730             1,
   8731             1,
   8732             1,
   8733             1,
   8734             1,
   8735             1,
   8736             1,
   8737             1,
   8738             1,
   8739             1,
   8740             1,
   8741             1,
   8742             1,
   8743             1,
   8744             1,
   8745             1,
   8746             1,
   8747             1,
   8748             1,
   8749             1,
   8750             1,
   8751             1,
   8752             1,
   8753             1,
   8754             1,
   8755             1,
   8756             1,
   8757             1,
   8758             1,
   8759             1,
   8760             1,
   8761             1,
   8762             1,
   8763             1,
   8764             1,
   8765             1,
   8766             1,
   8767             1,
   8768             1,
   8769             1,
   8770             1,
   8771             1,
   8772             1,
   8773             1,
   8774             1,
   8775             1,
   8776             1,
   8777             1,
   8778             1,
   8779             1,
   8780             1,
   8781             1,
   8782             1,
   8783             1,
   8784             1,
   8785             1,
   8786             1,
   8787             1,
   8788             1,
   8789             1,
   8790             1,
   8791             1,
   8792             1,
   8793             1,
   8794             1,
   8795             1,
   8796             1,
   8797             1,
   8798             1,
   8799             1,
   8800             1,
   8801             1,
   8802             1,
   8803             1,
   8804             1,
   8805             1,
   8806             1,
   8807             1,
   8808             1,
   8809             1,
   8810             1,
   8811             1,
   8812             1,
   8813             1,
   8814             1,
   8815             1,
   8816             1,
   8817             1,
   8818             1,
   8819             1,
   8820             1,
   8821             1,
   8822             1,
   8823             1,
   8824             1,
   8825             1,
   8826             1,
   8827             1,
   8828             1,
   8829             1,
   8830             1,
   8831             1,
   8832             1,
   8833             1,
   8834             1,
   8835             1,
   8836             1,
   8837             1,
   8838             1,
   8839             1,
   8840             1,
   8841             1,
   8842             1,
   8843             1,
   8844             1,
   8845             1,
   8846             1,
   8847             1,
   8848             1,
   8849             1,
   8850             1,
   8851             1,
   8852             1,
   8853             1,
   8854             1,
   8855             1,
   8856             1,
   8857             1,
   8858             1,
   8859             1,
   8860             1,
   8861             1,
   8862             1,
   8863             1,
   8864             1,
   8865             1,
   8866             1,
   8867             1,
   8868             1,
   8869             1,
   8870             1,
   8871             1,
   8872             1,
   8873             1,
   8874             1,
   8875             1,
   8876             1,
   8877             1,
   8878             1,
   8879             1,
   8880             1,
   8881             1,
   8882             1,
   8883             1,
   8884             1,
   8885             1,
   8886             1,
   8887             1,
   8888             1,
   8889             1,
   8890             1,
   8891             1,
   8892             1,
   8893             1,
   8894             1,
   8895             1,
   8896             1,
   8897             1,
   8898             1,
   8899             1,
   8900             1,
   8901             1,
   8902             1,
   8903             1,
   8904             1,
   8905             1,
   8906             1,
   8907             1,
   8908             1,
   8909             1,
   8910             1,
   8911             1,
   8912             1,
   8913             1,
   8914             1,
   8915             1,
   8916             1,
   8917             1,
   8918             1,
   8919             1,
   8920             1,
   8921             1,
   8922             1,
   8923             1,
   8924             1,
   8925             1,
   8926             1,
   8927             1,
   8928             1,
   8929             1,
   8930             1,
   8931             1,
   8932             1,
   8933             1,
   8934             1,
   8935             1,
   8936             1,
   8937             1,
   8938             1,
   8939             1,
   8940             1,
   8941             1,
   8942             1,
   8943             1,
   8944             1,
   8945             1,
   8946             1,
   8947             1,
   8948             1,
   8949             1,
   8950             1,
   8951             1,
   8952             1,
   8953             1,
   8954             1,
   8955             1,
   8956             1,
   8957             1,
   8958             1,
   8959             1,
   8960             1,
   8961             1,
   8962             1,
   8963             1,
   8964             1,
   8965             1,
   8966             1,
   8967             1,
   8968             1,
   8969             1,
   8970             1,
   8971             1,
   8972             1,
   8973             1,
   8974             1,
   8975             1,
   8976             1,
   8977             1,
   8978             1,
   8979             1,
   8980             1,
   8981             1,
   8982             1,
   8983             1,
   8984             1,
   8985             1,
   8986             1,
   8987             1,
   8988             1,
   8989             1,
   8990             1,
   8991             1,
   8992             1,
   8993             1,
   8994             1,
   8995             1,
   8996             1,
   8997             1,
   8998             1,
   8999             1,
   9000             1,
   9001             1,
   9002             1,
   9003             1,
   9004             1,
   9005             1,
   9006             1,
   9007             1,
   9008             1,
   9009             1,
   9010             1,
   9011             1,
   9012             1,
   9013             1,
   9014             1,
   9015             1,
   9016             1,
   9017             1,
   9018             1,
   9019             1,
   9020             1,
   9021             1,
   9022             1,
   9023             1,
   9024             1,
   9025             1,
   9026             1,
   9027             1,
   9028             1,
   9029             1,
   9030             1,
   9031             1,
   9032             1,
   9033             1,
   9034             1,
   9035             1,
   9036             1,
   9037             1,
   9038             1,
   9039             1,
   9040             1,
   9041             1,
   9042             1,
   9043             1,
   9044             1,
   9045             1,
   9046             1,
   9047             1,
   9048             1,
   9049             1,
   9050             1,
   9051             1,
   9052             1,
   9053             1,
   9054             1,
   9055             1,
   9056             1,
   9057             1,
   9058             1,
   9059             1,
   9060             1,
   9061             1,
   9062             1,
   9063             1,
   9064             1,
   9065             1,
   9066             1,
   9067             1,
   9068             1,
   9069             1,
   9070             1,
   9071             1,
   9072             1,
   9073             1,
   9074             1,
   9075             1,
   9076             1,
   9077             1,
   9078             1,
   9079             1,
   9080             1,
   9081             1,
   9082             1,
   9083             1,
   9084             1,
   9085             1,
   9086             1,
   9087             1,
   9088             1,
   9089             1,
   9090             1,
   9091             1,
   9092             1,
   9093             1,
   9094             1,
   9095             1,
   9096             1,
   9097             1,
   9098             1,
   9099             1,
   9100             1,
   9101             1,
   9102             1,
   9103             1,
   9104             1,
   9105             1,
   9106             1,
   9107             1,
   9108             1,
   9109             1,
   9110             1,
   9111             1,
   9112             1,
   9113             1,
   9114             1,
   9115             1,
   9116             1,
   9117             1,
   9118             1,
   9119             1,
   9120             1,
   9121             1,
   9122             1,
   9123             1,
   9124             1,
   9125             1,
   9126             1,
   9127             1,
   9128             1,
   9129             1,
   9130             1,
   9131             1,
   9132             1,
   9133             1,
   9134             1,
   9135             1,
   9136             1,
   9137             1,
   9138             1,
   9139             1,
   9140             1,
   9141             1,
   9142             1,
   9143             1,
   9144             1,
   9145             1,
   9146             1,
   9147             1,
   9148             1,
   9149             1,
   9150             1,
   9151             1,
   9152             1,
   9153             1,
   9154             1,
   9155             1,
   9156             1,
   9157             1,
   9158             1,
   9159             1,
   9160             1,
   9161             1,
   9162             1,
   9163             1,
   9164             1,
   9165             1,
   9166             1,
   9167             1,
   9168             1,
   9169             1,
   9170             1,
   9171             1,
   9172             1,
   9173             1,
   9174             1,
   9175             1,
   9176             1,
   9177             1,
   9178             1,
   9179             1,
   9180             1,
   9181             1,
   9182             1,
   9183             1,
   9184             1,
   9185             1,
   9186             1,
   9187             1,
   9188             1,
   9189             1,
   9190             1,
   9191             1,
   9192             1,
   9193             1,
   9194             1,
   9195             1,
   9196             1,
   9197             1,
   9198             1,
   9199             1,
   9200             1,
   9201             1,
   9202             1,
   9203             1,
   9204             1,
   9205             1,
   9206             1,
   9207             1,
   9208             1,
   9209             1,
   9210             1,
   9211             1,
   9212             1,
   9213             1,
   9214             1,
   9215             1,
   9216             1,
   9217             1,
   9218             1,
   9219             1,
   9220             1,
   9221             1,
   9222             1,
   9223             1,
   9224             1,
   9225             1,
   9226             1,
   9227             1,
   9228             1,
   9229             1,
   9230             1,
   9231             1,
   9232             1,
   9233             1,
   9234             1,
   9235             1,
   9236             1,
   9237             1,
   9238             1,
   9239             1,
   9240             1,
   9241             1,
   9242             1,
   9243             1,
   9244             1,
   9245             1,
   9246             1,
   9247             1,
   9248             1,
   9249             1,
   9250             1,
   9251             1,
   9252             1,
   9253             1,
   9254             1,
   9255             1,
   9256             1,
   9257             1,
   9258             1,
   9259             1,
   9260             1,
   9261             1,
   9262             1,
   9263             1,
   9264             1,
   9265             1,
   9266             1,
   9267             1,
   9268             1,
   9269             1,
   9270             1,
   9271             1,
   9272             1,
   9273             1,
   9274             1,
   9275             1,
   9276             1,
   9277             1,
   9278             1,
   9279             1,
   9280             1,
   9281             1,
   9282             1,
   9283             1,
   9284             1,
   9285             1,
   9286             1,
   9287             1,
   9288             1,
   9289             1,
   9290             1,
   9291             1,
   9292             1,
   9293             1,
   9294             1,
   9295             1,
   9296             1,
   9297             1,
   9298             1,
   9299             1,
   9300             1,
   9301             1,
   9302             1,
   9303             1,
   9304             1,
   9305             1,
   9306             1,
   9307             1,
   9308             1,
   9309             1,
   9310             1,
   9311             1,
   9312             1,
   9313             1,
   9314             1,
   9315             1,
   9316             1,
   9317             1,
   9318             1,
   9319             1,
   9320             1,
   9321             1,
   9322             1,
   9323             1,
   9324             1,
   9325             1,
   9326             1,
   9327             1,
   9328             1,
   9329             1,
   9330             1,
   9331             1,
   9332             1,
   9333             1,
   9334             1,
   9335             1,
   9336             1,
   9337             1,
   9338             1,
   9339             1,
   9340             1,
   9341             1,
   9342             1,
   9343             1,
   9344             1,
   9345             1,
   9346             1,
   9347             1,
   9348             1,
   9349             1,
   9350             1,
   9351             1,
   9352             1,
   9353             1,
   9354             1,
   9355             1,
   9356             1,
   9357             1,
   9358             1,
   9359             1,
   9360             1,
   9361             1,
   9362             1,
   9363             1,
   9364             1,
   9365             1,
   9366             1,
   9367             1,
   9368             1,
   9369             1,
   9370             1,
   9371             1,
   9372             1,
   9373             1,
   9374             1,
   9375             1,
   9376             1,
   9377             1,
   9378             1,
   9379             1,
   9380             1,
   9381             1,
   9382             1,
   9383             1,
   9384             1,
   9385             1,
   9386             1,
   9387             1,
   9388             1,
   9389             1,
   9390             1,
   9391             1,
   9392             1,
   9393             1,
   9394             1,
   9395             1,
   9396             1,
   9397             1,
   9398             1,
   9399             1,
   9400             1,
   9401             1,
   9402             1,
   9403             1,
   9404             1,
   9405             1,
   9406             1,
   9407             1,
   9408             1,
   9409             1,
   9410             1,
   9411             1,
   9412             1,
   9413             1,
   9414             1,
   9415             1,
   9416             1,
   9417             1,
   9418             1,
   9419             1,
   9420             1,
   9421             1,
   9422             1,
   9423             1,
   9424             1,
   9425             1,
   9426             1,
   9427             1,
   9428             1,
   9429             1,
   9430             1,
   9431             1,
   9432             1,
   9433             1,
   9434             1,
   9435             1,
   9436             1,
   9437             1,
   9438             1,
   9439             1,
   9440             1,
   9441             1,
   9442             1,
   9443             1,
   9444             1,
   9445             1,
   9446             1,
   9447             1,
   9448             1,
   9449             1,
   9450             1,
   9451             1,
   9452             1,
   9453             1,
   9454             1,
   9455             1,
   9456             1,
   9457             1,
   9458             1,
   9459             1,
   9460             1,
   9461             1,
   9462             1,
   9463             1,
   9464             1,
   9465             1,
   9466             1,
   9467             1,
   9468             1,
   9469             1,
   9470             1,
   9471             1,
   9472             1,
   9473             1,
   9474             1,
   9475             1,
   9476             1,
   9477             1,
   9478             1,
   9479             1,
   9480             1,
   9481             1,
   9482             1,
   9483             1,
   9484             1,
   9485             1,
   9486             1,
   9487             1,
   9488             1,
   9489             1,
   9490             1,
   9491             1,
   9492             1,
   9493             1,
   9494             1,
   9495             1,
   9496             1,
   9497             1,
   9498             1,
   9499             1,
   9500             1,
   9501             1,
   9502             1,
   9503             1,
   9504             1,
   9505             1,
   9506             1,
   9507             1,
   9508             1,
   9509             1,
   9510             1,
   9511             1,
   9512             1,
   9513             1,
   9514             1,
   9515             1,
   9516             1,
   9517             1,
   9518             1,
   9519             1,
   9520             1,
   9521             1,
   9522             1,
   9523             1,
   9524             1,
   9525             1,
   9526             1,
   9527             1,
   9528             1,
   9529             1,
   9530             1,
   9531             1,
   9532             1,
   9533             1,
   9534             1,
   9535             1,
   9536             1,
   9537             1,
   9538             1,
   9539             1,
   9540             1,
   9541             1,
   9542             1,
   9543             1,
   9544             1,
   9545             1,
   9546             1,
   9547             1,
   9548             1,
   9549             1,
   9550             1,
   9551             1,
   9552             1,
   9553             1,
   9554             1,
   9555             1,
   9556             1,
   9557             1,
   9558             1,
   9559             1,
   9560             1,
   9561             1,
   9562             1,
   9563             1,
   9564             1,
   9565             1,
   9566             1,
   9567             1,
   9568             1,
   9569             1,
   9570             1,
   9571             1,
   9572             1,
   9573             1,
   9574             1,
   9575             1,
   9576             1,
   9577             1,
   9578             1,
   9579             1,
   9580             1,
   9581             1,
   9582             1,
   9583             1,
   9584             1,
   9585             1,
   9586             1,
   9587             1,
   9588             1,
   9589             1,
   9590             1,
   9591             1,
   9592             1,
   9593             1,
   9594             1,
   9595             1,
   9596             1,
   9597             1,
   9598             1,
   9599             1,
   9600             1,
   9601             1,
   9602             1,
   9603             1,
   9604             1,
   9605             1,
   9606             1,
   9607             1,
   9608             1,
   9609             1,
   9610             1,
   9611             1,
   9612             1,
   9613             1,
   9614             1,
   9615             1,
   9616             1,
   9617             1,
   9618             1,
   9619             1,
   9620             1,
   9621             1,
   9622             1,
   9623             1,
   9624             1,
   9625             1,
   9626             1,
   9627             1,
   9628             1,
   9629             1,
   9630             1,
   9631             1,
   9632             1,
   9633             1,
   9634             1,
   9635             1,
   9636             1,
   9637             1,
   9638             1,
   9639             1,
   9640             1,
   9641             1,
   9642             1,
   9643             1,
   9644             1,
   9645             1,
   9646             1,
   9647             1,
   9648             1,
   9649             1,
   9650             1,
   9651             1,
   9652             1,
   9653             1,
   9654             1,
   9655             1,
   9656             1,
   9657             1,
   9658             1,
   9659             1,
   9660             1,
   9661             1,
   9662             1,
   9663             1,
   9664             1,
   9665             1,
   9666             1,
   9667             1,
   9668             1,
   9669             1,
   9670             1,
   9671             1,
   9672             1,
   9673             1,
   9674             1,
   9675             1,
   9676             1,
   9677             1,
   9678             1,
   9679             1,
   9680             1,
   9681             1,
   9682             1,
   9683             1,
   9684             1,
   9685             1,
   9686             1,
   9687             1,
   9688             1,
   9689             1,
   9690             1,
   9691             1,
   9692             1,
   9693             1,
   9694             1,
   9695             1,
   9696             1,
   9697             1,
   9698             1,
   9699             1,
   9700             1,
   9701             1,
   9702             1,
   9703             1,
   9704             1,
   9705             1,
   9706             1,
   9707             1,
   9708             1,
   9709             1,
   9710             1,
   9711             1,
   9712             1,
   9713             1,
   9714             1,
   9715             1,
   9716             1,
   9717             1,
   9718             1,
   9719             1,
   9720             1,
   9721             1,
   9722             1,
   9723             1,
   9724             1,
   9725             1,
   9726             1,
   9727             1,
   9728             1,
   9729             1,
   9730             1,
   9731             1,
   9732             1,
   9733             1,
   9734             1,
   9735             1,
   9736             1,
   9737             1,
   9738             1,
   9739             1,
   9740             1,
   9741             1,
   9742             1,
   9743             1,
   9744             1,
   9745             1,
   9746             1,
   9747             1,
   9748             1,
   9749             1,
   9750             1,
   9751             1,
   9752             1,
   9753             1,
   9754             1,
   9755             1,
   9756             1,
   9757             1,
   9758             1,
   9759             1,
   9760             1,
   9761             1,
   9762             1,
   9763             1,
   9764             1,
   9765             1,
   9766             1,
   9767             1,
   9768             1,
   9769             1,
   9770             1,
   9771             1,
   9772             1,
   9773             1,
   9774             1,
   9775             1,
   9776             1,
   9777             1,
   9778             1,
   9779             1,
   9780             1,
   9781             1,
   9782             1,
   9783             1,
   9784             1,
   9785             1,
   9786             1,
   9787             1,
   9788             1,
   9789             1,
   9790             1,
   9791             1,
   9792             1,
   9793             1,
   9794             1,
   9795             1,
   9796             1,
   9797             1,
   9798             1,
   9799             1,
   9800             1,
   9801             1,
   9802             1,
   9803             1,
   9804             1,
   9805             1,
   9806             1,
   9807             1,
   9808             1,
   9809             1,
   9810             1,
   9811             1,
   9812             1,
   9813             1,
   9814             1,
   9815             1,
   9816             1,
   9817             1,
   9818             1,
   9819             1,
   9820             1,
   9821             1,
   9822             1,
   9823             1,
   9824             1,
   9825             1,
   9826             1,
   9827             1,
   9828             1,
   9829             1,
   9830             1,
   9831             1,
   9832             1,
   9833             1,
   9834             1,
   9835             1,
   9836             1,
   9837             1,
   9838             1,
   9839             1,
   9840             1,
   9841             1,
   9842             1,
   9843             1,
   9844             1,
   9845             1,
   9846             1,
   9847             1,
   9848             1,
   9849             1,
   9850             1,
   9851             1,
   9852             1,
   9853             1,
   9854             1,
   9855             1,
   9856             1,
   9857             1,
   9858             1,
   9859             1,
   9860             1,
   9861             1,
   9862             1,
   9863             1,
   9864             1,
   9865             1,
   9866             1,
   9867             1,
   9868             1,
   9869             1,
   9870             1,
   9871             1,
   9872             1,
   9873             1,
   9874             1,
   9875             1,
   9876             1,
   9877             1,
   9878             1,
   9879             1,
   9880             1,
   9881             1,
   9882             1,
   9883             1,
   9884             1,
   9885             1,
   9886             1,
   9887             1,
   9888             1,
   9889             1,
   9890             1,
   9891             1,
   9892             1,
   9893             1,
   9894             1,
   9895             1,
   9896             1,
   9897         ];
   9898         let pub_key = MlDsaVerKey::<MlDsa44>::decode(&[1u8; 1312].into())
   9899             .to_public_key_der()
   9900             .unwrap();
   9901         let att_obj_len = att_obj.len();
   9902         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
   9903         let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 1393..]);
   9904         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
   9905         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
   9906         // Base case is valid.
   9907         assert!(
   9908             serde_json::from_str::<RegistrationRelaxed>(
   9909                 serde_json::json!({
   9910                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9911                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9912                     "response": {
   9913                         "clientDataJSON": b64_cdata_json,
   9914                         "authenticatorData": b64_adata,
   9915                         "transports": [],
   9916                         "publicKey": b64_key,
   9917                         "publicKeyAlgorithm": -48i8,
   9918                         "attestationObject": b64_aobj,
   9919                     },
   9920                     "clientExtensionResults": {},
   9921                     "type": "public-key"
   9922                 })
   9923                 .to_string()
   9924                 .as_str()
   9925             )
   9926             .is_ok_and(
   9927                 |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
   9928                     && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
   9929                     && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
   9930                         == *Sha256::digest(c_data_json.as_bytes())
   9931                     && reg.0.response.transports.is_empty()
   9932                     && matches!(
   9933                         reg.0.authenticator_attachment,
   9934                         AuthenticatorAttachment::None
   9935                     )
   9936                     && reg.0.client_extension_results.cred_props.is_none()
   9937                     && reg.0.client_extension_results.prf.is_none()
   9938             )
   9939         );
   9940         // `publicKeyAlgorithm` mismatch.
   9941         let mut err = Error::invalid_value(
   9942             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
   9943             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa44).as_str()
   9944         )
   9945         .to_string().into_bytes();
   9946         assert_eq!(
   9947             serde_json::from_str::<RegistrationRelaxed>(
   9948                 serde_json::json!({
   9949                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9950                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9951                     "response": {
   9952                         "clientDataJSON": b64_cdata_json,
   9953                         "authenticatorData": b64_adata,
   9954                         "transports": [],
   9955                         "publicKey": b64_key,
   9956                         "publicKeyAlgorithm": -8i8,
   9957                         "attestationObject": b64_aobj,
   9958                     },
   9959                     "clientExtensionResults": {},
   9960                     "type": "public-key"
   9961                 })
   9962                 .to_string()
   9963                 .as_str()
   9964             )
   9965             .unwrap_err()
   9966             .to_string()
   9967             .into_bytes()
   9968             .get(..err.len()),
   9969             Some(err.as_slice())
   9970         );
   9971         // Missing `publicKeyAlgorithm`.
   9972         drop(
   9973             serde_json::from_str::<RegistrationRelaxed>(
   9974                 serde_json::json!({
   9975                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9976                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9977                     "response": {
   9978                         "clientDataJSON": b64_cdata_json,
   9979                         "authenticatorData": b64_adata,
   9980                         "transports": [],
   9981                         "publicKey": b64_key,
   9982                         "attestationObject": b64_aobj,
   9983                     },
   9984                     "clientExtensionResults": {},
   9985                     "type": "public-key"
   9986                 })
   9987                 .to_string()
   9988                 .as_str(),
   9989             )
   9990             .unwrap(),
   9991         );
   9992         // `null` `publicKeyAlgorithm`.
   9993         drop(
   9994             serde_json::from_str::<RegistrationRelaxed>(
   9995                 serde_json::json!({
   9996                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9997                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9998                     "response": {
   9999                         "clientDataJSON": b64_cdata_json,
  10000                         "authenticatorData": b64_adata,
  10001                         "transports": [],
  10002                         "publicKey": b64_key,
  10003                         "publicKeyAlgorithm": null,
  10004                         "attestationObject": b64_aobj,
  10005                     },
  10006                     "clientExtensionResults": {},
  10007                     "type": "public-key"
  10008                 })
  10009                 .to_string()
  10010                 .as_str(),
  10011             )
  10012             .unwrap(),
  10013         );
  10014         // `publicKey` mismatch.
  10015         let bad_pub_key = MlDsaVerKey::<MlDsa44>::decode(&[2; 1312].into());
  10016         err = Error::invalid_value(
  10017             Unexpected::Bytes([0; 32].as_slice()),
  10018             &format!(
  10019                 "DER-encoded public key to match the public key within the attestation object: MlDsa44(MlDsa44PubKey({:?}))",
  10020                 &[1u8; 1312]
  10021             )
  10022             .as_str(),
  10023         )
  10024         .to_string().into_bytes();
  10025         assert_eq!(serde_json::from_str::<RegistrationRelaxed>(
  10026             serde_json::json!({
  10027                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10028                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10029                 "response": {
  10030                     "clientDataJSON": b64_cdata_json,
  10031                     "authenticatorData": b64_adata,
  10032                     "transports": [],
  10033                     "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
  10034                     "publicKeyAlgorithm": -48i8,
  10035                     "attestationObject": b64_aobj,
  10036                 },
  10037                 "clientExtensionResults": {},
  10038                 "type": "public-key"
  10039             })
  10040             .to_string()
  10041             .as_str()
  10042             )
  10043             .unwrap_err().to_string().into_bytes().get(..err.len()),
  10044             Some(err.as_slice())
  10045         );
  10046         // Missing `publicKey` is allowed when not using EdDSA, ES256, or RS256.
  10047         assert!(
  10048             serde_json::from_str::<RegistrationRelaxed>(
  10049                 serde_json::json!({
  10050                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10051                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10052                     "response": {
  10053                         "clientDataJSON": b64_cdata_json,
  10054                         "authenticatorData": b64_adata,
  10055                         "transports": [],
  10056                         "publicKeyAlgorithm": -48i8,
  10057                         "attestationObject": b64_aobj,
  10058                     },
  10059                     "clientExtensionResults": {},
  10060                     "type": "public-key"
  10061                 })
  10062                 .to_string()
  10063                 .as_str()
  10064             )
  10065             .is_ok()
  10066         );
  10067         // `publicKeyAlgorithm` mismatch when `publicKey` does not exist.
  10068         err = Error::invalid_value(
  10069             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
  10070             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa44).as_str()
  10071         )
  10072         .to_string().into_bytes();
  10073         assert_eq!(
  10074             serde_json::from_str::<RegistrationRelaxed>(
  10075                 serde_json::json!({
  10076                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10077                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10078                     "response": {
  10079                         "clientDataJSON": b64_cdata_json,
  10080                         "authenticatorData": b64_adata,
  10081                         "transports": [],
  10082                         "publicKeyAlgorithm": -7i8,
  10083                         "attestationObject": b64_aobj,
  10084                     },
  10085                     "clientExtensionResults": {},
  10086                     "type": "public-key"
  10087                 })
  10088                 .to_string()
  10089                 .as_str()
  10090             )
  10091             .unwrap_err()
  10092             .to_string()
  10093             .into_bytes()
  10094             .get(..err.len()),
  10095             Some(err.as_slice())
  10096         );
  10097         // `null` `publicKey` is allowed when not using EdDSA, ES256, or RS256.
  10098         assert!(
  10099             serde_json::from_str::<RegistrationRelaxed>(
  10100                 serde_json::json!({
  10101                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10102                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10103                     "response": {
  10104                         "clientDataJSON": b64_cdata_json,
  10105                         "authenticatorData": b64_adata,
  10106                         "transports": [],
  10107                         "publicKey": null,
  10108                         "publicKeyAlgorithm": -48i8,
  10109                         "attestationObject": b64_aobj,
  10110                     },
  10111                     "clientExtensionResults": {},
  10112                     "type": "public-key"
  10113                 })
  10114                 .to_string()
  10115                 .as_str()
  10116             )
  10117             .is_ok()
  10118         );
  10119         // `publicKeyAlgorithm` mismatch when `publicKey` is null.
  10120         err = Error::invalid_value(
  10121             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
  10122             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa44).as_str()
  10123         )
  10124         .to_string().into_bytes();
  10125         assert_eq!(
  10126             serde_json::from_str::<RegistrationRelaxed>(
  10127                 serde_json::json!({
  10128                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10129                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10130                     "response": {
  10131                         "clientDataJSON": b64_cdata_json,
  10132                         "authenticatorData": b64_adata,
  10133                         "transports": [],
  10134                         "publicKey": null,
  10135                         "publicKeyAlgorithm": -7i8,
  10136                         "attestationObject": b64_aobj,
  10137                     },
  10138                     "clientExtensionResults": {},
  10139                     "type": "public-key"
  10140                 })
  10141                 .to_string()
  10142                 .as_str()
  10143             )
  10144             .unwrap_err()
  10145             .to_string()
  10146             .into_bytes()
  10147             .get(..err.len()),
  10148             Some(err.as_slice())
  10149         );
  10150     }
  10151     #[expect(clippy::unwrap_used, reason = "OK in tests")]
  10152     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
  10153     #[expect(clippy::too_many_lines, reason = "a lot to test")]
  10154     #[test]
  10155     fn es256_registration_deserialize_data_mismatch() {
  10156         let c_data_json = serde_json::json!({}).to_string();
  10157         let mut att_obj: [u8; 178] = [
  10158             cbor::MAP_3,
  10159             cbor::TEXT_3,
  10160             b'f',
  10161             b'm',
  10162             b't',
  10163             cbor::TEXT_4,
  10164             b'n',
  10165             b'o',
  10166             b'n',
  10167             b'e',
  10168             cbor::TEXT_7,
  10169             b'a',
  10170             b't',
  10171             b't',
  10172             b'S',
  10173             b't',
  10174             b'm',
  10175             b't',
  10176             cbor::MAP_0,
  10177             cbor::TEXT_8,
  10178             b'a',
  10179             b'u',
  10180             b't',
  10181             b'h',
  10182             b'D',
  10183             b'a',
  10184             b't',
  10185             b'a',
  10186             cbor::BYTES_INFO_24,
  10187             148,
  10188             // `rpIdHash`.
  10189             0,
  10190             0,
  10191             0,
  10192             0,
  10193             0,
  10194             0,
  10195             0,
  10196             0,
  10197             0,
  10198             0,
  10199             0,
  10200             0,
  10201             0,
  10202             0,
  10203             0,
  10204             0,
  10205             0,
  10206             0,
  10207             0,
  10208             0,
  10209             0,
  10210             0,
  10211             0,
  10212             0,
  10213             0,
  10214             0,
  10215             0,
  10216             0,
  10217             0,
  10218             0,
  10219             0,
  10220             0,
  10221             // `flags`.
  10222             0b0100_0101,
  10223             // `signCount`.
  10224             0,
  10225             0,
  10226             0,
  10227             0,
  10228             // `aaguid`.
  10229             0,
  10230             0,
  10231             0,
  10232             0,
  10233             0,
  10234             0,
  10235             0,
  10236             0,
  10237             0,
  10238             0,
  10239             0,
  10240             0,
  10241             0,
  10242             0,
  10243             0,
  10244             0,
  10245             // `credentialIdLength`.
  10246             0,
  10247             16,
  10248             // `credentialId`.
  10249             0,
  10250             0,
  10251             0,
  10252             0,
  10253             0,
  10254             0,
  10255             0,
  10256             0,
  10257             0,
  10258             0,
  10259             0,
  10260             0,
  10261             0,
  10262             0,
  10263             0,
  10264             0,
  10265             // P-256 COSE key.
  10266             cbor::MAP_5,
  10267             KTY,
  10268             EC2,
  10269             ALG,
  10270             ES256,
  10271             // `crv`.
  10272             cbor::NEG_ONE,
  10273             // `P-256`.
  10274             cbor::ONE,
  10275             // `x`.
  10276             cbor::NEG_TWO,
  10277             cbor::BYTES_INFO_24,
  10278             32,
  10279             // x-coordinate. This will be overwritten later.
  10280             0,
  10281             0,
  10282             0,
  10283             0,
  10284             0,
  10285             0,
  10286             0,
  10287             0,
  10288             0,
  10289             0,
  10290             0,
  10291             0,
  10292             0,
  10293             0,
  10294             0,
  10295             0,
  10296             0,
  10297             0,
  10298             0,
  10299             0,
  10300             0,
  10301             0,
  10302             0,
  10303             0,
  10304             0,
  10305             0,
  10306             0,
  10307             0,
  10308             0,
  10309             0,
  10310             0,
  10311             0,
  10312             // `y`.
  10313             cbor::NEG_THREE,
  10314             cbor::BYTES_INFO_24,
  10315             32,
  10316             // y-coordinate. This will be overwritten later.
  10317             0,
  10318             0,
  10319             0,
  10320             0,
  10321             0,
  10322             0,
  10323             0,
  10324             0,
  10325             0,
  10326             0,
  10327             0,
  10328             0,
  10329             0,
  10330             0,
  10331             0,
  10332             0,
  10333             0,
  10334             0,
  10335             0,
  10336             0,
  10337             0,
  10338             0,
  10339             0,
  10340             0,
  10341             0,
  10342             0,
  10343             0,
  10344             0,
  10345             0,
  10346             0,
  10347             0,
  10348             0,
  10349         ];
  10350         let key = P256Key::from_bytes(
  10351             &[
  10352                 137, 133, 36, 206, 163, 47, 255, 5, 76, 144, 163, 141, 40, 109, 108, 240, 246, 115,
  10353                 178, 237, 169, 68, 6, 129, 92, 21, 238, 127, 55, 158, 207, 95,
  10354             ]
  10355             .into(),
  10356         )
  10357         .unwrap()
  10358         .public_key();
  10359         let enc_key = key.to_sec1_point(false);
  10360         let pub_key = key.to_public_key_der().unwrap();
  10361         let att_obj_len = att_obj.len();
  10362         let x_start = att_obj_len - 67;
  10363         let y_meta_start = x_start + 32;
  10364         let y_start = y_meta_start + 3;
  10365         att_obj[x_start..y_meta_start].copy_from_slice(enc_key.x().unwrap());
  10366         att_obj[y_start..].copy_from_slice(enc_key.y().unwrap());
  10367         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
  10368         let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 148..]);
  10369         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
  10370         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
  10371         // Base case is valid.
  10372         assert!(
  10373             serde_json::from_str::<RegistrationRelaxed>(
  10374                 serde_json::json!({
  10375                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10376                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10377                     "response": {
  10378                         "clientDataJSON": b64_cdata_json,
  10379                         "authenticatorData": b64_adata,
  10380                         "transports": [],
  10381                         "publicKey": b64_key,
  10382                         "publicKeyAlgorithm": -7i8,
  10383                         "attestationObject": b64_aobj,
  10384                     },
  10385                     "clientExtensionResults": {},
  10386                     "type": "public-key"
  10387                 })
  10388                 .to_string()
  10389                 .as_str()
  10390             )
  10391             .is_ok_and(
  10392                 |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
  10393                     && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
  10394                     && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
  10395                         == *Sha256::digest(c_data_json.as_bytes())
  10396                     && reg.0.response.transports.is_empty()
  10397                     && matches!(
  10398                         reg.0.authenticator_attachment,
  10399                         AuthenticatorAttachment::None
  10400                     )
  10401                     && reg.0.client_extension_results.cred_props.is_none()
  10402                     && reg.0.client_extension_results.prf.is_none()
  10403             )
  10404         );
  10405         // `publicKeyAlgorithm` mismatch.
  10406         let mut err = Error::invalid_value(
  10407             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
  10408             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Es256).as_str()
  10409         )
  10410         .to_string().into_bytes();
  10411         assert_eq!(
  10412             serde_json::from_str::<RegistrationRelaxed>(
  10413                 serde_json::json!({
  10414                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10415                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10416                     "response": {
  10417                         "clientDataJSON": b64_cdata_json,
  10418                         "authenticatorData": b64_adata,
  10419                         "transports": [],
  10420                         "publicKey": b64_key,
  10421                         "publicKeyAlgorithm": -8i8,
  10422                         "attestationObject": b64_aobj,
  10423                     },
  10424                     "clientExtensionResults": {},
  10425                     "type": "public-key"
  10426                 })
  10427                 .to_string()
  10428                 .as_str()
  10429             )
  10430             .unwrap_err()
  10431             .to_string()
  10432             .into_bytes()
  10433             .get(..err.len()),
  10434             Some(err.as_slice())
  10435         );
  10436         // Missing `publicKeyAlgorithm`.
  10437         drop(
  10438             serde_json::from_str::<RegistrationRelaxed>(
  10439                 serde_json::json!({
  10440                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10441                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10442                     "response": {
  10443                         "clientDataJSON": b64_cdata_json,
  10444                         "authenticatorData": b64_adata,
  10445                         "transports": [],
  10446                         "publicKey": b64_key,
  10447                         "attestationObject": b64_aobj,
  10448                     },
  10449                     "clientExtensionResults": {},
  10450                     "type": "public-key"
  10451                 })
  10452                 .to_string()
  10453                 .as_str(),
  10454             )
  10455             .unwrap(),
  10456         );
  10457         // `null` `publicKeyAlgorithm`.
  10458         drop(
  10459             serde_json::from_str::<RegistrationRelaxed>(
  10460                 serde_json::json!({
  10461                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10462                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10463                     "response": {
  10464                         "clientDataJSON": b64_cdata_json,
  10465                         "authenticatorData": b64_adata,
  10466                         "transports": [],
  10467                         "publicKey": b64_key,
  10468                         "publicKeyAlgorithm": null,
  10469                         "attestationObject": b64_aobj,
  10470                     },
  10471                     "clientExtensionResults": {},
  10472                     "type": "public-key"
  10473                 })
  10474                 .to_string()
  10475                 .as_str(),
  10476             )
  10477             .unwrap(),
  10478         );
  10479         // `publicKey` mismatch.
  10480         let bad_pub_key = P256PubKey::from_sec1_point(&P256Pt::from_affine_coordinates(
  10481             &[
  10482                 66, 71, 188, 41, 125, 2, 226, 44, 148, 62, 63, 190, 172, 64, 33, 214, 6, 37, 148,
  10483                 23, 240, 235, 203, 84, 112, 219, 232, 197, 54, 182, 17, 235,
  10484             ]
  10485             .into(),
  10486             &[
  10487                 22, 172, 123, 13, 170, 242, 217, 248, 193, 209, 206, 163, 92, 4, 162, 168, 113, 63,
  10488                 2, 117, 16, 223, 239, 196, 109, 179, 10, 130, 43, 213, 205, 92,
  10489             ]
  10490             .into(),
  10491             false,
  10492         ))
  10493         .unwrap();
  10494         err = Error::invalid_value(
  10495             Unexpected::Bytes([0; 32].as_slice()),
  10496             &format!(
  10497                 "DER-encoded public key to match the public key within the attestation object: P256(UncompressedP256PubKey({:?}, {:?}))",
  10498                 &att_obj[x_start..y_meta_start],
  10499                 &att_obj[y_start..],
  10500             )
  10501             .as_str(),
  10502         )
  10503         .to_string().into_bytes();
  10504         assert_eq!(serde_json::from_str::<RegistrationRelaxed>(
  10505             serde_json::json!({
  10506                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10507                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10508                 "response": {
  10509                     "clientDataJSON": b64_cdata_json,
  10510                     "authenticatorData": b64_adata,
  10511                     "transports": [],
  10512                     "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
  10513                     "publicKeyAlgorithm": -7i8,
  10514                     "attestationObject": b64_aobj,
  10515                 },
  10516                 "clientExtensionResults": {},
  10517                 "type": "public-key"
  10518             })
  10519             .to_string()
  10520             .as_str()
  10521             )
  10522             .unwrap_err().to_string().into_bytes().get(..err.len()),
  10523             Some(err.as_slice())
  10524         );
  10525         // Missing `publicKey`.
  10526         drop(
  10527             serde_json::from_str::<RegistrationRelaxed>(
  10528                 serde_json::json!({
  10529                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10530                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10531                     "response": {
  10532                         "clientDataJSON": b64_cdata_json,
  10533                         "authenticatorData": b64_adata,
  10534                         "transports": [],
  10535                         "publicKeyAlgorithm": -7i8,
  10536                         "attestationObject": b64_aobj,
  10537                     },
  10538                     "clientExtensionResults": {},
  10539                     "type": "public-key"
  10540                 })
  10541                 .to_string()
  10542                 .as_str(),
  10543             )
  10544             .unwrap(),
  10545         );
  10546         // `null` `publicKey`.
  10547         drop(
  10548             serde_json::from_str::<RegistrationRelaxed>(
  10549                 serde_json::json!({
  10550                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10551                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10552                     "response": {
  10553                         "clientDataJSON": b64_cdata_json,
  10554                         "authenticatorData": b64_adata,
  10555                         "transports": [],
  10556                         "publicKey": null,
  10557                         "publicKeyAlgorithm": -7i8,
  10558                         "attestationObject": b64_aobj,
  10559                     },
  10560                     "clientExtensionResults": {},
  10561                     "type": "public-key"
  10562                 })
  10563                 .to_string()
  10564                 .as_str(),
  10565             )
  10566             .unwrap(),
  10567         );
  10568         // Base case is valid.
  10569         assert!(
  10570             serde_json::from_str::<CustomRegistration>(
  10571                 serde_json::json!({
  10572                     "clientDataJSON": b64_cdata_json,
  10573                     "transports": [],
  10574                     "attestationObject": b64_aobj,
  10575                     "clientExtensionResults": {},
  10576                     "type": "public-key"
  10577                 })
  10578                 .to_string()
  10579                 .as_str()
  10580             )
  10581             .is_ok_and(
  10582                 |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
  10583                     && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
  10584                     && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
  10585                         == *Sha256::digest(c_data_json.as_bytes())
  10586                     && reg.0.response.transports.is_empty()
  10587                     && matches!(
  10588                         reg.0.authenticator_attachment,
  10589                         AuthenticatorAttachment::None
  10590                     )
  10591                     && reg.0.client_extension_results.cred_props.is_none()
  10592                     && reg.0.client_extension_results.prf.is_none()
  10593             )
  10594         );
  10595     }
  10596     #[expect(clippy::unwrap_used, reason = "OK in tests")]
  10597     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
  10598     #[expect(clippy::too_many_lines, reason = "a lot to test")]
  10599     #[test]
  10600     fn es384_registration_deserialize_data_mismatch() {
  10601         let c_data_json = serde_json::json!({}).to_string();
  10602         let mut att_obj: [u8; 211] = [
  10603             cbor::MAP_3,
  10604             cbor::TEXT_3,
  10605             b'f',
  10606             b'm',
  10607             b't',
  10608             cbor::TEXT_4,
  10609             b'n',
  10610             b'o',
  10611             b'n',
  10612             b'e',
  10613             cbor::TEXT_7,
  10614             b'a',
  10615             b't',
  10616             b't',
  10617             b'S',
  10618             b't',
  10619             b'm',
  10620             b't',
  10621             cbor::MAP_0,
  10622             cbor::TEXT_8,
  10623             b'a',
  10624             b'u',
  10625             b't',
  10626             b'h',
  10627             b'D',
  10628             b'a',
  10629             b't',
  10630             b'a',
  10631             cbor::BYTES_INFO_24,
  10632             181,
  10633             // `rpIdHash`.
  10634             0,
  10635             0,
  10636             0,
  10637             0,
  10638             0,
  10639             0,
  10640             0,
  10641             0,
  10642             0,
  10643             0,
  10644             0,
  10645             0,
  10646             0,
  10647             0,
  10648             0,
  10649             0,
  10650             0,
  10651             0,
  10652             0,
  10653             0,
  10654             0,
  10655             0,
  10656             0,
  10657             0,
  10658             0,
  10659             0,
  10660             0,
  10661             0,
  10662             0,
  10663             0,
  10664             0,
  10665             0,
  10666             // `flags`.
  10667             0b0100_0101,
  10668             // `signCount`.
  10669             0,
  10670             0,
  10671             0,
  10672             0,
  10673             // `aaguid`.
  10674             0,
  10675             0,
  10676             0,
  10677             0,
  10678             0,
  10679             0,
  10680             0,
  10681             0,
  10682             0,
  10683             0,
  10684             0,
  10685             0,
  10686             0,
  10687             0,
  10688             0,
  10689             0,
  10690             // `credentialIdLength`.
  10691             0,
  10692             16,
  10693             // `credentialId`.
  10694             0,
  10695             0,
  10696             0,
  10697             0,
  10698             0,
  10699             0,
  10700             0,
  10701             0,
  10702             0,
  10703             0,
  10704             0,
  10705             0,
  10706             0,
  10707             0,
  10708             0,
  10709             0,
  10710             // P-384 COSE key.
  10711             cbor::MAP_5,
  10712             KTY,
  10713             EC2,
  10714             ALG,
  10715             cbor::NEG_INFO_24,
  10716             ES384,
  10717             // `crv`.
  10718             cbor::NEG_ONE,
  10719             // `P-384`.
  10720             cbor::TWO,
  10721             // `x`.
  10722             cbor::NEG_TWO,
  10723             cbor::BYTES_INFO_24,
  10724             48,
  10725             // x-coordinate. This will be overwritten later.
  10726             0,
  10727             0,
  10728             0,
  10729             0,
  10730             0,
  10731             0,
  10732             0,
  10733             0,
  10734             0,
  10735             0,
  10736             0,
  10737             0,
  10738             0,
  10739             0,
  10740             0,
  10741             0,
  10742             0,
  10743             0,
  10744             0,
  10745             0,
  10746             0,
  10747             0,
  10748             0,
  10749             0,
  10750             0,
  10751             0,
  10752             0,
  10753             0,
  10754             0,
  10755             0,
  10756             0,
  10757             0,
  10758             0,
  10759             0,
  10760             0,
  10761             0,
  10762             0,
  10763             0,
  10764             0,
  10765             0,
  10766             0,
  10767             0,
  10768             0,
  10769             0,
  10770             0,
  10771             0,
  10772             0,
  10773             0,
  10774             // `y`.
  10775             cbor::NEG_THREE,
  10776             cbor::BYTES_INFO_24,
  10777             48,
  10778             // y-coordinate. This will be overwritten later.
  10779             0,
  10780             0,
  10781             0,
  10782             0,
  10783             0,
  10784             0,
  10785             0,
  10786             0,
  10787             0,
  10788             0,
  10789             0,
  10790             0,
  10791             0,
  10792             0,
  10793             0,
  10794             0,
  10795             0,
  10796             0,
  10797             0,
  10798             0,
  10799             0,
  10800             0,
  10801             0,
  10802             0,
  10803             0,
  10804             0,
  10805             0,
  10806             0,
  10807             0,
  10808             0,
  10809             0,
  10810             0,
  10811             0,
  10812             0,
  10813             0,
  10814             0,
  10815             0,
  10816             0,
  10817             0,
  10818             0,
  10819             0,
  10820             0,
  10821             0,
  10822             0,
  10823             0,
  10824             0,
  10825             0,
  10826             0,
  10827         ];
  10828         let key = P384Key::from_bytes(
  10829             &[
  10830                 158, 99, 156, 49, 190, 211, 85, 167, 28, 2, 80, 57, 31, 22, 17, 38, 85, 78, 232,
  10831                 42, 45, 199, 154, 243, 136, 251, 84, 34, 5, 120, 208, 91, 61, 248, 64, 144, 87, 1,
  10832                 32, 86, 220, 68, 182, 11, 105, 223, 75, 70,
  10833             ]
  10834             .into(),
  10835         )
  10836         .unwrap()
  10837         .public_key();
  10838         let enc_key = key.to_sec1_point(false);
  10839         let pub_key = key.to_public_key_der().unwrap();
  10840         let att_obj_len = att_obj.len();
  10841         let x_start = att_obj_len - 99;
  10842         let y_meta_start = x_start + 48;
  10843         let y_start = y_meta_start + 3;
  10844         att_obj[x_start..y_meta_start].copy_from_slice(enc_key.x().unwrap());
  10845         att_obj[y_start..].copy_from_slice(enc_key.y().unwrap());
  10846         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
  10847         let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 181..]);
  10848         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
  10849         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
  10850         // Base case is valid.
  10851         assert!(
  10852             serde_json::from_str::<RegistrationRelaxed>(
  10853                 serde_json::json!({
  10854                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10855                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10856                     "response": {
  10857                         "clientDataJSON": b64_cdata_json,
  10858                         "authenticatorData": b64_adata,
  10859                         "transports": [],
  10860                         "publicKey": b64_key,
  10861                         "publicKeyAlgorithm": -35i8,
  10862                         "attestationObject": b64_aobj,
  10863                     },
  10864                     "clientExtensionResults": {},
  10865                     "type": "public-key"
  10866                 })
  10867                 .to_string()
  10868                 .as_str()
  10869             )
  10870             .is_ok_and(
  10871                 |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
  10872                     && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
  10873                     && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
  10874                         == *Sha256::digest(c_data_json.as_bytes())
  10875                     && reg.0.response.transports.is_empty()
  10876                     && matches!(
  10877                         reg.0.authenticator_attachment,
  10878                         AuthenticatorAttachment::None
  10879                     )
  10880                     && reg.0.client_extension_results.cred_props.is_none()
  10881                     && reg.0.client_extension_results.prf.is_none()
  10882             )
  10883         );
  10884         // `publicKeyAlgorithm` mismatch.
  10885         let mut err = Error::invalid_value(
  10886             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
  10887             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Es384).as_str()
  10888         )
  10889         .to_string().into_bytes();
  10890         assert_eq!(
  10891             serde_json::from_str::<RegistrationRelaxed>(
  10892                 serde_json::json!({
  10893                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10894                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10895                     "response": {
  10896                         "clientDataJSON": b64_cdata_json,
  10897                         "authenticatorData": b64_adata,
  10898                         "transports": [],
  10899                         "publicKey": b64_key,
  10900                         "publicKeyAlgorithm": -7i8,
  10901                         "attestationObject": b64_aobj,
  10902                     },
  10903                     "clientExtensionResults": {},
  10904                     "type": "public-key"
  10905                 })
  10906                 .to_string()
  10907                 .as_str()
  10908             )
  10909             .unwrap_err()
  10910             .to_string()
  10911             .into_bytes()
  10912             .get(..err.len()),
  10913             Some(err.as_slice())
  10914         );
  10915         // Missing `publicKeyAlgorithm`.
  10916         drop(
  10917             serde_json::from_str::<RegistrationRelaxed>(
  10918                 serde_json::json!({
  10919                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10920                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10921                     "response": {
  10922                         "clientDataJSON": b64_cdata_json,
  10923                         "authenticatorData": b64_adata,
  10924                         "transports": [],
  10925                         "publicKey": b64_key,
  10926                         "attestationObject": b64_aobj,
  10927                     },
  10928                     "clientExtensionResults": {},
  10929                     "type": "public-key"
  10930                 })
  10931                 .to_string()
  10932                 .as_str(),
  10933             )
  10934             .unwrap(),
  10935         );
  10936         // `null` `publicKeyAlgorithm`.
  10937         drop(
  10938             serde_json::from_str::<RegistrationRelaxed>(
  10939                 serde_json::json!({
  10940                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10941                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10942                     "response": {
  10943                         "clientDataJSON": b64_cdata_json,
  10944                         "authenticatorData": b64_adata,
  10945                         "transports": [],
  10946                         "publicKey": b64_key,
  10947                         "publicKeyAlgorithm": null,
  10948                         "attestationObject": b64_aobj,
  10949                     },
  10950                     "clientExtensionResults": {},
  10951                     "type": "public-key"
  10952                 })
  10953                 .to_string()
  10954                 .as_str(),
  10955             )
  10956             .unwrap(),
  10957         );
  10958         // `publicKey` mismatch.
  10959         let bad_pub_key = P384PubKey::from_sec1_point(&P384Pt::from_affine_coordinates(
  10960             &[
  10961                 192, 10, 27, 46, 66, 67, 80, 98, 33, 230, 156, 95, 1, 135, 150, 110, 64, 243, 22,
  10962                 118, 5, 255, 107, 44, 234, 111, 217, 105, 125, 114, 39, 7, 126, 2, 191, 111, 48,
  10963                 93, 234, 175, 18, 172, 59, 28, 97, 106, 178, 152,
  10964             ]
  10965             .into(),
  10966             &[
  10967                 57, 36, 196, 12, 109, 129, 253, 115, 88, 154, 6, 43, 195, 85, 169, 5, 230, 51, 28,
  10968                 205, 142, 28, 150, 35, 24, 222, 170, 253, 14, 248, 84, 151, 109, 191, 152, 111,
  10969                 222, 70, 134, 247, 109, 171, 211, 33, 214, 217, 200, 111,
  10970             ]
  10971             .into(),
  10972             false,
  10973         ))
  10974         .unwrap();
  10975         err = Error::invalid_value(
  10976             Unexpected::Bytes([0; 32].as_slice()),
  10977             &format!(
  10978                 "DER-encoded public key to match the public key within the attestation object: P384(UncompressedP384PubKey({:?}, {:?}))",
  10979                 &att_obj[x_start..y_meta_start],
  10980                 &att_obj[y_start..],
  10981             )
  10982             .as_str(),
  10983         )
  10984         .to_string().into_bytes();
  10985         assert_eq!(serde_json::from_str::<RegistrationRelaxed>(
  10986             serde_json::json!({
  10987                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10988                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10989                 "response": {
  10990                     "clientDataJSON": b64_cdata_json,
  10991                     "authenticatorData": b64_adata,
  10992                     "transports": [],
  10993                     "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
  10994                     "publicKeyAlgorithm": -35i8,
  10995                     "attestationObject": b64_aobj,
  10996                 },
  10997                 "clientExtensionResults": {},
  10998                 "type": "public-key"
  10999             }).to_string().as_str()
  11000         ).unwrap_err().to_string().into_bytes().get(..err.len()), Some(err.as_slice()));
  11001         // Missing `publicKey`.
  11002         drop(
  11003             serde_json::from_str::<RegistrationRelaxed>(
  11004                 serde_json::json!({
  11005                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11006                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11007                     "response": {
  11008                         "clientDataJSON": b64_cdata_json,
  11009                         "authenticatorData": b64_adata,
  11010                         "transports": [],
  11011                         "publicKeyAlgorithm": -35i8,
  11012                         "attestationObject": b64_aobj,
  11013                     },
  11014                     "clientExtensionResults": {},
  11015                     "type": "public-key"
  11016                 })
  11017                 .to_string()
  11018                 .as_str(),
  11019             )
  11020             .unwrap(),
  11021         );
  11022         // `publicKeyAlgorithm` mismatch when `publicKey` does not exist.
  11023         err = Error::invalid_value(
  11024             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
  11025             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Es384).as_str()
  11026         )
  11027         .to_string().into_bytes();
  11028         assert_eq!(
  11029             serde_json::from_str::<RegistrationRelaxed>(
  11030                 serde_json::json!({
  11031                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11032                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11033                     "response": {
  11034                         "clientDataJSON": b64_cdata_json,
  11035                         "authenticatorData": b64_adata,
  11036                         "transports": [],
  11037                         "publicKeyAlgorithm": -8i8,
  11038                         "attestationObject": b64_aobj,
  11039                     },
  11040                     "clientExtensionResults": {},
  11041                     "type": "public-key"
  11042                 })
  11043                 .to_string()
  11044                 .as_str()
  11045             )
  11046             .unwrap_err()
  11047             .to_string()
  11048             .into_bytes()
  11049             .get(..err.len()),
  11050             Some(err.as_slice())
  11051         );
  11052         // `null` `publicKey`.
  11053         drop(
  11054             serde_json::from_str::<RegistrationRelaxed>(
  11055                 serde_json::json!({
  11056                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11057                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11058                     "response": {
  11059                         "clientDataJSON": b64_cdata_json,
  11060                         "authenticatorData": b64_adata,
  11061                         "transports": [],
  11062                         "publicKey": null,
  11063                         "publicKeyAlgorithm": -35i8,
  11064                         "attestationObject": b64_aobj,
  11065                     },
  11066                     "clientExtensionResults": {},
  11067                     "type": "public-key"
  11068                 })
  11069                 .to_string()
  11070                 .as_str(),
  11071             )
  11072             .unwrap(),
  11073         );
  11074         // `publicKeyAlgorithm` mismatch when `publicKey` is null.
  11075         err = Error::invalid_value(
  11076             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
  11077             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Es384).as_str()
  11078         )
  11079         .to_string().into_bytes();
  11080         assert_eq!(
  11081             serde_json::from_str::<RegistrationRelaxed>(
  11082                 serde_json::json!({
  11083                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11084                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11085                     "response": {
  11086                         "clientDataJSON": b64_cdata_json,
  11087                         "authenticatorData": b64_adata,
  11088                         "transports": [],
  11089                         "publicKey": null,
  11090                         "publicKeyAlgorithm": -8i8,
  11091                         "attestationObject": b64_aobj,
  11092                     },
  11093                     "clientExtensionResults": {},
  11094                     "type": "public-key"
  11095                 })
  11096                 .to_string()
  11097                 .as_str()
  11098             )
  11099             .unwrap_err()
  11100             .to_string()
  11101             .into_bytes()
  11102             .get(..err.len()),
  11103             Some(err.as_slice())
  11104         );
  11105         // Base case is valid.
  11106         assert!(
  11107             serde_json::from_str::<CustomRegistration>(
  11108                 serde_json::json!({
  11109                     "clientDataJSON": b64_cdata_json,
  11110                     "transports": [],
  11111                     "attestationObject": b64_aobj,
  11112                     "clientExtensionResults": {},
  11113                     "type": "public-key"
  11114                 })
  11115                 .to_string()
  11116                 .as_str()
  11117             )
  11118             .is_ok_and(
  11119                 |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
  11120                     && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
  11121                     && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
  11122                         == *Sha256::digest(c_data_json.as_bytes())
  11123                     && reg.0.response.transports.is_empty()
  11124                     && matches!(
  11125                         reg.0.authenticator_attachment,
  11126                         AuthenticatorAttachment::None
  11127                     )
  11128                     && reg.0.client_extension_results.cred_props.is_none()
  11129                     && reg.0.client_extension_results.prf.is_none()
  11130             )
  11131         );
  11132     }
  11133     #[expect(clippy::unwrap_used, reason = "OK in tests")]
  11134     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
  11135     #[expect(clippy::too_many_lines, reason = "a lot to test")]
  11136     #[test]
  11137     fn rs256_registration_deserialize_data_mismatch() {
  11138         let c_data_json = serde_json::json!({}).to_string();
  11139         let mut att_obj: [u8; 374] = [
  11140             cbor::MAP_3,
  11141             cbor::TEXT_3,
  11142             b'f',
  11143             b'm',
  11144             b't',
  11145             cbor::TEXT_4,
  11146             b'n',
  11147             b'o',
  11148             b'n',
  11149             b'e',
  11150             cbor::TEXT_7,
  11151             b'a',
  11152             b't',
  11153             b't',
  11154             b'S',
  11155             b't',
  11156             b'm',
  11157             b't',
  11158             cbor::MAP_0,
  11159             cbor::TEXT_8,
  11160             b'a',
  11161             b'u',
  11162             b't',
  11163             b'h',
  11164             b'D',
  11165             b'a',
  11166             b't',
  11167             b'a',
  11168             cbor::BYTES_INFO_25,
  11169             1,
  11170             87,
  11171             // `rpIdHash`.
  11172             0,
  11173             0,
  11174             0,
  11175             0,
  11176             0,
  11177             0,
  11178             0,
  11179             0,
  11180             0,
  11181             0,
  11182             0,
  11183             0,
  11184             0,
  11185             0,
  11186             0,
  11187             0,
  11188             0,
  11189             0,
  11190             0,
  11191             0,
  11192             0,
  11193             0,
  11194             0,
  11195             0,
  11196             0,
  11197             0,
  11198             0,
  11199             0,
  11200             0,
  11201             0,
  11202             0,
  11203             0,
  11204             // `flags`.
  11205             0b0100_0101,
  11206             // `signCount`.
  11207             0,
  11208             0,
  11209             0,
  11210             0,
  11211             // `aaguid`.
  11212             0,
  11213             0,
  11214             0,
  11215             0,
  11216             0,
  11217             0,
  11218             0,
  11219             0,
  11220             0,
  11221             0,
  11222             0,
  11223             0,
  11224             0,
  11225             0,
  11226             0,
  11227             0,
  11228             // `credentialIdLength`.
  11229             0,
  11230             16,
  11231             // `credentialId`.
  11232             0,
  11233             0,
  11234             0,
  11235             0,
  11236             0,
  11237             0,
  11238             0,
  11239             0,
  11240             0,
  11241             0,
  11242             0,
  11243             0,
  11244             0,
  11245             0,
  11246             0,
  11247             0,
  11248             // RSA COSE key.
  11249             cbor::MAP_4,
  11250             KTY,
  11251             RSA,
  11252             ALG,
  11253             cbor::NEG_INFO_25,
  11254             // RS256.
  11255             1,
  11256             0,
  11257             // `n`.
  11258             cbor::NEG_ONE,
  11259             cbor::BYTES_INFO_25,
  11260             1,
  11261             0,
  11262             // n. This will be overwritten later.
  11263             0,
  11264             0,
  11265             0,
  11266             0,
  11267             0,
  11268             0,
  11269             0,
  11270             0,
  11271             0,
  11272             0,
  11273             0,
  11274             0,
  11275             0,
  11276             0,
  11277             0,
  11278             0,
  11279             0,
  11280             0,
  11281             0,
  11282             0,
  11283             0,
  11284             0,
  11285             0,
  11286             0,
  11287             0,
  11288             0,
  11289             0,
  11290             0,
  11291             0,
  11292             0,
  11293             0,
  11294             0,
  11295             0,
  11296             0,
  11297             0,
  11298             0,
  11299             0,
  11300             0,
  11301             0,
  11302             0,
  11303             0,
  11304             0,
  11305             0,
  11306             0,
  11307             0,
  11308             0,
  11309             0,
  11310             0,
  11311             0,
  11312             0,
  11313             0,
  11314             0,
  11315             0,
  11316             0,
  11317             0,
  11318             0,
  11319             0,
  11320             0,
  11321             0,
  11322             0,
  11323             0,
  11324             0,
  11325             0,
  11326             0,
  11327             0,
  11328             0,
  11329             0,
  11330             0,
  11331             0,
  11332             0,
  11333             0,
  11334             0,
  11335             0,
  11336             0,
  11337             0,
  11338             0,
  11339             0,
  11340             0,
  11341             0,
  11342             0,
  11343             0,
  11344             0,
  11345             0,
  11346             0,
  11347             0,
  11348             0,
  11349             0,
  11350             0,
  11351             0,
  11352             0,
  11353             0,
  11354             0,
  11355             0,
  11356             0,
  11357             0,
  11358             0,
  11359             0,
  11360             0,
  11361             0,
  11362             0,
  11363             0,
  11364             0,
  11365             0,
  11366             0,
  11367             0,
  11368             0,
  11369             0,
  11370             0,
  11371             0,
  11372             0,
  11373             0,
  11374             0,
  11375             0,
  11376             0,
  11377             0,
  11378             0,
  11379             0,
  11380             0,
  11381             0,
  11382             0,
  11383             0,
  11384             0,
  11385             0,
  11386             0,
  11387             0,
  11388             0,
  11389             0,
  11390             0,
  11391             0,
  11392             0,
  11393             0,
  11394             0,
  11395             0,
  11396             0,
  11397             0,
  11398             0,
  11399             0,
  11400             0,
  11401             0,
  11402             0,
  11403             0,
  11404             0,
  11405             0,
  11406             0,
  11407             0,
  11408             0,
  11409             0,
  11410             0,
  11411             0,
  11412             0,
  11413             0,
  11414             0,
  11415             0,
  11416             0,
  11417             0,
  11418             0,
  11419             0,
  11420             0,
  11421             0,
  11422             0,
  11423             0,
  11424             0,
  11425             0,
  11426             0,
  11427             0,
  11428             0,
  11429             0,
  11430             0,
  11431             0,
  11432             0,
  11433             0,
  11434             0,
  11435             0,
  11436             0,
  11437             0,
  11438             0,
  11439             0,
  11440             0,
  11441             0,
  11442             0,
  11443             0,
  11444             0,
  11445             0,
  11446             0,
  11447             0,
  11448             0,
  11449             0,
  11450             0,
  11451             0,
  11452             0,
  11453             0,
  11454             0,
  11455             0,
  11456             0,
  11457             0,
  11458             0,
  11459             0,
  11460             0,
  11461             0,
  11462             0,
  11463             0,
  11464             0,
  11465             0,
  11466             0,
  11467             0,
  11468             0,
  11469             0,
  11470             0,
  11471             0,
  11472             0,
  11473             0,
  11474             0,
  11475             0,
  11476             0,
  11477             0,
  11478             0,
  11479             0,
  11480             0,
  11481             0,
  11482             0,
  11483             0,
  11484             0,
  11485             0,
  11486             0,
  11487             0,
  11488             0,
  11489             0,
  11490             0,
  11491             0,
  11492             0,
  11493             0,
  11494             0,
  11495             0,
  11496             0,
  11497             0,
  11498             0,
  11499             0,
  11500             0,
  11501             0,
  11502             0,
  11503             0,
  11504             0,
  11505             0,
  11506             0,
  11507             0,
  11508             0,
  11509             0,
  11510             0,
  11511             0,
  11512             0,
  11513             0,
  11514             0,
  11515             0,
  11516             0,
  11517             0,
  11518             0,
  11519             // `e`.
  11520             cbor::NEG_TWO,
  11521             cbor::BYTES | 3,
  11522             // e.
  11523             1,
  11524             0,
  11525             1,
  11526         ];
  11527         let n = [
  11528             111, 183, 124, 133, 38, 167, 70, 148, 44, 50, 30, 60, 121, 14, 38, 37, 96, 114, 107,
  11529             195, 248, 64, 79, 36, 237, 140, 43, 27, 94, 74, 102, 152, 135, 102, 184, 150, 186, 206,
  11530             185, 19, 165, 209, 48, 98, 98, 9, 3, 205, 208, 82, 250, 105, 132, 201, 73, 62, 60, 165,
  11531             100, 128, 153, 9, 41, 118, 66, 95, 236, 214, 73, 135, 197, 68, 184, 10, 27, 116, 204,
  11532             145, 50, 174, 58, 42, 183, 181, 119, 232, 126, 252, 217, 96, 162, 190, 103, 122, 64,
  11533             87, 145, 45, 32, 207, 17, 239, 223, 3, 35, 14, 112, 119, 124, 141, 123, 208, 239, 105,
  11534             81, 217, 151, 162, 190, 17, 88, 182, 176, 158, 81, 200, 42, 166, 133, 48, 23, 236, 55,
  11535             117, 248, 233, 151, 203, 122, 155, 231, 46, 177, 20, 20, 151, 64, 222, 239, 226, 7, 21,
  11536             254, 81, 202, 64, 232, 161, 235, 22, 51, 246, 207, 213, 0, 229, 138, 46, 222, 205, 157,
  11537             108, 139, 253, 230, 80, 50, 2, 122, 212, 163, 100, 180, 114, 12, 113, 52, 56, 99, 188,
  11538             42, 198, 212, 23, 182, 222, 56, 221, 200, 79, 96, 239, 221, 135, 10, 17, 106, 183, 56,
  11539             104, 68, 94, 198, 196, 35, 200, 83, 204, 26, 185, 204, 212, 31, 183, 19, 111, 233, 13,
  11540             72, 93, 53, 65, 111, 59, 242, 122, 160, 244, 162, 126, 38, 235, 156, 47, 88, 39, 132,
  11541             153, 79, 0, 133, 78, 7, 218, 165, 241,
  11542         ];
  11543         let e = 0x0001_0001u32;
  11544         let d = [
  11545             145, 79, 21, 97, 233, 3, 192, 194, 177, 68, 181, 80, 120, 197, 23, 44, 185, 74, 144, 0,
  11546             132, 149, 139, 11, 16, 224, 4, 112, 236, 94, 238, 97, 121, 124, 213, 145, 24, 253, 168,
  11547             35, 190, 205, 132, 115, 33, 201, 38, 253, 246, 180, 66, 155, 165, 46, 3, 254, 68, 108,
  11548             154, 247, 246, 45, 187, 0, 204, 96, 185, 157, 249, 174, 158, 38, 62, 244, 183, 76, 102,
  11549             6, 219, 92, 212, 138, 59, 147, 163, 219, 111, 39, 105, 21, 236, 196, 38, 255, 114, 247,
  11550             82, 104, 113, 204, 29, 152, 209, 219, 48, 239, 74, 129, 19, 247, 33, 239, 119, 166,
  11551             216, 152, 94, 138, 238, 164, 242, 129, 50, 150, 57, 20, 53, 224, 56, 241, 138, 97, 111,
  11552             215, 107, 212, 195, 146, 108, 143, 0, 229, 181, 171, 73, 152, 105, 146, 25, 243, 242,
  11553             140, 252, 248, 162, 247, 63, 168, 180, 20, 153, 120, 10, 248, 211, 1, 71, 127, 212,
  11554             249, 237, 203, 202, 48, 26, 216, 226, 228, 186, 13, 204, 70, 255, 240, 89, 255, 59, 83,
  11555             31, 253, 55, 43, 158, 90, 248, 83, 32, 159, 105, 57, 134, 34, 96, 18, 255, 245, 153,
  11556             162, 60, 91, 99, 220, 51, 44, 85, 114, 67, 125, 202, 65, 217, 245, 40, 8, 81, 165, 142,
  11557             24, 245, 127, 122, 247, 152, 212, 75, 45, 59, 90, 184, 234, 31, 147, 36, 8, 212, 45,
  11558             50, 23, 3, 25, 253, 87, 227, 79, 119, 161,
  11559         ];
  11560         let p = BoxedUint::from_le_slice_vartime(
  11561             [
  11562                 215, 166, 5, 21, 11, 179, 41, 77, 198, 92, 165, 48, 77, 162, 42, 41, 206, 141, 60,
  11563                 69, 47, 164, 19, 92, 46, 72, 100, 238, 100, 53, 214, 197, 163, 185, 6, 140, 229,
  11564                 250, 195, 77, 8, 12, 5, 236, 178, 173, 86, 201, 43, 213, 165, 51, 108, 101, 161,
  11565                 99, 76, 240, 14, 234, 76, 197, 137, 53, 198, 168, 135, 205, 212, 198, 120, 29, 16,
  11566                 82, 98, 233, 236, 177, 12, 171, 141, 100, 107, 146, 33, 176, 125, 202, 172, 79,
  11567                 147, 179, 30, 62, 247, 206, 169, 19, 168, 114, 26, 73, 108, 178, 105, 84, 89, 191,
  11568                 168, 253, 228, 214, 54, 16, 212, 199, 111, 72, 3, 41, 247, 227, 165, 244, 32, 188,
  11569                 24, 247,
  11570             ]
  11571             .as_slice(),
  11572         );
  11573         let p_2 = BoxedUint::from_le_slice_vartime(
  11574             [
  11575                 41, 25, 198, 240, 134, 206, 121, 57, 11, 5, 134, 192, 212, 77, 229, 197, 14, 78,
  11576                 85, 212, 190, 114, 179, 188, 21, 171, 174, 12, 104, 74, 15, 164, 136, 173, 62, 177,
  11577                 141, 213, 93, 102, 147, 83, 59, 124, 146, 59, 175, 213, 55, 27, 25, 248, 154, 29,
  11578                 39, 85, 50, 235, 134, 60, 203, 106, 186, 195, 190, 185, 71, 169, 142, 236, 92, 11,
  11579                 250, 187, 198, 8, 201, 184, 120, 178, 227, 87, 63, 243, 89, 227, 234, 184, 28, 252,
  11580                 112, 211, 193, 69, 23, 92, 5, 72, 93, 53, 69, 159, 73, 160, 105, 244, 249, 94, 214,
  11581                 173, 9, 236, 4, 255, 129, 11, 224, 140, 252, 168, 57, 143, 176, 241, 60, 219, 90,
  11582                 250,
  11583             ]
  11584             .as_slice(),
  11585         );
  11586         let key = RsaPrivateKey::from_components(
  11587             BoxedUint::from_le_slice_vartime(n.as_slice()),
  11588             e.into(),
  11589             BoxedUint::from_le_slice_vartime(d.as_slice()),
  11590             vec![p, p_2],
  11591         )
  11592         .unwrap()
  11593         .to_public_key();
  11594         let pub_key = key.to_public_key_der().unwrap();
  11595         let att_obj_len = att_obj.len();
  11596         let n_start = att_obj_len - 261;
  11597         let e_start = n_start + 256;
  11598         att_obj[n_start..e_start].copy_from_slice(key.n().to_be_bytes().as_ref());
  11599         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
  11600         let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 343..]);
  11601         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
  11602         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
  11603         // Base case is valid.
  11604         assert!(
  11605             serde_json::from_str::<RegistrationRelaxed>(
  11606                 serde_json::json!({
  11607                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11608                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11609                     "response": {
  11610                         "clientDataJSON": b64_cdata_json,
  11611                         "authenticatorData": b64_adata,
  11612                         "transports": [],
  11613                         "publicKey": b64_key,
  11614                         "publicKeyAlgorithm": -257i16,
  11615                         "attestationObject": b64_aobj,
  11616                     },
  11617                     "clientExtensionResults": {},
  11618                     "type": "public-key"
  11619                 })
  11620                 .to_string()
  11621                 .as_str()
  11622             )
  11623             .is_ok_and(
  11624                 |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
  11625                     && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
  11626                     && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
  11627                         == *Sha256::digest(c_data_json.as_bytes())
  11628                     && reg.0.response.transports.is_empty()
  11629                     && matches!(
  11630                         reg.0.authenticator_attachment,
  11631                         AuthenticatorAttachment::None
  11632                     )
  11633                     && reg.0.client_extension_results.cred_props.is_none()
  11634                     && reg.0.client_extension_results.prf.is_none()
  11635             )
  11636         );
  11637         // `publicKeyAlgorithm` mismatch.
  11638         let mut err = Error::invalid_value(
  11639             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
  11640             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Rs256).as_str()
  11641         )
  11642         .to_string().into_bytes();
  11643         assert_eq!(
  11644             serde_json::from_str::<RegistrationRelaxed>(
  11645                 serde_json::json!({
  11646                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11647                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11648                     "response": {
  11649                         "clientDataJSON": b64_cdata_json,
  11650                         "authenticatorData": b64_adata,
  11651                         "transports": [],
  11652                         "publicKey": b64_key,
  11653                         "publicKeyAlgorithm": -8i8,
  11654                         "attestationObject": b64_aobj,
  11655                     },
  11656                     "clientExtensionResults": {},
  11657                     "type": "public-key"
  11658                 })
  11659                 .to_string()
  11660                 .as_str()
  11661             )
  11662             .unwrap_err()
  11663             .to_string()
  11664             .into_bytes()
  11665             .get(..err.len()),
  11666             Some(err.as_slice())
  11667         );
  11668         // Missing `publicKeyAlgorithm`.
  11669         drop(
  11670             serde_json::from_str::<RegistrationRelaxed>(
  11671                 serde_json::json!({
  11672                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11673                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11674                     "response": {
  11675                         "clientDataJSON": b64_cdata_json,
  11676                         "authenticatorData": b64_adata,
  11677                         "transports": [],
  11678                         "publicKey": b64_key,
  11679                         "attestationObject": b64_aobj,
  11680                     },
  11681                     "clientExtensionResults": {},
  11682                     "type": "public-key"
  11683                 })
  11684                 .to_string()
  11685                 .as_str(),
  11686             )
  11687             .unwrap(),
  11688         );
  11689         // `null` `publicKeyAlgorithm`.
  11690         drop(
  11691             serde_json::from_str::<RegistrationRelaxed>(
  11692                 serde_json::json!({
  11693                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11694                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11695                     "response": {
  11696                         "clientDataJSON": b64_cdata_json,
  11697                         "authenticatorData": b64_adata,
  11698                         "transports": [],
  11699                         "publicKey": b64_key,
  11700                         "publicKeyAlgorithm": null,
  11701                         "attestationObject": b64_aobj,
  11702                     },
  11703                     "clientExtensionResults": {},
  11704                     "type": "public-key"
  11705                 })
  11706                 .to_string()
  11707                 .as_str(),
  11708             )
  11709             .unwrap(),
  11710         );
  11711         // `publicKey` mismatch.
  11712         let bad_pub_key = RsaPrivateKey::from_components(
  11713             BoxedUint::from_le_slice_vartime(
  11714                 [
  11715                     175, 161, 161, 75, 52, 244, 72, 168, 29, 119, 33, 120, 3, 222, 231, 152, 222,
  11716                     119, 112, 83, 221, 237, 74, 174, 79, 216, 147, 251, 245, 94, 234, 114, 254, 21,
  11717                     17, 254, 8, 115, 75, 127, 150, 87, 59, 109, 230, 116, 85, 90, 11, 160, 63, 217,
  11718                     9, 38, 187, 250, 226, 183, 38, 164, 182, 218, 22, 19, 58, 189, 83, 219, 11,
  11719                     144, 15, 99, 151, 166, 46, 57, 17, 111, 189, 131, 142, 113, 85, 122, 188, 238,
  11720                     52, 21, 116, 125, 102, 195, 182, 165, 29, 156, 213, 182, 125, 156, 88, 56, 221,
  11721                     2, 98, 43, 210, 115, 32, 4, 105, 88, 181, 158, 207, 236, 162, 250, 253, 240,
  11722                     72, 8, 253, 50, 220, 247, 76, 170, 143, 68, 225, 231, 113, 64, 244, 17, 138,
  11723                     162, 233, 33, 2, 67, 11, 223, 188, 232, 152, 193, 20, 32, 243, 52, 64, 43, 2,
  11724                     243, 8, 77, 150, 232, 109, 148, 95, 127, 55, 71, 162, 34, 54, 83, 135, 52, 172,
  11725                     191, 32, 42, 106, 43, 211, 206, 100, 104, 110, 232, 5, 43, 120, 180, 166, 40,
  11726                     144, 233, 239, 103, 134, 103, 255, 224, 138, 184, 208, 137, 127, 36, 189, 143,
  11727                     248, 201, 2, 218, 51, 232, 96, 30, 83, 124, 109, 241, 23, 179, 247, 151, 238,
  11728                     212, 204, 44, 43, 223, 148, 241, 172, 10, 235, 155, 94, 68, 116, 24, 116, 191,
  11729                     86, 53, 127, 35, 133, 198, 204, 59, 76, 110, 16, 1, 15, 148, 135, 157,
  11730                 ]
  11731                 .as_slice(),
  11732             ),
  11733             0x0001_0001u32.into(),
  11734             BoxedUint::from_le_slice_vartime(
  11735                 [
  11736                     129, 93, 123, 251, 104, 29, 84, 203, 116, 100, 75, 237, 111, 160, 12, 100, 172,
  11737                     76, 57, 178, 144, 235, 81, 61, 115, 243, 28, 40, 183, 22, 56, 150, 68, 38, 220,
  11738                     62, 233, 110, 48, 174, 35, 197, 244, 109, 148, 109, 36, 69, 69, 82, 225, 113,
  11739                     175, 6, 239, 27, 193, 101, 50, 239, 122, 102, 7, 46, 98, 79, 195, 116, 155,
  11740                     158, 138, 147, 51, 93, 24, 237, 246, 82, 14, 109, 144, 250, 239, 93, 63, 214,
  11741                     96, 130, 226, 134, 198, 145, 161, 11, 231, 97, 214, 180, 255, 95, 158, 88, 108,
  11742                     254, 243, 177, 133, 184, 92, 95, 148, 88, 55, 124, 245, 244, 84, 86, 4, 121,
  11743                     44, 231, 97, 176, 190, 29, 155, 40, 57, 69, 165, 80, 168, 9, 56, 43, 233, 6,
  11744                     14, 157, 112, 223, 64, 88, 141, 7, 65, 23, 64, 208, 6, 83, 61, 8, 182, 248,
  11745                     126, 84, 179, 163, 80, 238, 90, 133, 4, 14, 71, 177, 175, 27, 29, 151, 211,
  11746                     108, 162, 195, 7, 157, 167, 86, 169, 3, 87, 235, 89, 158, 237, 216, 31, 243,
  11747                     197, 62, 5, 84, 131, 230, 186, 248, 49, 12, 93, 244, 61, 135, 180, 17, 162,
  11748                     241, 13, 115, 241, 138, 219, 98, 155, 166, 191, 63, 12, 37, 1, 165, 178, 84,
  11749                     200, 72, 80, 41, 77, 136, 217, 141, 246, 209, 31, 243, 159, 71, 43, 246, 159,
  11750                     182, 171, 116, 12, 3, 142, 235, 218, 164, 70, 90, 147, 238, 42, 75,
  11751                 ]
  11752                 .as_slice(),
  11753             ),
  11754             vec![
  11755                 BoxedUint::from_le_slice_vartime(
  11756                     [
  11757                         215, 199, 110, 28, 64, 16, 16, 109, 106, 152, 150, 124, 52, 166, 121, 92,
  11758                         242, 13, 0, 69, 7, 152, 72, 172, 118, 63, 156, 180, 140, 39, 53, 29, 197,
  11759                         224, 177, 48, 41, 221, 102, 65, 17, 185, 55, 62, 219, 152, 227, 7, 78, 219,
  11760                         14, 139, 71, 204, 144, 152, 14, 39, 247, 244, 165, 224, 234, 60, 213, 74,
  11761                         237, 30, 102, 177, 242, 138, 168, 31, 122, 47, 206, 155, 225, 113, 103,
  11762                         175, 152, 244, 27, 233, 112, 223, 248, 38, 215, 178, 20, 244, 8, 121, 26,
  11763                         11, 70, 122, 16, 85, 167, 87, 64, 216, 228, 227, 173, 57, 250, 8, 221, 38,
  11764                         12, 203, 212, 1, 112, 43, 72, 91, 225, 97, 228, 57, 154, 193,
  11765                     ]
  11766                     .as_slice(),
  11767                 ),
  11768                 BoxedUint::from_le_slice_vartime(
  11769                     [
  11770                         233, 89, 204, 152, 31, 242, 8, 110, 38, 190, 111, 159, 105, 105, 45, 85,
  11771                         15, 244, 30, 250, 174, 226, 219, 111, 107, 191, 196, 135, 17, 123, 186,
  11772                         167, 85, 13, 120, 197, 159, 129, 78, 237, 152, 31, 230, 26, 229, 253, 197,
  11773                         211, 105, 204, 126, 142, 250, 55, 26, 172, 65, 160, 45, 6, 99, 86, 66, 238,
  11774                         107, 6, 98, 171, 93, 224, 201, 160, 31, 204, 82, 120, 228, 158, 238, 6,
  11775                         190, 12, 150, 153, 239, 95, 57, 71, 100, 239, 235, 155, 73, 200, 5, 225,
  11776                         127, 185, 46, 48, 243, 84, 33, 142, 17, 19, 20, 23, 215, 16, 114, 58, 211,
  11777                         14, 73, 148, 168, 252, 159, 252, 125, 57, 101, 211, 188, 12, 77, 208,
  11778                     ]
  11779                     .as_slice(),
  11780                 ),
  11781             ],
  11782         )
  11783         .unwrap()
  11784         .to_public_key();
  11785         err = Error::invalid_value(
  11786             Unexpected::Bytes([0; 32].as_slice()),
  11787             &format!(
  11788                 "DER-encoded public key to match the public key within the attestation object: Rsa(RsaPubKey({:?}, 65537))",
  11789                 &att_obj[n_start..e_start],
  11790             )
  11791             .as_str(),
  11792         )
  11793         .to_string().into_bytes();
  11794         assert_eq!(serde_json::from_str::<RegistrationRelaxed>(
  11795             serde_json::json!({
  11796                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11797                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11798                 "response": {
  11799                     "clientDataJSON": b64_cdata_json,
  11800                     "authenticatorData": b64_adata,
  11801                     "transports": [],
  11802                     "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
  11803                     "publicKeyAlgorithm": -257i16,
  11804                     "attestationObject": b64_aobj,
  11805                 },
  11806                 "clientExtensionResults": {},
  11807                 "type": "public-key"
  11808             })
  11809             .to_string()
  11810             .as_str()
  11811             )
  11812            .unwrap_err().to_string().into_bytes().get(..err.len()),
  11813             Some(err.as_slice())
  11814         );
  11815         // Missing `publicKey`.
  11816         drop(
  11817             serde_json::from_str::<RegistrationRelaxed>(
  11818                 serde_json::json!({
  11819                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11820                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11821                     "response": {
  11822                         "clientDataJSON": b64_cdata_json,
  11823                         "authenticatorData": b64_adata,
  11824                         "transports": [],
  11825                         "publicKeyAlgorithm": -257i16,
  11826                         "attestationObject": b64_aobj,
  11827                     },
  11828                     "clientExtensionResults": {},
  11829                     "type": "public-key"
  11830                 })
  11831                 .to_string()
  11832                 .as_str(),
  11833             )
  11834             .unwrap(),
  11835         );
  11836         // `null` `publicKey`.
  11837         drop(
  11838             serde_json::from_str::<RegistrationRelaxed>(
  11839                 serde_json::json!({
  11840                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11841                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11842                     "response": {
  11843                         "clientDataJSON": b64_cdata_json,
  11844                         "authenticatorData": b64_adata,
  11845                         "transports": [],
  11846                         "publicKey": null,
  11847                         "publicKeyAlgorithm": -257i16,
  11848                         "attestationObject": b64_aobj,
  11849                     },
  11850                     "clientExtensionResults": {},
  11851                     "type": "public-key"
  11852                 })
  11853                 .to_string()
  11854                 .as_str(),
  11855             )
  11856             .unwrap(),
  11857         );
  11858         // Base case is valid.
  11859         assert!(
  11860             serde_json::from_str::<CustomRegistration>(
  11861                 serde_json::json!({
  11862                     "clientDataJSON": b64_cdata_json,
  11863                     "transports": [],
  11864                     "attestationObject": b64_aobj,
  11865                     "clientExtensionResults": {},
  11866                     "type": "public-key"
  11867                 })
  11868                 .to_string()
  11869                 .as_str()
  11870             )
  11871             .is_ok_and(
  11872                 |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
  11873                     && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
  11874                     && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
  11875                         == *Sha256::digest(c_data_json.as_bytes())
  11876                     && reg.0.response.transports.is_empty()
  11877                     && matches!(
  11878                         reg.0.authenticator_attachment,
  11879                         AuthenticatorAttachment::None
  11880                     )
  11881                     && reg.0.client_extension_results.cred_props.is_none()
  11882                     && reg.0.client_extension_results.prf.is_none()
  11883             )
  11884         );
  11885     }
  11886 }