webauthn_rp

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

ser.rs (373797B)


      1 use super::{
      2     super::{
      3         super::request::register::CoseAlgorithmIdentifier,
      4         ser::{
      5             AuthenticationExtensionsPrfOutputsHelper, AuthenticationExtensionsPrfValues,
      6             Base64DecodedVal, ClientExtensions, PublicKeyCredential,
      7         },
      8     },
      9     AttestationObject, AttestedCredentialData, AuthTransports, AuthenticationExtensionsPrfOutputs,
     10     AuthenticatorAttestation, ClientExtensionsOutputs, CredentialPropertiesOutput, FromCbor as _,
     11     Registration, UncompressedPubKey,
     12 };
     13 #[cfg(doc)]
     14 use super::{AuthenticatorAttachment, CredentialId};
     15 use core::{
     16     fmt::{self, Formatter},
     17     marker::PhantomData,
     18     str,
     19 };
     20 use rsa::sha2::{Sha256, digest::OutputSizeUser as _};
     21 use serde::de::{Deserialize, Deserializer, Error, IgnoredAny, MapAccess, Unexpected, Visitor};
     22 /// Functionality for deserializing DER-encoded `SubjectPublicKeyInfo` _without_ making copies of data or
     23 /// verifying the key is valid. This exists purely to ensure that the public key we receive in JSON is the same as
     24 /// the public key in the attestation object.
     25 mod spki {
     26     use super::super::{
     27         Ed25519PubKey, MlDsa44PubKey, MlDsa65PubKey, MlDsa87PubKey, RsaPubKey, RsaPubKeyErr,
     28         UncompressedP256PubKey, UncompressedP384PubKey, UncompressedPubKey,
     29     };
     30     use core::fmt::{self, Display, Formatter};
     31     use p256::{
     32         NistP256,
     33         elliptic_curve::{Curve, common::typenum::type_operators::ToInt as _},
     34     };
     35     use p384::NistP384;
     36     /// Value assigned to the integer type under the universal tag class per
     37     /// [ITU-T X.680](https://www.itu.int/rec/T-REC-X.680-202102-I/en).
     38     const INTEGER: u8 = 2;
     39     /// Value assigned to the bitstring type under the universal tag class per
     40     /// [ITU-T X.680](https://www.itu.int/rec/T-REC-X.680-202102-I/en).
     41     const BITSTRING: u8 = 3;
     42     /// Value assigned to the null type under the universal tag class per
     43     /// [ITU-T X.680](https://www.itu.int/rec/T-REC-X.680-202102-I/en).
     44     const NULL: u8 = 5;
     45     /// Value assigned to the object identifier type under the universal tag class per
     46     /// [ITU-T X.680](https://www.itu.int/rec/T-REC-X.680-202102-I/en).
     47     const OID: u8 = 6;
     48     /// Value assigned to the sequence type under the universal tag class per
     49     /// [ITU-T X.680](https://www.itu.int/rec/T-REC-X.680-202102-I/en).
     50     const SEQUENCE: u8 = 16;
     51     /// Value assigned to a constructed [`SEQUENCE`] per
     52     /// [ITU-T X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
     53     ///
     54     /// All sequences are constructed once encoded, so this will likely always be used instead of
     55     /// `SEQUENCE`.
     56     const CONSTRUCTED_SEQUENCE: u8 = SEQUENCE | 0b0010_0000;
     57     /// Length of the header before the encoded key in a DER-encoded ASN.1 `SubjectPublicKeyInfo`
     58     /// for an ML-DSA-87 public key.
     59     const MLDSA87_HEADER_LEN: usize = 22;
     60     /// Length of a DER-encoded ASN.1 `SubjectPublicKeyInfo` for ML-DSA-87 public key.
     61     const MLDSA87_LEN: usize = MLDSA87_HEADER_LEN + 2592;
     62     /// Length of the header before the encoded key in a DER-encoded ASN.1 `SubjectPublicKeyInfo`
     63     /// for an ML-DSA-65 public key.
     64     const MLDSA65_HEADER_LEN: usize = 22;
     65     /// Length of a DER-encoded ASN.1 `SubjectPublicKeyInfo` for ML-DSA-65 public key.
     66     const MLDSA65_LEN: usize = MLDSA65_HEADER_LEN + 1952;
     67     /// Length of the header before the encoded key in a DER-encoded ASN.1 `SubjectPublicKeyInfo`
     68     /// for an ML-DSA-44 public key.
     69     const MLDSA44_HEADER_LEN: usize = 22;
     70     /// Length of a DER-encoded ASN.1 `SubjectPublicKeyInfo` for ML-DSA-44 public key.
     71     const MLDSA44_LEN: usize = MLDSA44_HEADER_LEN + 1312;
     72     /// Length of the header before the compressed y-coordinate in a DER-encoded ASN.1 `SubjectPublicKeyInfo`
     73     /// for an Ed25519 public key.
     74     const ED25519_HEADER_LEN: usize = 12;
     75     /// Length of a DER-encoded ASN.1 `SubjectPublicKeyInfo` for Ed25519 public key.
     76     const ED25519_LEN: usize = ED25519_HEADER_LEN + ed25519_dalek::PUBLIC_KEY_LENGTH;
     77     /// `ED25519_LEN` as a `u8`.
     78     // `44 as u8` is clearly OK.
     79     #[expect(
     80         clippy::as_conversions,
     81         clippy::cast_possible_truncation,
     82         reason = "comments above justify their correctness"
     83     )]
     84     const ED25519_LEN_U8: u8 = ED25519_LEN as u8;
     85     /// Length of the header before the uncompressed SEC- 1 pubic key in a DER-encoded ASN.1 `SubjectPublicKeyInfo`
     86     /// for an uncompressed ECDSA public key based on secp256r1/P-256.
     87     const P256_HEADER_LEN: usize = 27;
     88     /// Number of bytes the x-coordinate takes in an uncompressed P-256 public key.
     89     const P256_X_LEN: usize = <NistP256 as Curve>::FieldBytesSize::INT;
     90     /// Number of bytes the y-coordinate takes in an uncompressed P-256 public key.
     91     const P256_Y_LEN: usize = <NistP256 as Curve>::FieldBytesSize::INT;
     92     /// Number of bytes the x and y coordinates take in an uncompressed P-256 public key when concatenated together.
     93     const P256_COORD_LEN: usize = P256_X_LEN + P256_Y_LEN;
     94     /// Length of a DER-encoded ASN.1 `SubjectPublicKeyInfo` for an uncompressed SEC-1 ECDSA public key
     95     /// based on secp256r1/P-256.
     96     const P256_LEN: usize = P256_HEADER_LEN + P256_COORD_LEN;
     97     /// `P256_LEN` as a `u8`.
     98     // `91 as u8` is clearly OK.
     99     #[expect(
    100         clippy::as_conversions,
    101         clippy::cast_possible_truncation,
    102         reason = "comments above justify their correctness"
    103     )]
    104     const P256_LEN_U8: u8 = P256_LEN as u8;
    105     /// Length of the header before the uncompressed SEC- 1 pubic key in a DER-encoded ASN.1 `SubjectPublicKeyInfo`
    106     /// for an uncompressed ECDSA public key based on secp384r1/P-384.
    107     const P384_HEADER_LEN: usize = 24;
    108     /// Number of bytes the x-coordinate takes in an uncompressed P-384 public key.
    109     const P384_X_LEN: usize = <NistP384 as Curve>::FieldBytesSize::INT;
    110     /// Number of bytes the y-coordinate takes in an uncompressed P-384 public key.
    111     const P384_Y_LEN: usize = <NistP384 as Curve>::FieldBytesSize::INT;
    112     /// Number of bytes the x and y coordinates take in an uncompressed P-384 public key when concatenated together.
    113     const P384_COORD_LEN: usize = P384_X_LEN + P384_Y_LEN;
    114     /// Length of a DER-encoded ASN.1 `SubjectPublicKeyInfo` for an uncompressed SEC-1 ECDSA public key
    115     /// based on secp384r1/P-384.
    116     const P384_LEN: usize = P384_HEADER_LEN + P384_COORD_LEN;
    117     /// `P384_LEN` as a `u8`.
    118     // `120 as u8` is clearly OK.
    119     #[expect(
    120         clippy::as_conversions,
    121         clippy::cast_possible_truncation,
    122         reason = "comments above justify their correctness"
    123     )]
    124     const P384_LEN_U8: u8 = P384_LEN as u8;
    125     /// Error returned from [`SubjectPublicKeyInfo::from_der`].
    126     pub(super) enum SubjectPublicKeyInfoErr {
    127         /// The length of the DER-encoded ML-DSA-87 key was invalid.
    128         MlDsa87Len,
    129         /// The header of the DER-encoded ML-DSA-87 key was invalid.
    130         MlDsa87Header,
    131         /// The length of the DER-encoded ML-DSA-65 key was invalid.
    132         MlDsa65Len,
    133         /// The header of the DER-encoded ML-DSA-65 key was invalid.
    134         MlDsa65Header,
    135         /// The length of the DER-encoded ML-DSA-44 key was invalid.
    136         MlDsa44Len,
    137         /// The header of the DER-encoded ML-DSA-44 key was invalid.
    138         MlDsa44Header,
    139         /// The length of the DER-encoded Ed25519 key was invalid.
    140         Ed25519Len,
    141         /// The header of the DER-encoded Ed25519 key was invalid.
    142         Ed25519Header,
    143         /// The length of the DER-encoded P-256 key was invalid.
    144         P256Len,
    145         /// The header of the DER-encoded P-256 key was invalid.
    146         P256Header,
    147         /// The length of the DER-encoded P-384 key was invalid.
    148         P384Len,
    149         /// The header of the DER-encoded P-384 key was invalid.
    150         P384Header,
    151         /// The length of the DER-encoded RSA key was invalid.
    152         RsaLen,
    153         /// The DER-encoding of the RSA key was invalid.
    154         RsaEncoding,
    155         /// The exponent of the DER-encoded RSA key was too large.
    156         RsaExponentTooLarge,
    157         /// The DER-encoded RSA key was not a valid [`RsaPubKey`].
    158         RsaPubKey(RsaPubKeyErr),
    159     }
    160     impl Display for SubjectPublicKeyInfoErr {
    161         fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    162             match *self {
    163                 Self::MlDsa87Len => {
    164                     f.write_str("length of the DER-encoded ML-DSA-87 key was invalid")
    165                 }
    166                 Self::MlDsa87Header => {
    167                     f.write_str("header of the DER-encoded ML-DSA-87 key was invalid")
    168                 }
    169                 Self::MlDsa65Len => {
    170                     f.write_str("length of the DER-encoded ML-DSA-65 key was invalid")
    171                 }
    172                 Self::MlDsa65Header => {
    173                     f.write_str("header of the DER-encoded ML-DSA-65 key was invalid")
    174                 }
    175                 Self::MlDsa44Len => {
    176                     f.write_str("length of the DER-encoded ML-DSA-44 key was invalid")
    177                 }
    178                 Self::MlDsa44Header => {
    179                     f.write_str("header of the DER-encoded ML-DSA-44 key was invalid")
    180                 }
    181                 Self::Ed25519Len => {
    182                     f.write_str("length of the DER-encoded Ed25519 key was invalid")
    183                 }
    184                 Self::Ed25519Header => {
    185                     f.write_str("header of the DER-encoded Ed25519 key was invalid")
    186                 }
    187                 Self::P256Len => f.write_str("length of the DER-encoded P-256 key was invalid"),
    188                 Self::P256Header => f.write_str("header of the DER-encoded P-256 key was invalid"),
    189                 Self::P384Len => f.write_str("length of the DER-encoded P-384 key was invalid"),
    190                 Self::P384Header => f.write_str("header of the DER-encoded P-384 key was invalid"),
    191                 Self::RsaLen => f.write_str("length of the DER-encoded RSA key was invalid"),
    192                 Self::RsaEncoding => {
    193                     f.write_str("the DER-encoding of the RSA public key was invalid")
    194                 }
    195                 Self::RsaExponentTooLarge => {
    196                     f.write_str("the DER-encoded RSA public key had an exponent that was too large")
    197                 }
    198                 Self::RsaPubKey(err) => {
    199                     write!(f, "the DER-encoded RSA public was not valid: {err}")
    200                 }
    201             }
    202         }
    203     }
    204     /// Types that can be deserialized from the DER-encoded ASN.1 `SubjectPublicKeyInfo` as defined in
    205     /// [RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280#appendix-A.1) and other applicable RFCs
    206     /// and documents (e.g., [ITU-T X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en)).
    207     pub(super) trait SubjectPublicKeyInfo<'a>: Sized {
    208         /// Transforms the DER-encoded ASN.1 `SubjectPublicKeyInfo` into `Self`.
    209         ///
    210         /// # Errors
    211         ///
    212         /// Errors iff `der` does not conform.
    213         #[expect(single_use_lifetimes, reason = "false positive")]
    214         fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr>;
    215     }
    216     impl<'a> SubjectPublicKeyInfo<'a> for MlDsa87PubKey<&'a [u8]> {
    217         #[expect(single_use_lifetimes, reason = "false positive")]
    218         fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    219             /// ```asn
    220             /// SubjectPublicKeyInfo ::= SEQUENCE {
    221             ///     algorithm           AlgorithmIdentifier,
    222             ///     subjectPublicKey    BIT STRING
    223             /// }
    224             ///
    225             /// AlgorithmIdentifier ::= SEQUENCE {
    226             ///     algorithm     OBJECT IDENTIFIER,
    227             ///     parameters    ANY DEFINED BY algorithm OPTIONAL
    228             /// }
    229             /// ```
    230             ///
    231             /// [RFC 9882](https://www.rfc-editor.org/rfc/rfc9882.html) requires parameters to not exist
    232             /// in `AlgorithmIdentifier`.
    233             ///
    234             /// RFC 9882 defines the OID as 2.16.840.1.101.3.4.3.19 which is encoded as 96.134.72.1.101.3.4.3.19
    235             /// per [X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
    236             ///
    237             /// [FIPS 204](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf) defines the bitstring as a reinterpretation of the byte string.
    238             const HEADER: [u8; MLDSA87_HEADER_LEN] = [
    239                 CONSTRUCTED_SEQUENCE,
    240                 130,
    241                 10,
    242                 50,
    243                 CONSTRUCTED_SEQUENCE,
    244                 9 + 2,
    245                 OID,
    246                 9,
    247                 96,
    248                 134,
    249                 72,
    250                 1,
    251                 101,
    252                 3,
    253                 4,
    254                 3,
    255                 19,
    256                 BITSTRING,
    257                 130,
    258                 10,
    259                 33,
    260                 // The number of unused bits.
    261                 0,
    262             ];
    263             der.split_at_checked(HEADER.len())
    264                 .ok_or(SubjectPublicKeyInfoErr::MlDsa87Len)
    265                 .and_then(|(header, rem)| {
    266                     if header == HEADER {
    267                         if rem.len() == 2592 {
    268                             Ok(Self(rem))
    269                         } else {
    270                             Err(SubjectPublicKeyInfoErr::MlDsa87Len)
    271                         }
    272                     } else {
    273                         Err(SubjectPublicKeyInfoErr::MlDsa87Header)
    274                     }
    275                 })
    276         }
    277     }
    278     impl<'a> SubjectPublicKeyInfo<'a> for MlDsa65PubKey<&'a [u8]> {
    279         #[expect(single_use_lifetimes, reason = "false positive")]
    280         fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    281             /// ```asn
    282             /// SubjectPublicKeyInfo ::= SEQUENCE {
    283             ///     algorithm           AlgorithmIdentifier,
    284             ///     subjectPublicKey    BIT STRING
    285             /// }
    286             ///
    287             /// AlgorithmIdentifier ::= SEQUENCE {
    288             ///     algorithm     OBJECT IDENTIFIER,
    289             ///     parameters    ANY DEFINED BY algorithm OPTIONAL
    290             /// }
    291             /// ```
    292             ///
    293             /// [RFC 9882](https://www.rfc-editor.org/rfc/rfc9882.html) requires parameters to not exist
    294             /// in `AlgorithmIdentifier`.
    295             ///
    296             /// RFC 9882 defines the OID as 2.16.840.1.101.3.4.3.18 which is encoded as 96.134.72.1.101.3.4.3.18
    297             /// per [X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
    298             ///
    299             /// [FIPS 204](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf) defines the bitstring as a reinterpretation of the byte string.
    300             const HEADER: [u8; MLDSA65_HEADER_LEN] = [
    301                 CONSTRUCTED_SEQUENCE,
    302                 130,
    303                 7,
    304                 178,
    305                 CONSTRUCTED_SEQUENCE,
    306                 9 + 2,
    307                 OID,
    308                 9,
    309                 96,
    310                 134,
    311                 72,
    312                 1,
    313                 101,
    314                 3,
    315                 4,
    316                 3,
    317                 18,
    318                 BITSTRING,
    319                 130,
    320                 7,
    321                 161,
    322                 // The number of unused bits.
    323                 0,
    324             ];
    325             der.split_at_checked(HEADER.len())
    326                 .ok_or(SubjectPublicKeyInfoErr::MlDsa65Len)
    327                 .and_then(|(header, rem)| {
    328                     if header == HEADER {
    329                         if rem.len() == 1952 {
    330                             Ok(Self(rem))
    331                         } else {
    332                             Err(SubjectPublicKeyInfoErr::MlDsa65Len)
    333                         }
    334                     } else {
    335                         Err(SubjectPublicKeyInfoErr::MlDsa65Header)
    336                     }
    337                 })
    338         }
    339     }
    340     impl<'a> SubjectPublicKeyInfo<'a> for MlDsa44PubKey<&'a [u8]> {
    341         #[expect(single_use_lifetimes, reason = "false positive")]
    342         fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    343             /// ```asn
    344             /// SubjectPublicKeyInfo ::= SEQUENCE {
    345             ///     algorithm           AlgorithmIdentifier,
    346             ///     subjectPublicKey    BIT STRING
    347             /// }
    348             ///
    349             /// AlgorithmIdentifier ::= SEQUENCE {
    350             ///     algorithm     OBJECT IDENTIFIER,
    351             ///     parameters    ANY DEFINED BY algorithm OPTIONAL
    352             /// }
    353             /// ```
    354             ///
    355             /// [RFC 9882](https://www.rfc-editor.org/rfc/rfc9882.html) requires parameters to not exist
    356             /// in `AlgorithmIdentifier`.
    357             ///
    358             /// RFC 9882 defines the OID as 2.16.840.1.101.3.4.3.17 which is encoded as 96.134.72.1.101.3.4.3.17
    359             /// per [X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
    360             ///
    361             /// [FIPS 204](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf) defines the bitstring as a reinterpretation of the byte string.
    362             const HEADER: [u8; MLDSA44_HEADER_LEN] = [
    363                 CONSTRUCTED_SEQUENCE,
    364                 130,
    365                 5,
    366                 50,
    367                 CONSTRUCTED_SEQUENCE,
    368                 9 + 2,
    369                 OID,
    370                 9,
    371                 96,
    372                 134,
    373                 72,
    374                 1,
    375                 101,
    376                 3,
    377                 4,
    378                 3,
    379                 17,
    380                 BITSTRING,
    381                 130,
    382                 5,
    383                 33,
    384                 // The number of unused bits.
    385                 0,
    386             ];
    387             der.split_at_checked(HEADER.len())
    388                 .ok_or(SubjectPublicKeyInfoErr::MlDsa44Len)
    389                 .and_then(|(header, rem)| {
    390                     if header == HEADER {
    391                         if rem.len() == 1312 {
    392                             Ok(Self(rem))
    393                         } else {
    394                             Err(SubjectPublicKeyInfoErr::MlDsa44Len)
    395                         }
    396                     } else {
    397                         Err(SubjectPublicKeyInfoErr::MlDsa44Header)
    398                     }
    399                 })
    400         }
    401     }
    402     impl<'a> SubjectPublicKeyInfo<'a> for Ed25519PubKey<&'a [u8]> {
    403         #[expect(single_use_lifetimes, reason = "false positive")]
    404         fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    405             /// ```asn
    406             /// SubjectPublicKeyInfo ::= SEQUENCE {
    407             ///     algorithm           AlgorithmIdentifier,
    408             ///     subjectPublicKey    BIT STRING
    409             /// }
    410             ///
    411             /// AlgorithmIdentifier ::= SEQUENCE {
    412             ///     algorithm     OBJECT IDENTIFIER,
    413             ///     parameters    ANY DEFINED BY algorithm OPTIONAL
    414             /// }
    415             /// ```
    416             ///
    417             /// [RFC 8410](https://www.rfc-editor.org/rfc/rfc8410#section-3) requires parameters to not exist
    418             /// in `AlgorithmIdentifier`.
    419             ///
    420             /// RFC 8410 defines the OID as 1.3.101.112 which is encoded as 43.101.112
    421             /// per [X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
    422             ///
    423             /// RFC 8410 defines the bitstring as a reinterpretation of the byte string.
    424             const HEADER: [u8; ED25519_HEADER_LEN] = [
    425                 CONSTRUCTED_SEQUENCE,
    426                 // `ED25519_LEN_U8` is the length of the entire payload; thus we subtract
    427                 // the "consumed" length.
    428                 ED25519_LEN_U8 - 2,
    429                 CONSTRUCTED_SEQUENCE,
    430                 // AlgorithmIdentifier only contains the OID; thus it's length is 5.
    431                 3 + 2,
    432                 OID,
    433                 3,
    434                 43,
    435                 101,
    436                 112,
    437                 BITSTRING,
    438                 // `ED25519_LEN_U8` is the length of the entire payload; thus we subtract
    439                 // the "consumed" length.
    440                 ED25519_LEN_U8 - 11,
    441                 // The number of unused bits.
    442                 0,
    443             ];
    444             der.split_at_checked(HEADER.len())
    445                 .ok_or(SubjectPublicKeyInfoErr::Ed25519Len)
    446                 .and_then(|(header, rem)| {
    447                     if header == HEADER {
    448                         if rem.len() == ed25519_dalek::PUBLIC_KEY_LENGTH {
    449                             Ok(Self(rem))
    450                         } else {
    451                             Err(SubjectPublicKeyInfoErr::Ed25519Len)
    452                         }
    453                     } else {
    454                         Err(SubjectPublicKeyInfoErr::Ed25519Header)
    455                     }
    456                 })
    457         }
    458     }
    459     impl<'a> SubjectPublicKeyInfo<'a> for UncompressedP256PubKey<'a> {
    460         #[expect(single_use_lifetimes, reason = "false positive")]
    461         fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    462             // ```asn
    463             // SubjectPublicKeyInfo ::= SEQUENCE {
    464             //     algorithm           AlgorithmIdentifier,
    465             //     subjectPublicKey    BIT STRING
    466             // }
    467             //
    468             // AlgorithmIdentifier ::= SEQUENCE {
    469             //     algorithm     OBJECT IDENTIFIER,
    470             //     parameters    ANY DEFINED BY algorithm OPTIONAL
    471             // }
    472             //
    473             // ECParameters ::= CHOICE {
    474             //     namedCurve         OBJECT IDENTIFIER
    475             //     -- implicitCurve   NULL
    476             //     -- specifiedCurve  SpecifiedECDomain
    477             // }
    478             // ```
    479             // [RFC 5480](https://www.rfc-editor.org/rfc/rfc5480#section-2.1.1) requires parameters to exist and
    480             // be of the `ECParameters` form with the requirement that `namedCurve` is chosen.
    481             //
    482             // RFC 5480 defines the OID for id-ecPublicKey as 1.2.840.10045.2.1 and the OID for the namedCurve
    483             // secp256r1 as 1.2.840.10045.3.1.7. The former OID is encoded as 42.134.72.206.61.2.1 and the latter
    484             // is encoded as 42.134.72.206.61.3.1.7 per [X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
    485             //
    486             // [RFC 5480](https://www.rfc-editor.org/rfc/rfc5480#section-5) only requires support for the
    487             // uncompressed form and only states that the compressed form MAY be supported. In practice this means
    488             // DER-encoded payloads almost always are of the uncompressed form for compatibility reasons. This in
    489             // conjunction with the fact the COSE key is required to be in the uncompressed form means we only support
    490             // DER-encoded payloads containing uncompressed keys.
    491             //
    492             // [SEC 1](https://secg.org/sec1-v2.pdf) defines the point as an octet string, and the conversion
    493             // to a bitstring simply requires reinterpreting the octet string as a bitstring.
    494 
    495             /// Header of the DER-encoded payload before the public key.
    496             const HEADER: [u8; P256_HEADER_LEN] = [
    497                 CONSTRUCTED_SEQUENCE,
    498                 // `P256_LEN_U8` is the length of the entire payload; thus we subtract
    499                 // the "consumed" length.
    500                 P256_LEN_U8 - 2,
    501                 CONSTRUCTED_SEQUENCE,
    502                 7 + 2 + 8 + 2,
    503                 OID,
    504                 7,
    505                 42,
    506                 134,
    507                 72,
    508                 206,
    509                 61,
    510                 2,
    511                 1,
    512                 OID,
    513                 8,
    514                 42,
    515                 134,
    516                 72,
    517                 206,
    518                 61,
    519                 3,
    520                 1,
    521                 7,
    522                 BITSTRING,
    523                 // `P256_LEN_U8` is the length of the entire payload; thus we subtract
    524                 // the "consumed" length.
    525                 P256_LEN_U8 - 25,
    526                 // The number of unused bits.
    527                 0,
    528                 // SEC-1 tag for an uncompressed key.
    529                 4,
    530             ];
    531             der.split_at_checked(HEADER.len())
    532                 .ok_or(SubjectPublicKeyInfoErr::P256Len)
    533                 .and_then(|(header, header_rem)| {
    534                     if header == HEADER {
    535                         header_rem
    536                             .split_at_checked(P256_X_LEN)
    537                             .ok_or(SubjectPublicKeyInfoErr::P256Len)
    538                             .and_then(|(x, y)| {
    539                                 if y.len() == P256_Y_LEN {
    540                                     Ok(Self(x, y))
    541                                 } else {
    542                                     Err(SubjectPublicKeyInfoErr::P256Len)
    543                                 }
    544                             })
    545                     } else {
    546                         Err(SubjectPublicKeyInfoErr::P256Header)
    547                     }
    548                 })
    549         }
    550     }
    551     impl<'a> SubjectPublicKeyInfo<'a> for UncompressedP384PubKey<'a> {
    552         #[expect(single_use_lifetimes, reason = "false positive")]
    553         fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    554             // ```asn
    555             // SubjectPublicKeyInfo ::= SEQUENCE {
    556             //     algorithm           AlgorithmIdentifier,
    557             //     subjectPublicKey    BIT STRING
    558             // }
    559             //
    560             // AlgorithmIdentifier ::= SEQUENCE {
    561             //     algorithm     OBJECT IDENTIFIER,
    562             //     parameters    ANY DEFINED BY algorithm OPTIONAL
    563             // }
    564             //
    565             // ECParameters ::= CHOICE {
    566             //     namedCurve         OBJECT IDENTIFIER
    567             //     -- implicitCurve   NULL
    568             //     -- specifiedCurve  SpecifiedECDomain
    569             // }
    570             // ```
    571             // [RFC 5480](https://www.rfc-editor.org/rfc/rfc5480#section-2.1.1) requires parameters to exist and
    572             // be of the `ECParameters` form with the requirement that `namedCurve` is chosen.
    573             //
    574             // RFC 5480 defines the OID for id-ecPublicKey as 1.2.840.10045.2.1 and the OID for the namedCurve
    575             // secp384r1 as 1.3.132.0.34. The former OID is encoded as 42.134.72.206.61.2.1 and the latter
    576             // is encoded as 43.129.4.0.34 per [X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
    577             //
    578             // [RFC 5480](https://www.rfc-editor.org/rfc/rfc5480#section-5) only requires support for the
    579             // uncompressed form and only states that the compressed form MAY be supported. In practice this means
    580             // DER-encoded payloads almost always are of the uncompressed form for compatibility reasons. This in
    581             // conjunction with the fact the COSE key is required to be in the uncompressed form means we only support
    582             // DER-encoded payloads containing uncompressed keys.
    583             //
    584             // [SEC 1](https://secg.org/sec1-v2.pdf) defines the point as an octet string, and the conversion
    585             // to a bitstring simply requires reinterpreting the octet string as a bitstring.
    586 
    587             /// Header of the DER-encoded payload before the public key.
    588             const HEADER: [u8; P384_HEADER_LEN] = [
    589                 CONSTRUCTED_SEQUENCE,
    590                 // `P384_LEN_U8` is the length of the entire payload; thus we subtract
    591                 // the "consumed" length.
    592                 P384_LEN_U8 - 2,
    593                 CONSTRUCTED_SEQUENCE,
    594                 7 + 2 + 5 + 2,
    595                 OID,
    596                 7,
    597                 42,
    598                 134,
    599                 72,
    600                 206,
    601                 61,
    602                 2,
    603                 1,
    604                 OID,
    605                 5,
    606                 43,
    607                 129,
    608                 4,
    609                 0,
    610                 34,
    611                 BITSTRING,
    612                 // `P384_LEN_U8` is the length of the entire payload; thus we subtract
    613                 // the "consumed" length.
    614                 P384_LEN_U8 - 22,
    615                 // The number of unused bits.
    616                 0,
    617                 // SEC-1 tag for an uncompressed key.
    618                 4,
    619             ];
    620             der.split_at_checked(HEADER.len())
    621                 .ok_or(SubjectPublicKeyInfoErr::P384Len)
    622                 .and_then(|(header, header_rem)| {
    623                     if header == HEADER {
    624                         header_rem
    625                             .split_at_checked(P384_X_LEN)
    626                             .ok_or(SubjectPublicKeyInfoErr::P384Len)
    627                             .and_then(|(x, y)| {
    628                                 if y.len() == P384_Y_LEN {
    629                                     Ok(Self(x, y))
    630                                 } else {
    631                                     Err(SubjectPublicKeyInfoErr::P384Len)
    632                                 }
    633                             })
    634                     } else {
    635                         Err(SubjectPublicKeyInfoErr::P384Header)
    636                     }
    637                 })
    638         }
    639     }
    640     impl<'a> SubjectPublicKeyInfo<'a> for RsaPubKey<&'a [u8]> {
    641         #[expect(single_use_lifetimes, reason = "false positive")]
    642         #[expect(
    643             clippy::arithmetic_side_effects,
    644             clippy::big_endian_bytes,
    645             clippy::indexing_slicing,
    646             clippy::missing_asserts_for_indexing,
    647             reason = "comments justify their correctness"
    648         )]
    649         #[expect(
    650             clippy::too_many_lines,
    651             reason = "rsa keys are the only type that would benefit from a modular SubjectPublicKeyInfo (similar to FromCbor). if more types benefit in the future, then this will be done."
    652         )]
    653         fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    654             // ```asn
    655             // SubjectPublicKeyInfo ::= SEQUENCE {
    656             //     algorithm           AlgorithmIdentifier,
    657             //     subjectPublicKey    BIT STRING
    658             // }
    659             //
    660             // AlgorithmIdentifier ::= SEQUENCE {
    661             //     algorithm     OBJECT IDENTIFIER,
    662             //     parameters    ANY DEFINED BY algorithm OPTIONAL
    663             // }
    664             //
    665             // RSAPublicKey ::= SEQUENCE {
    666             //     modulus          INTEGER, -- n
    667             //     publicExponent   INTEGER  --e
    668             // }
    669             //
    670             // pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
    671             //     rsadsi(113549) pkcs(1) 1
    672             // }
    673             //
    674             // rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1}
    675             // ```
    676             // [RFC 3279](https://www.rfc-editor.org/rfc/rfc3279#section-2.3.1) requires parameters to exist and
    677             // be null.
    678             //
    679             // RFC 3279 defines the OID for rsaEncryption as 1.2.840.113549.1.1.1 which is encoded as
    680             // 42.134.72.134.247.13.1.1.1 per [X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
    681             //
    682             // Note we only allow moduli that are 256 to 2048 bytes in length inclusively. Additionally
    683             // we only allow `u32` exponents; consequently all lengths that include the modulus will always be
    684             // encoded with two bytes.
    685 
    686             /// `AlgorithmIdentifier` header including the `BITSTRING` and number of bytes the length
    687             /// is encoded in of the `BITSTRING` type of `subjectPublicKey`
    688             /// (130-128 = 2 bytes to encode the length).
    689             const ALG_OID_HEADER: [u8; 17] = [
    690                 CONSTRUCTED_SEQUENCE,
    691                 9 + 2 + 2,
    692                 OID,
    693                 9,
    694                 42,
    695                 134,
    696                 72,
    697                 134,
    698                 247,
    699                 13,
    700                 1,
    701                 1,
    702                 1,
    703                 NULL,
    704                 0,
    705                 BITSTRING,
    706                 130,
    707             ];
    708             /// `CONSTRUCTED_SEQUENCE` whose length is encoded in two bytes.
    709             const SEQ_LONG: [u8; 2] = [CONSTRUCTED_SEQUENCE, 130];
    710             /// `INTEGER` whose length is encoded in two bytes.
    711             const INT_LONG: [u8; 2] = [INTEGER, 130];
    712             der.split_at_checked(SEQ_LONG.len())
    713                 .ok_or(SubjectPublicKeyInfoErr::RsaLen)
    714                 .and_then(|(seq, seq_rem)| {
    715                     if seq == SEQ_LONG {
    716                         seq_rem
    717                             .split_at_checked(2)
    718                             .ok_or(SubjectPublicKeyInfoErr::RsaLen)
    719                             .and_then(|(seq_len, seq_len_rem)| {
    720                                 let mut len = [0; 2];
    721                                 len.copy_from_slice(seq_len);
    722                                 let rem_len = usize::from(u16::from_be_bytes(len));
    723                                 if rem_len == seq_len_rem.len() {
    724                                     if rem_len > 255 {
    725                                         // We can safely split here since we know `seq_len_rem` is at least
    726                                         // 256 which is greater than `ALG_OID_HEADER.len()`.
    727                                         let (a_oid, a_oid_rem) = seq_len_rem.split_at(ALG_OID_HEADER.len());
    728                                         if a_oid == ALG_OID_HEADER {
    729                                             // `a_oid_rem.len()` is at least 239, so splitting is fine.
    730                                             let (bit_str_len_enc, bit_str_val) = a_oid_rem.split_at(2);
    731                                             let mut bit_string_len = [0; 2];
    732                                             bit_string_len.copy_from_slice(bit_str_len_enc);
    733                                             let bit_str_val_len = usize::from(u16::from_be_bytes(bit_string_len));
    734                                             if bit_str_val_len == bit_str_val.len() {
    735                                                 if bit_str_val_len > 255 {
    736                                                     // `bit_str_val.len() > 255`, so splitting is fine.
    737                                                     let (unused_bits, bits_rem) = bit_str_val.split_at(1);
    738                                                     if unused_bits == [0] {
    739                                                         // We can safely split here since we know `bits_rem.len()` is at least
    740                                                         // 255.
    741                                                         let (rsa_seq, rsa_seq_rem) = bits_rem.split_at(SEQ_LONG.len());
    742                                                         if rsa_seq == SEQ_LONG {
    743                                                             // `rsa_seq_rem.len()` is at least 253, so splitting is fine.
    744                                                             let (rsa_seq_len_enc, rsa_seq_len_enc_rem) = rsa_seq_rem.split_at(2);
    745                                                             let mut rsa_seq_len = [0; 2];
    746                                                             rsa_seq_len.copy_from_slice(rsa_seq_len_enc);
    747                                                             let rsa_key_info_len = usize::from(u16::from_be_bytes(rsa_seq_len));
    748                                                             if rsa_key_info_len == rsa_seq_len_enc_rem.len() {
    749                                                                 if rsa_key_info_len > 255 {
    750                                                                     // We can safely split here since we know `rsa_seq_len_enc_rem.len()`
    751                                                                     // is at least 256.
    752                                                                     let (n_meta, n_meta_rem) = rsa_seq_len_enc_rem.split_at(INT_LONG.len());
    753                                                                     if n_meta == INT_LONG {
    754                                                                         // `n_meta_rem.len()` is at least 254, so splitting is fine.
    755                                                                         let (n_len_enc, n_len_enc_rem) = n_meta_rem.split_at(2);
    756                                                                         let mut n_len = [0; 2];
    757                                                                         n_len.copy_from_slice(n_len_enc);
    758                                                                         let mod_len = usize::from(u16::from_be_bytes(n_len));
    759                                                                         if mod_len > 255 {
    760                                                                             n_len_enc_rem.split_at_checked(mod_len).ok_or(SubjectPublicKeyInfoErr::RsaLen).and_then(|(mut n, n_rem)| {
    761                                                                                 // `n.len() > 255`, so indexing is fine.
    762                                                                                 let n_first = n[0];
    763                                                                                 // DER integers are signed; thus the most significant bit must be 0.
    764                                                                                 // DER integers are minimally encoded; thus when a leading 0 exists,
    765                                                                                 // the second byte must be at least 128.
    766                                                                                 // `n.len() > 255`, so indexing is fine.
    767                                                                                 if n_first < 128 && (n_first != 0 || n[1] > 127) {
    768                                                                                     if n_first == 0 {
    769                                                                                         // `n.len() > 255`, so indexing is fine.
    770                                                                                         // We must remove the leading 0.
    771                                                                                         n = &n[1..];
    772                                                                                     }
    773                                                                                     n_rem.split_first().ok_or(SubjectPublicKeyInfoErr::RsaLen).and_then(|(e_type, e_type_rem)| {
    774                                                                                         if *e_type == INTEGER {
    775                                                                                             e_type_rem.split_first().ok_or(SubjectPublicKeyInfoErr::RsaLen).and_then(|(e_len, e_len_rem)| {
    776                                                                                                 let e_len_usize = usize::from(*e_len);
    777                                                                                                 if e_len_usize == e_len_rem.len() {
    778                                                                                                     e_len_rem.first().ok_or(SubjectPublicKeyInfoErr::RsaLen).and_then(|&e_first| {
    779                                                                                                         // DER integers are signed; thus the most significant bit must be 0.
    780                                                                                                         if e_first < 128 {
    781                                                                                                             // `RsaPubKey` only allows `u32` exponents, which means we only care
    782                                                                                                             // about lengths up to 5.
    783                                                                                                             match e_len_usize {
    784                                                                                                                 1 => Ok(u32::from(e_first)),
    785                                                                                                                 2..=5 => if e_first == 0 {
    786                                                                                                                     // DER integers are minimally encoded; thus when a leading
    787                                                                                                                     // 0 exists, the second byte must be at least 128.
    788                                                                                                                     // We know the length is at least 2; thus this won't `panic`.
    789                                                                                                                     if e_len_rem[1] > 127 {
    790                                                                                                                         let mut e = [0; 4];
    791                                                                                                                         if e_len_usize == 5 {
    792                                                                                                                             // We know the length is at least 2; thus this won't `panic`.
    793                                                                                                                             e.copy_from_slice(&e_len_rem[1..]);
    794                                                                                                                         } else {
    795                                                                                                                             // `e.len() == 4` and `e_len_usize` is at most 4; thus underflow
    796                                                                                                                             // won't occur nor will indexing `panic`. `e` is big-endian,
    797                                                                                                                             // so we start from the right.
    798                                                                                                                             e[4 - e_len_usize..].copy_from_slice(e_len_rem);
    799                                                                                                                         }
    800                                                                                                                         Ok(u32::from_be_bytes(e))
    801                                                                                                                     } else {
    802                                                                                                                         Err(SubjectPublicKeyInfoErr::RsaEncoding)
    803                                                                                                                     }
    804                                                                                                                 } else if e_len_usize == 5 {
    805                                                                                                                     // 5 bytes are only possible for `INTEGER`s that
    806                                                                                                                     // are greater than `i32::MAX`, which will be encoded
    807                                                                                                                     // with a leading 0.
    808                                                                                                                     Err(SubjectPublicKeyInfoErr::RsaEncoding)
    809                                                                                                                 } else {
    810                                                                                                                     let mut e = [0; 4];
    811                                                                                                                     // `e.len() == 4` and `e_len_usize` is at most 4; thus underflow
    812                                                                                                                     // won't occur nor will indexing `panic`. `e` is big-endian,
    813                                                                                                                     // so we start from the right.
    814                                                                                                                     e[4 - e_len_usize..].copy_from_slice(e_len_rem);
    815                                                                                                                     Ok(u32::from_be_bytes(e))
    816                                                                                                                 },
    817                                                                                                                 _ => Err(SubjectPublicKeyInfoErr::RsaExponentTooLarge),
    818                                                                                                             }.and_then(|e| Self::try_from((n, e)).map_err(SubjectPublicKeyInfoErr::RsaPubKey))
    819                                                                                                         } else {
    820                                                                                                             Err(SubjectPublicKeyInfoErr::RsaEncoding)
    821                                                                                                         }
    822                                                                                                     })
    823                                                                                                 } else {
    824                                                                                                     Err(SubjectPublicKeyInfoErr::RsaLen)
    825                                                                                                 }
    826                                                                                             })
    827                                                                                         } else {
    828                                                                                             Err(SubjectPublicKeyInfoErr::RsaEncoding)
    829                                                                                         }
    830                                                                                     })
    831                                                                                 } else {
    832                                                                                     Err(SubjectPublicKeyInfoErr::RsaEncoding)
    833                                                                                 }
    834                                                                             })
    835                                                                         } else {
    836                                                                             Err(SubjectPublicKeyInfoErr::RsaEncoding)
    837                                                                         }
    838                                                                     } else {
    839                                                                         Err(SubjectPublicKeyInfoErr::RsaEncoding)
    840                                                                     }
    841                                                                 } else {
    842                                                                     Err(SubjectPublicKeyInfoErr::RsaEncoding)
    843                                                                 }
    844                                                             } else {
    845                                                                 Err(SubjectPublicKeyInfoErr::RsaLen)
    846                                                             }
    847                                                         } else {
    848                                                             Err(SubjectPublicKeyInfoErr::RsaEncoding)
    849                                                         }
    850                                                     } else {
    851                                                         Err(SubjectPublicKeyInfoErr::RsaEncoding)
    852                                                     }
    853                                                 } else {
    854                                                     Err(SubjectPublicKeyInfoErr::RsaEncoding)
    855                                                 }
    856                                             } else {
    857                                                 Err(SubjectPublicKeyInfoErr::RsaLen)
    858                                             }
    859                                         } else {
    860                                             Err(SubjectPublicKeyInfoErr::RsaEncoding)
    861                                         }
    862                                     } else {
    863                                         Err(SubjectPublicKeyInfoErr::RsaEncoding)
    864                                     }
    865                                 } else {
    866                                     Err(SubjectPublicKeyInfoErr::RsaLen)
    867                                 }
    868                             })
    869                     } else {
    870                         Err(SubjectPublicKeyInfoErr::RsaEncoding)
    871                     }
    872                 })
    873         }
    874     }
    875     impl<'a> SubjectPublicKeyInfo<'a> for UncompressedPubKey<'a> {
    876         #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
    877         #[expect(single_use_lifetimes, reason = "false positive")]
    878         fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    879             /// Index in a DER-encoded payload of the ML-DSA-* public key that corresponds
    880             /// to the OID length.
    881             const ML_DSA_OID_LEN_IDX: usize = 5;
    882             /// Length of the OID for the DER-encoded ML-DSA-* public keys.
    883             ///
    884             /// Note this is _not_ the same as the OID length for an RSA public key (i.e., 13).
    885             const ML_DSA_OID_LEN: u8 = 11;
    886             // The only lengths that overlap is RSA with ML-DSA-44 and ML-DSA-65.
    887             match der.len() {
    888                 // The minimum modulus we support for RSA is 2048 bits which is 256 bytes;
    889                 // thus clearly its encoding will be at least 256 which is greater than
    890                 // all of the non-ML-DSA-* values and less than the ML-DSA-* values.
    891                 // The maximum modulus we support for RSA is 16K bits which is 2048 bytes and the maximum
    892                 // exponent we support for RSA is 4 bytes which is hundreds of bytes less than 2614
    893                 // (i.e., the length of a DER-encoded ML-DSAS-87 public key).
    894                 ED25519_LEN => Ed25519PubKey::from_der(der).map(Self::Ed25519),
    895                 P256_LEN => UncompressedP256PubKey::from_der(der).map(Self::P256),
    896                 P384_LEN => UncompressedP384PubKey::from_der(der).map(Self::P384),
    897                 MLDSA44_LEN => {
    898                     // `ML_DSA_OID_LEN_IDX < MLDSA44_LEN = der.len()` so indexing
    899                     // won't `panic`.
    900                     if der[ML_DSA_OID_LEN_IDX] == ML_DSA_OID_LEN {
    901                         MlDsa44PubKey::from_der(der).map(Self::MlDsa44)
    902                     } else {
    903                         RsaPubKey::from_der(der).map(Self::Rsa)
    904                     }
    905                 }
    906                 MLDSA65_LEN => {
    907                     // `ML_DSA_OID_LEN_IDX < MLDSA65_LEN = der.len()` so indexing
    908                     // won't `panic`.
    909                     if der[ML_DSA_OID_LEN_IDX] == ML_DSA_OID_LEN {
    910                         MlDsa65PubKey::from_der(der).map(Self::MlDsa65)
    911                     } else {
    912                         RsaPubKey::from_der(der).map(Self::Rsa)
    913                     }
    914                 }
    915                 MLDSA87_LEN => MlDsa87PubKey::from_der(der).map(Self::MlDsa87),
    916                 _ => RsaPubKey::from_der(der).map(Self::Rsa),
    917             }
    918         }
    919     }
    920 }
    921 /// Helper type returned from [`AuthenticatorAttestationVisitor::visit_map`].
    922 ///
    923 /// The purpose of this type is to hopefully avoid re-parsing the raw attestation object multiple times. In
    924 /// particular [`Registration`] and [`super::ser_relaxed::RegistrationRelaxed`] will attempt to validate `id` is the
    925 /// same as the [`CredentialId`] within the attestation object.
    926 pub(super) struct AuthAttest {
    927     /// The data we care about.
    928     pub attest: AuthenticatorAttestation,
    929     /// [`CredentialId`] information. This is `None` iff `authenticatorData`, `publicKey`, and
    930     /// `publicKeyAlgorithm` do not exist and we are performing a `RELAXED` parsing. When `Some`, the first
    931     /// `usize` is the starting index of `CredentialId` within the attestation object; and the second `usize` is
    932     /// 1 past the last index of `CredentialId`.
    933     pub cred_info: Option<(usize, usize)>,
    934 }
    935 /// Fields in `AuthenticatorAttestationResponseJSON`.
    936 enum AttestField<const IGNORE_UNKNOWN: bool> {
    937     /// `clientDataJSON`.
    938     ClientDataJson,
    939     /// `attestationObject`.
    940     AttestationObject,
    941     /// `authenticatorData`.
    942     AuthenticatorData,
    943     /// `transports`.
    944     Transports,
    945     /// `publicKey`.
    946     PublicKey,
    947     /// `publicKeyAlgorithm`.
    948     PublicKeyAlgorithm,
    949     /// Unknown fields.
    950     Other,
    951 }
    952 impl<'e, const I: bool> Deserialize<'e> for AttestField<I> {
    953     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    954     where
    955         D: Deserializer<'e>,
    956     {
    957         /// `Visitor` for `AttestField`.
    958         struct AttestFieldVisitor<const IGNORE_UNKNOWN: bool>;
    959         impl<const IG: bool> Visitor<'_> for AttestFieldVisitor<IG> {
    960             type Value = AttestField<IG>;
    961             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
    962                 write!(
    963                     formatter,
    964                     "'{CLIENT_DATA_JSON}', '{ATTESTATION_OBJECT}', '{AUTHENTICATOR_DATA}', '{TRANSPORTS}', '{PUBLIC_KEY}', or '{PUBLIC_KEY_ALGORITHM}'"
    965                 )
    966             }
    967             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    968             where
    969                 E: Error,
    970             {
    971                 match v {
    972                     CLIENT_DATA_JSON => Ok(AttestField::ClientDataJson),
    973                     ATTESTATION_OBJECT => Ok(AttestField::AttestationObject),
    974                     AUTHENTICATOR_DATA => Ok(AttestField::AuthenticatorData),
    975                     TRANSPORTS => Ok(AttestField::Transports),
    976                     PUBLIC_KEY => Ok(AttestField::PublicKey),
    977                     PUBLIC_KEY_ALGORITHM => Ok(AttestField::PublicKeyAlgorithm),
    978                     _ => {
    979                         if IG {
    980                             Ok(AttestField::Other)
    981                         } else {
    982                             Err(E::unknown_field(v, AUTH_ATTEST_FIELDS))
    983                         }
    984                     }
    985                 }
    986             }
    987         }
    988         deserializer.deserialize_identifier(AttestFieldVisitor::<I>)
    989     }
    990 }
    991 /// Attestation object. We use this instead of `Base64DecodedVal` since we want to manually
    992 /// allocate the `Vec` in order to avoid re-allocation. Internally `AuthenticatorAttestation::new`
    993 /// appends the SHA-256 hash to the passed attestation object `Vec` to avoid temporarily allocating
    994 /// a `Vec` that contains the attestation object and hash for signature verification. Calling code
    995 /// can avoid any reallocation that would occur when the capacity is not large enough by ensuring the
    996 /// passed `Vec` has at least 32 bytes of available capacity.
    997 pub(super) struct AttObj(pub Vec<u8>);
    998 impl<'e> Deserialize<'e> for AttObj {
    999     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
   1000     where
   1001         D: Deserializer<'e>,
   1002     {
   1003         /// `Visitor` for `AttObj`.
   1004         struct AttObjVisitor;
   1005         impl Visitor<'_> for AttObjVisitor {
   1006             type Value = AttObj;
   1007             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
   1008                 formatter.write_str("base64url-encoded attestation object")
   1009             }
   1010             #[expect(
   1011                 clippy::arithmetic_side_effects,
   1012                 reason = "comment justifies their correctness"
   1013             )]
   1014             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
   1015             where
   1016                 E: Error,
   1017             {
   1018                 base64url_nopad::decode_len(v.len())
   1019                     .ok_or_else(|| E::invalid_value(Unexpected::Str(v), &"base64url-encoded value"))
   1020                     .and_then(|len| {
   1021                         // The decoded length is 3/4 of the encoded length, so overflow could only occur
   1022                         // if usize::MAX / 4 < 32 => usize::MAX < 128 < u8::MAX; thus overflow is not
   1023                         // possible. We add 32 since the SHA-256 hash of `clientDataJSON` will be added to
   1024                         // the raw attestation object by `AuthenticatorAttestation::new`.
   1025                         let mut att_obj = vec![0; len + Sha256::output_size()];
   1026                         att_obj.truncate(len);
   1027                         base64url_nopad::decode_buffer_exact(v.as_bytes(), &mut att_obj)
   1028                             .map_err(E::custom)
   1029                             .map(|()| AttObj(att_obj))
   1030                     })
   1031             }
   1032         }
   1033         deserializer.deserialize_str(AttObjVisitor)
   1034     }
   1035 }
   1036 /// `Visitor` for `AuthenticatorAttestation`.
   1037 ///
   1038 /// Unknown fields are ignored and only `clientDataJSON` and `attestationObject` are required iff `RELAXED`.
   1039 pub(super) struct AuthenticatorAttestationVisitor<const RELAXED: bool>;
   1040 impl<'d, const R: bool> Visitor<'d> for AuthenticatorAttestationVisitor<R> {
   1041     type Value = AuthAttest;
   1042     fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
   1043         formatter.write_str("AuthenticatorAttestation")
   1044     }
   1045     #[expect(clippy::too_many_lines, reason = "find it easier to reason about")]
   1046     #[expect(
   1047         clippy::arithmetic_side_effects,
   1048         clippy::indexing_slicing,
   1049         reason = "comments justify their correctness"
   1050     )]
   1051     fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
   1052     where
   1053         A: MapAccess<'d>,
   1054     {
   1055         use spki::SubjectPublicKeyInfo as _;
   1056         let mut client_data = None;
   1057         let mut attest = None;
   1058         let mut auth = None;
   1059         let mut pub_key = None;
   1060         let mut key_alg = None;
   1061         let mut trans = None;
   1062         while let Some(key) = map.next_key::<AttestField<R>>()? {
   1063             match key {
   1064                 AttestField::ClientDataJson => {
   1065                     if client_data.is_some() {
   1066                         return Err(Error::duplicate_field(CLIENT_DATA_JSON));
   1067                     }
   1068                     client_data = map
   1069                         .next_value::<Base64DecodedVal>()
   1070                         .map(|c_data| Some(c_data.0))?;
   1071                 }
   1072                 AttestField::AttestationObject => {
   1073                     if attest.is_some() {
   1074                         return Err(Error::duplicate_field(ATTESTATION_OBJECT));
   1075                     }
   1076                     attest = map.next_value::<AttObj>().map(|att_obj| Some(att_obj.0))?;
   1077                 }
   1078                 AttestField::AuthenticatorData => {
   1079                     if auth.is_some() {
   1080                         return Err(Error::duplicate_field(AUTHENTICATOR_DATA));
   1081                     }
   1082                     auth = map.next_value::<Option<Base64DecodedVal>>().map(Some)?;
   1083                 }
   1084                 AttestField::Transports => {
   1085                     if trans.is_some() {
   1086                         return Err(Error::duplicate_field(TRANSPORTS));
   1087                     }
   1088                     trans = map.next_value::<Option<_>>().map(Some)?;
   1089                 }
   1090                 AttestField::PublicKey => {
   1091                     if pub_key.is_some() {
   1092                         return Err(Error::duplicate_field(PUBLIC_KEY));
   1093                     }
   1094                     pub_key = map.next_value::<Option<Base64DecodedVal>>().map(Some)?;
   1095                 }
   1096                 AttestField::PublicKeyAlgorithm => {
   1097                     if key_alg.is_some() {
   1098                         return Err(Error::duplicate_field(PUBLIC_KEY_ALGORITHM));
   1099                     }
   1100                     key_alg = map
   1101                         .next_value::<Option<CoseAlgorithmIdentifier>>()
   1102                         .map(Some)?;
   1103                 }
   1104                 AttestField::Other => map.next_value::<IgnoredAny>().map(|_| ())?,
   1105             }
   1106         }
   1107         // Note the order of this matters from a performance perspective. In particular `auth` must be evaluated
   1108         // before `pub_key` which must be evaluated before `key_alg` as this allows us to parse the attestation
   1109         // object at most once and allow us to prioritize parsing `authenticatorData` over the attestation object.
   1110         client_data.ok_or_else(|| Error::missing_field(CLIENT_DATA_JSON)).and_then(|client_data_json| attest.ok_or_else(|| Error::missing_field(ATTESTATION_OBJECT)).and_then(|attestation_object| {
   1111             trans.ok_or(false).and_then(|opt_trans| opt_trans.ok_or(true)).or_else(
   1112                 |flag| {
   1113                     if R {
   1114                         Ok(AuthTransports::new())
   1115                     } else if flag {
   1116                         Err(Error::invalid_type(Unexpected::Other("null"), &format!("{TRANSPORTS} to be a sequence of AuthenticatorTransports").as_str()))
   1117                     } else {
   1118                         Err(Error::missing_field(TRANSPORTS))
   1119                     }
   1120                 },
   1121             ).and_then(|transports| {
   1122                 auth.ok_or(false).and_then(|opt_auth| opt_auth.ok_or(true)).as_ref().map_or_else(
   1123                     |flag| {
   1124                         if R {
   1125                             Ok(None)
   1126                         } else if *flag {
   1127                             Err(Error::invalid_type(Unexpected::Other("null"), &format!("{AUTHENTICATOR_DATA} to be a base64url-encoded AuthenticatorData").as_str()))
   1128                         } else {
   1129                             Err(Error::missing_field(AUTHENTICATOR_DATA))
   1130                         }
   1131                     },
   1132                     |a_data| {
   1133                         if a_data.0.len() > 37 {
   1134                             // The last portion of attestation object is always authenticator data.
   1135                             attestation_object.len().checked_sub(a_data.0.len()).ok_or_else(|| Error::invalid_value(Unexpected::Bytes(a_data.0.as_slice()), &format!("authenticator data to match the authenticator data portion of attestation object: {attestation_object:?}").as_str())).and_then(|idx| {
   1136                                 // Indexing is fine; otherwise the above check would have returned `None`.
   1137                                 if *a_data.0 == attestation_object[idx..] {
   1138                                     // We know `a_data.len() > 37`; thus indexing is fine.
   1139                                     // We start at 37 since that is the beginning of `attestedCredentialData`.
   1140                                     // Recall the first 32 bytes are `rpIdHash`, then a 1 byte `flags`, then a
   1141                                     // 4-byte big-endian integer `signCount`.
   1142                                     // The starting index of `credentialId` is 18 within `attestedCredentialData`.
   1143                                     // Recall the first 16 bytes are `aaguid`, then a 2-byte big-endian integer
   1144                                     // `credentialIdLength`. Consequently the starting index within
   1145                                     // `attestation_object` is `idx + 37 + 18` = `idx + 55`. Overflow cannot occur
   1146                                     // since we successfully parsed `AttestedCredentialData`.
   1147                                     AttestedCredentialData::from_cbor(&a_data.0[37..]).map_err(Error::custom).map(|success| Some((success.value, idx + 55)))
   1148                                 } else {
   1149                                     Err(Error::invalid_value(Unexpected::Bytes(a_data.0.as_slice()), &format!("authenticator data to match the authenticator data portion of attestation object: {:?}", &attestation_object[idx..]).as_str()))
   1150                                 }
   1151                             })
   1152                         } else {
   1153                             Err(Error::invalid_value(Unexpected::Bytes(a_data.0.as_slice()), &"authenticator data to be long enough to contain attested credential data"))
   1154                         }
   1155                     }
   1156                 ).and_then(|attested_info| {
   1157                     pub_key.ok_or(false).and_then(|opt_key| opt_key.ok_or(true)).map_or_else(
   1158                         |flag| {
   1159                             if R {
   1160                                 attested_info.as_ref().map_or(Ok(None), |&(ref attested_data, cred_id_start)| Ok(Some((match attested_data.credential_public_key {
   1161                                     UncompressedPubKey::MlDsa87(_) => CoseAlgorithmIdentifier::Mldsa87,
   1162                                     UncompressedPubKey::MlDsa65(_) => CoseAlgorithmIdentifier::Mldsa65,
   1163                                     UncompressedPubKey::MlDsa44(_) => CoseAlgorithmIdentifier::Mldsa44,
   1164                                     UncompressedPubKey::Ed25519(_) => CoseAlgorithmIdentifier::Eddsa,
   1165                                     UncompressedPubKey::P256(_) => CoseAlgorithmIdentifier::Es256,
   1166                                     UncompressedPubKey::P384(_) => CoseAlgorithmIdentifier::Es384,
   1167                                     UncompressedPubKey::Rsa(_) => CoseAlgorithmIdentifier::Rs256,
   1168                                     // Overflow won't occur since this is correct as
   1169                                     // `AttestedCredentialData::from_cbor` would have erred if not.
   1170                                 }, cred_id_start, cred_id_start + attested_data.credential_id.0.len()))))
   1171                             } else {
   1172                                 // `publicKey` is only allowed to not exist when `CoseAlgorithmIdentifier::Eddsa`,
   1173                                 // `CoseAlgorithmIdentifier::Es256`, or `CoseAlgorithmIdentifier::Rs256` is not
   1174                                 // used.
   1175                                 attested_info.as_ref().map_or_else(
   1176                                     || AttestationObject::parse_data(attestation_object.as_slice()).map_err(Error::custom).and_then(|(att_obj, auth_idx)| {
   1177                                         match att_obj.auth_data.attested_credential_data.credential_public_key {
   1178                                             UncompressedPubKey::MlDsa87(_) => {
   1179                                                 // This won't overflow since `AttestationObject::parse_data` succeeded and `auth_idx`
   1180                                                 // is the start of the raw authenticator data which itself contains the raw Credential ID.
   1181                                                 Ok(Some((CoseAlgorithmIdentifier::Mldsa87, auth_idx,  auth_idx + att_obj.auth_data.attested_credential_data.credential_id.0.len())))
   1182                                             }
   1183                                             UncompressedPubKey::MlDsa65(_) => {
   1184                                                 // This won't overflow since `AttestationObject::parse_data` succeeded and `auth_idx`
   1185                                                 // is the start of the raw authenticator data which itself contains the raw Credential ID.
   1186                                                 Ok(Some((CoseAlgorithmIdentifier::Mldsa65, auth_idx,  auth_idx + att_obj.auth_data.attested_credential_data.credential_id.0.len())))
   1187                                             }
   1188                                             UncompressedPubKey::MlDsa44(_) => {
   1189                                                 // This won't overflow since `AttestationObject::parse_data` succeeded and `auth_idx`
   1190                                                 // is the start of the raw authenticator data which itself contains the raw Credential ID.
   1191                                                 Ok(Some((CoseAlgorithmIdentifier::Mldsa44, auth_idx,  auth_idx + att_obj.auth_data.attested_credential_data.credential_id.0.len())))
   1192                                             }
   1193                                             UncompressedPubKey::P384(_) => {
   1194                                                 // This won't overflow since `AttestationObject::parse_data` succeeded and `auth_idx`
   1195                                                 // is the start of the raw authenticator data which itself contains the raw Credential ID.
   1196                                                 Ok(Some((CoseAlgorithmIdentifier::Es384, auth_idx,  auth_idx + att_obj.auth_data.attested_credential_data.credential_id.0.len())))
   1197                                             }
   1198                                             UncompressedPubKey::Ed25519(_) | UncompressedPubKey::P256(_) | UncompressedPubKey::Rsa(_) => Err(Error::missing_field(PUBLIC_KEY)),
   1199                                         }
   1200                                     }),
   1201                                     |&(ref attested_data, cred_id_start)| {
   1202                                         match attested_data.credential_public_key {
   1203                                             UncompressedPubKey::MlDsa87(_) => {
   1204                                                 // Overflow won't occur since this is correct. This is correct since we successfully parsed
   1205                                                 // `AttestedCredentialData` and calculated `cred_id_start` from it.
   1206                                                 Ok(Some((CoseAlgorithmIdentifier::Mldsa87, cred_id_start, cred_id_start + attested_data.credential_id.0.len())))
   1207                                             }
   1208                                             UncompressedPubKey::MlDsa65(_) => {
   1209                                                 // Overflow won't occur since this is correct. This is correct since we successfully parsed
   1210                                                 // `AttestedCredentialData` and calculated `cred_id_start` from it.
   1211                                                 Ok(Some((CoseAlgorithmIdentifier::Mldsa65, cred_id_start, cred_id_start + attested_data.credential_id.0.len())))
   1212                                             }
   1213                                             UncompressedPubKey::MlDsa44(_) => {
   1214                                                 // Overflow won't occur since this is correct. This is correct since we successfully parsed
   1215                                                 // `AttestedCredentialData` and calculated `cred_id_start` from it.
   1216                                                 Ok(Some((CoseAlgorithmIdentifier::Mldsa44, cred_id_start, cred_id_start + attested_data.credential_id.0.len())))
   1217                                             }
   1218                                             UncompressedPubKey::P384(_) => {
   1219                                                 // Overflow won't occur since this is correct. This is correct since we successfully parsed
   1220                                                 // `AttestedCredentialData` and calculated `cred_id_start` from it.
   1221                                                 Ok(Some((CoseAlgorithmIdentifier::Es384, cred_id_start, cred_id_start + attested_data.credential_id.0.len())))
   1222                                             }
   1223                                             UncompressedPubKey::Ed25519(_) | UncompressedPubKey::P256(_) | UncompressedPubKey::Rsa(_) => if flag { Err(Error::invalid_type(Unexpected::Other("null"), &format!("{PUBLIC_KEY} to be a base64url-encoded DER-encoded SubjectPublicKeyInfo").as_str())) } else { Err(Error::missing_field(PUBLIC_KEY)) },
   1224                                         }
   1225                                     }
   1226                                 )
   1227                             }
   1228                         },
   1229                         |der| {
   1230                             UncompressedPubKey::from_der(der.0.as_slice()).map_err(Error::custom).and_then(|key| {
   1231                                 attested_info.as_ref().map_or_else(
   1232                                     || AttestationObject::parse_data(attestation_object.as_slice()).map_err(Error::custom).and_then(|(att_obj, auth_idx)| {
   1233                                         if key == att_obj.auth_data.attested_credential_data.credential_public_key {
   1234                                             let alg = match att_obj.auth_data.attested_credential_data.credential_public_key {
   1235                                                 UncompressedPubKey::MlDsa87(_) => CoseAlgorithmIdentifier::Mldsa87,
   1236                                                 UncompressedPubKey::MlDsa65(_) => CoseAlgorithmIdentifier::Mldsa65,
   1237                                                 UncompressedPubKey::MlDsa44(_) => CoseAlgorithmIdentifier::Mldsa44,
   1238                                                 UncompressedPubKey::Ed25519(_) => CoseAlgorithmIdentifier::Eddsa,
   1239                                                 UncompressedPubKey::P256(_) => CoseAlgorithmIdentifier::Es256,
   1240                                                 UncompressedPubKey::P384(_) => CoseAlgorithmIdentifier::Es384,
   1241                                                 UncompressedPubKey::Rsa(_) => CoseAlgorithmIdentifier::Rs256,
   1242                                             };
   1243                                             // This won't overflow since `AttestationObject::parse_data` succeeded and `auth_idx`
   1244                                             // is the start of the raw authenticator data which itself contains the raw Credential ID.
   1245                                             Ok(Some((alg, auth_idx, auth_idx+ att_obj.auth_data.attested_credential_data.credential_id.0.len())))
   1246                                         } else {
   1247                                             Err(Error::invalid_value(Unexpected::Bytes(der.0.as_slice()), &format!("DER-encoded public key to match the public key within the attestation object: {:?}", att_obj.auth_data.attested_credential_data.credential_public_key).as_str()))
   1248                                         }
   1249                                     }),
   1250                                     |&(ref attested_data, cred_id_start)| {
   1251                                         if key == attested_data.credential_public_key {
   1252                                             let alg = match attested_data.credential_public_key {
   1253                                                 UncompressedPubKey::MlDsa87(_) => CoseAlgorithmIdentifier::Mldsa87,
   1254                                                 UncompressedPubKey::MlDsa65(_) => CoseAlgorithmIdentifier::Mldsa65,
   1255                                                 UncompressedPubKey::MlDsa44(_) => CoseAlgorithmIdentifier::Mldsa44,
   1256                                                 UncompressedPubKey::Ed25519(_) => CoseAlgorithmIdentifier::Eddsa,
   1257                                                 UncompressedPubKey::P256(_) => CoseAlgorithmIdentifier::Es256,
   1258                                                 UncompressedPubKey::P384(_) => CoseAlgorithmIdentifier::Es384,
   1259                                                 UncompressedPubKey::Rsa(_) => CoseAlgorithmIdentifier::Rs256,
   1260                                             };
   1261                                             // Overflow won't occur since this is correct. This is correct since we successfully parsed
   1262                                             // `AttestedCredentialData` and calculated `cred_id_start` from it.
   1263                                             Ok(Some((alg, cred_id_start, cred_id_start + attested_data.credential_id.0.len())))
   1264                                         } else {
   1265                                             Err(Error::invalid_value(Unexpected::Bytes(der.0.as_slice()), &format!("DER-encoded public key to match the public key within the attestation object: {:?}", attested_data.credential_public_key).as_str()))
   1266                                         }
   1267                                     }
   1268                                 )
   1269                             })
   1270                         }
   1271                     ).and_then(|cred_key_alg_cred_info| {
   1272                         key_alg.ok_or(false).and_then(|opt_alg| opt_alg.ok_or(true)).map_or_else(
   1273                             |flag| {
   1274                                 if R {
   1275                                     Ok(cred_key_alg_cred_info.map(|info| (info.1, info.2)))
   1276                                 } else if flag {
   1277                                     Err(Error::invalid_type(Unexpected::Other("null"), &format!("{PUBLIC_KEY_ALGORITHM} to be a base64url-encoded DER-encoded SubjectPublicKeyInfo").as_str()))
   1278                                 } else {
   1279                                     Err(Error::missing_field(PUBLIC_KEY_ALGORITHM))
   1280                                 }
   1281                             },
   1282                             |alg| {
   1283                                 cred_key_alg_cred_info.map_or_else(
   1284                                     || AttestationObject::parse_data(attestation_object.as_slice()).map_err(Error::custom).and_then(|(att_obj, auth_idx)| {
   1285                                         let att_obj_alg = match att_obj.auth_data.attested_credential_data.credential_public_key {
   1286                                             UncompressedPubKey::MlDsa87(_) => CoseAlgorithmIdentifier::Mldsa87,
   1287                                             UncompressedPubKey::MlDsa65(_) => CoseAlgorithmIdentifier::Mldsa65,
   1288                                             UncompressedPubKey::MlDsa44(_) => CoseAlgorithmIdentifier::Mldsa44,
   1289                                             UncompressedPubKey::Ed25519(_) => CoseAlgorithmIdentifier::Eddsa,
   1290                                             UncompressedPubKey::P256(_) => CoseAlgorithmIdentifier::Es256,
   1291                                             UncompressedPubKey::P384(_) => CoseAlgorithmIdentifier::Es384,
   1292                                             UncompressedPubKey::Rsa(_) => CoseAlgorithmIdentifier::Rs256,
   1293                                         };
   1294                                         if alg == att_obj_alg {
   1295                                             // This won't overflow since `AttestationObject::parse_data` succeeded and `auth_idx`
   1296                                             // is the start of the raw authenticator data which itself contains the raw Credential ID.
   1297                                             Ok(Some((auth_idx, auth_idx + att_obj.auth_data.attested_credential_data.credential_id.0.len())))
   1298                                         } else {
   1299                                             Err(Error::invalid_value(Unexpected::Other(format!("{alg:?}").as_str()), &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {att_obj_alg:?}").as_str()))
   1300                                         }
   1301                                     }),
   1302                                     |(a, start, last)| if alg == a {
   1303                                         Ok(Some((start, last)))
   1304                                     } else {
   1305                                         Err(Error::invalid_value(Unexpected::Other(format!("{alg:?}").as_str()), &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {a:?}").as_str()))
   1306                                     },
   1307                                 )
   1308                             }
   1309                         ).map(|cred_info| AuthAttest{ attest: AuthenticatorAttestation::new(client_data_json, attestation_object, transports), cred_info, })
   1310                     })
   1311                 })
   1312             })
   1313         }))
   1314     }
   1315 }
   1316 /// `"clientDataJSON"`
   1317 const CLIENT_DATA_JSON: &str = "clientDataJSON";
   1318 /// `"attestationObject"`
   1319 const ATTESTATION_OBJECT: &str = "attestationObject";
   1320 /// `"authenticatorData"`
   1321 const AUTHENTICATOR_DATA: &str = "authenticatorData";
   1322 /// `"transports"`
   1323 const TRANSPORTS: &str = "transports";
   1324 /// `"publicKey"`
   1325 const PUBLIC_KEY: &str = "publicKey";
   1326 /// `"publicKeyAlgorithm"`
   1327 const PUBLIC_KEY_ALGORITHM: &str = "publicKeyAlgorithm";
   1328 /// Fields in `AuthenticatorAttestationResponseJSON`.
   1329 pub(super) const AUTH_ATTEST_FIELDS: &[&str; 6] = &[
   1330     CLIENT_DATA_JSON,
   1331     ATTESTATION_OBJECT,
   1332     AUTHENTICATOR_DATA,
   1333     TRANSPORTS,
   1334     PUBLIC_KEY,
   1335     PUBLIC_KEY_ALGORITHM,
   1336 ];
   1337 impl<'de> Deserialize<'de> for AuthAttest {
   1338     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
   1339     where
   1340         D: Deserializer<'de>,
   1341     {
   1342         deserializer.deserialize_struct(
   1343             "AuthenticatorAttestation",
   1344             AUTH_ATTEST_FIELDS,
   1345             AuthenticatorAttestationVisitor::<false>,
   1346         )
   1347     }
   1348 }
   1349 impl<'de> Deserialize<'de> for AuthenticatorAttestation {
   1350     /// Deserializes a `struct` based on
   1351     /// [`AuthenticatorAttestationResponseJSON`](https://www.w3.org/TR/webauthn-3/#dictdef-authenticatorattestationresponsejson).
   1352     ///
   1353     /// Note unknown keys and duplicate keys are forbidden;
   1354     /// [`clientDataJSON`](https://www.w3.org/TR/webauthn-3/#dom-authenticatorattestationresponsejson-clientdatajson),
   1355     /// [`authenticatorData`](https://www.w3.org/TR/webauthn-3/#dom-authenticatorattestationresponsejson-authenticatordata),
   1356     /// [`publicKey`](https://www.w3.org/TR/webauthn-3/#dom-authenticatorattestationresponsejson-publickey)
   1357     /// and
   1358     /// [`attestationObject`](https://www.w3.org/TR/webauthn-3/#dom-authenticatorattestationresponsejson-attestationobject)
   1359     /// are base64url-decoded;
   1360     /// [`transports`](https://www.w3.org/TR/webauthn-3/#dom-authenticatorattestationresponsejson-transports)
   1361     /// is deserialized via [`AuthTransports::deserialize`]; the decoded `publicKey` is parsed according to the
   1362     /// applicable DER-encoded ASN.1 `SubjectPublicKeyInfo` schema;
   1363     /// [`publicKeyAlgorithm`](https://www.w3.org/TR/webauthn-3/#dom-authenticatorattestationresponsejson-publickeyalgorithm)
   1364     /// is deserialized according to
   1365     /// [`CoseAlgorithmIdentifier`](https://www.w3.org/TR/webauthn-3/#typedefdef-cosealgorithmidentifier); all `required`
   1366     /// fields in the `AuthenticatorAttestationResponseJSON` Web IDL `dictionary` exist (and must not be `null`); `publicKey`
   1367     /// exists when Ed25519, P-256 with SHA-256, or RSASSA-PKCS1-v1_5 with SHA-256 is used (and must not be `null`)
   1368     /// [per WebAuthn](https://www.w3.org/TR/webauthn-3/#sctn-public-key-easy); the `publicKeyAlgorithm` aligns
   1369     /// with
   1370     /// [`credentialPublicKey`](https://www.w3.org/TR/webauthn-3/#authdata-attestedcredentialdata-credentialpublickey)
   1371     /// within
   1372     /// [`attestedCredentialData`](https://www.w3.org/TR/webauthn-3/#authdata-attestedcredentialdata) within the
   1373     /// decoded `authenticatorData`; the decoded `publicKey` is the same as `credentialPublicKey` within
   1374     /// `attestedCredentialData` within the decoded `authenticatorData`; and the decoded `authenticatorData` is the
   1375     /// same as [`authData`](https://www.w3.org/TR/webauthn-3/#attestation-object) within the decoded
   1376     /// `attestationObject`.
   1377     #[inline]
   1378     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
   1379     where
   1380         D: Deserializer<'de>,
   1381     {
   1382         AuthAttest::deserialize(deserializer).map(|val| val.attest)
   1383     }
   1384 }
   1385 /// `Visitor` for `CredentialPropertiesOutput`.
   1386 ///
   1387 /// Unknown fields are ignored iff `RELAXED`.
   1388 pub(super) struct CredentialPropertiesOutputVisitor<const RELAXED: bool>;
   1389 impl<'d, const R: bool> Visitor<'d> for CredentialPropertiesOutputVisitor<R> {
   1390     type Value = CredentialPropertiesOutput;
   1391     fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
   1392         formatter.write_str("CredentialPropertiesOutput")
   1393     }
   1394     fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
   1395     where
   1396         A: MapAccess<'d>,
   1397     {
   1398         /// Allowed fields.
   1399         enum Field<const IGNORE_UNKNOWN: bool> {
   1400             /// `rk` field.
   1401             Rk,
   1402             /// Unknown field.
   1403             Other,
   1404         }
   1405         impl<'e, const I: bool> Deserialize<'e> for Field<I> {
   1406             fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
   1407             where
   1408                 D: Deserializer<'e>,
   1409             {
   1410                 /// `Visitor` for `Field`.
   1411                 ///
   1412                 /// Unknown fields are ignored iff `IGNORE_UNKNOWN`.
   1413                 struct FieldVisitor<const IGNORE_UNKNOWN: bool>;
   1414                 impl<const IG: bool> Visitor<'_> for FieldVisitor<IG> {
   1415                     type Value = Field<IG>;
   1416                     fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
   1417                         write!(formatter, "'{RK}'")
   1418                     }
   1419                     fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
   1420                     where
   1421                         E: Error,
   1422                     {
   1423                         match v {
   1424                             RK => Ok(Field::Rk),
   1425                             _ => {
   1426                                 if IG {
   1427                                     Ok(Field::Other)
   1428                                 } else {
   1429                                     Err(E::unknown_field(v, PROPS_FIELDS))
   1430                                 }
   1431                             }
   1432                         }
   1433                     }
   1434                 }
   1435                 deserializer.deserialize_identifier(FieldVisitor)
   1436             }
   1437         }
   1438         let mut rk = None;
   1439         while let Some(key) = map.next_key::<Field<R>>()? {
   1440             match key {
   1441                 Field::Rk => {
   1442                     if rk.is_some() {
   1443                         return Err(Error::duplicate_field(RK));
   1444                     }
   1445                     rk = map.next_value().map(Some)?;
   1446                 }
   1447                 Field::Other => map.next_value::<IgnoredAny>().map(|_| ())?,
   1448             }
   1449         }
   1450         Ok(CredentialPropertiesOutput { rk: rk.flatten() })
   1451     }
   1452 }
   1453 /// `"rk"`
   1454 const RK: &str = "rk";
   1455 /// `CredentialPropertiesOutput` fields.
   1456 pub(super) const PROPS_FIELDS: &[&str; 1] = &[RK];
   1457 impl<'de> Deserialize<'de> for CredentialPropertiesOutput {
   1458     /// Deserializes a `struct` based on
   1459     /// [`CredentialPropertiesOutput`](https://www.w3.org/TR/webauthn-3/#dictdef-credentialpropertiesoutput).
   1460     ///
   1461     /// Note unknown and duplicate keys are forbidden.
   1462     #[inline]
   1463     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
   1464     where
   1465         D: Deserializer<'de>,
   1466     {
   1467         deserializer.deserialize_struct(
   1468             "CredentialPropertiesOutput",
   1469             PROPS_FIELDS,
   1470             CredentialPropertiesOutputVisitor::<false>,
   1471         )
   1472     }
   1473 }
   1474 impl<'de> Deserialize<'de> for AuthenticationExtensionsPrfOutputs {
   1475     /// Deserializes a `struct` based on
   1476     /// [`AuthenticationExtensionsPRFOutputsJSON`](https://www.w3.org/TR/webauthn-3/#dictdef-authenticationextensionsprfoutputsjson).
   1477     ///
   1478     /// Note unknown and duplicate keys are forbidden;
   1479     /// [`enabled`](https://www.w3.org/TR/webauthn-3/#dom-authenticationextensionsprfoutputs-enabled)
   1480     /// must exist (and not be `null`); and
   1481     /// [`results`](https://www.w3.org/TR/webauthn-3/#dom-authenticationextensionsprfoutputs-results) must not exist,
   1482     /// be `null`, or be an
   1483     /// [`AuthenticationExtensionsPRFValues`](https://www.w3.org/TR/webauthn-3/#dictdef-authenticationextensionsprfvalues)
   1484     /// with no unknown or duplicate keys,
   1485     /// [`first`](https://www.w3.org/TR/webauthn-3/#dom-authenticationextensionsprfvalues-first) must exist but be
   1486     /// `null`, and
   1487     /// [`second`](https://www.w3.org/TR/webauthn-3/#dom-authenticationextensionsprfvalues-second) can exist but
   1488     /// must be `null` if so.
   1489     #[inline]
   1490     #[expect(clippy::unreachable, reason = "we want to crash when there is a bug")]
   1491     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
   1492     where
   1493         D: Deserializer<'de>,
   1494     {
   1495         AuthenticationExtensionsPrfOutputsHelper::<false, true, AuthenticationExtensionsPrfValues>::deserialize(deserializer).map(|val| Self {
   1496             enabled: val.0.unwrap_or_else(|| {
   1497                 unreachable!(
   1498                     "there is a bug in AuthenticationExtensionsPrfOutputsHelper::deserialize"
   1499                 )
   1500             }),
   1501         })
   1502     }
   1503 }
   1504 /// `Visitor` for `ClientExtensionsOutputs`.
   1505 ///
   1506 /// Unknown fields are ignored iff `RELAXED`.
   1507 pub(super) struct ClientExtensionsOutputsVisitor<const RELAXED: bool, PROPS, PRF>(
   1508     pub PhantomData<fn() -> (PROPS, PRF)>,
   1509 );
   1510 impl<'d, const R: bool, C, P> Visitor<'d> for ClientExtensionsOutputsVisitor<R, C, P>
   1511 where
   1512     C: for<'a> Deserialize<'a> + Into<CredentialPropertiesOutput>,
   1513     P: for<'a> Deserialize<'a> + Into<AuthenticationExtensionsPrfOutputs>,
   1514 {
   1515     type Value = ClientExtensionsOutputs;
   1516     fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
   1517         formatter.write_str("ClientExtensionsOutputs")
   1518     }
   1519     fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
   1520     where
   1521         A: MapAccess<'d>,
   1522     {
   1523         /// Allowed fields.
   1524         enum Field<const IGNORE_UNKNOWN: bool> {
   1525             /// `credProps` field.
   1526             CredProps,
   1527             /// `prf` field.
   1528             Prf,
   1529             /// Unknown field.
   1530             Other,
   1531         }
   1532         impl<'e, const I: bool> Deserialize<'e> for Field<I> {
   1533             fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
   1534             where
   1535                 D: Deserializer<'e>,
   1536             {
   1537                 /// `Visitor` for `Field`.
   1538                 ///
   1539                 /// Unknown fields are ignored iff `IGNORE_UNKNOWN`.
   1540                 struct FieldVisitor<const IGNORE_UNKNOWN: bool>;
   1541                 impl<const IG: bool> Visitor<'_> for FieldVisitor<IG> {
   1542                     type Value = Field<IG>;
   1543                     fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
   1544                         write!(formatter, "'{CRED_PROPS}' or '{PRF}'")
   1545                     }
   1546                     fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
   1547                     where
   1548                         E: Error,
   1549                     {
   1550                         match v {
   1551                             CRED_PROPS => Ok(Field::CredProps),
   1552                             PRF => Ok(Field::Prf),
   1553                             _ => {
   1554                                 if IG {
   1555                                     Ok(Field::Other)
   1556                                 } else {
   1557                                     Err(E::unknown_field(v, EXT_FIELDS))
   1558                                 }
   1559                             }
   1560                         }
   1561                     }
   1562                 }
   1563                 deserializer.deserialize_identifier(FieldVisitor)
   1564             }
   1565         }
   1566         let mut cred_props = None;
   1567         let mut prf = None;
   1568         while let Some(key) = map.next_key::<Field<R>>()? {
   1569             match key {
   1570                 Field::CredProps => {
   1571                     if cred_props.is_some() {
   1572                         return Err(Error::duplicate_field(CRED_PROPS));
   1573                     }
   1574                     cred_props = map.next_value::<Option<C>>().map(Some)?;
   1575                 }
   1576                 Field::Prf => {
   1577                     if prf.is_some() {
   1578                         return Err(Error::duplicate_field(PRF));
   1579                     }
   1580                     prf = map.next_value::<Option<P>>().map(Some)?;
   1581                 }
   1582                 Field::Other => map.next_value::<IgnoredAny>().map(|_| ())?,
   1583             }
   1584         }
   1585         Ok(ClientExtensionsOutputs {
   1586             cred_props: cred_props.flatten().map(Into::into),
   1587             prf: prf.flatten().map(Into::into),
   1588         })
   1589     }
   1590 }
   1591 impl ClientExtensions for ClientExtensionsOutputs {
   1592     fn empty() -> Self {
   1593         Self {
   1594             prf: None,
   1595             cred_props: None,
   1596         }
   1597     }
   1598 }
   1599 /// `"credProps"`
   1600 const CRED_PROPS: &str = "credProps";
   1601 /// `"prf"`
   1602 const PRF: &str = "prf";
   1603 /// `AuthenticationExtensionsClientOutputsJSON` fields.
   1604 pub(super) const EXT_FIELDS: &[&str; 2] = &[CRED_PROPS, PRF];
   1605 impl<'de> Deserialize<'de> for ClientExtensionsOutputs {
   1606     /// Deserializes a `struct` based on
   1607     /// [`AuthenticationExtensionsClientOutputsJSON`](https://www.w3.org/TR/webauthn-3/#dictdef-authenticationextensionsclientoutputsjson).
   1608     ///
   1609     /// Note that unknown and duplicate keys are forbidden;
   1610     /// [`credProps`](https://www.w3.org/TR/webauthn-3/#dom-authenticationextensionsclientoutputs-credprops) is
   1611     /// `null` or deserialized via [`CredentialPropertiesOutput::deserialize`]; and
   1612     /// [`prf`](https://www.w3.org/TR/webauthn-3/#dom-authenticationextensionsclientoutputs-prf) is `null`
   1613     /// or deserialized via [`AuthenticationExtensionsPrfOutputs::deserialize`].
   1614     #[inline]
   1615     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
   1616     where
   1617         D: Deserializer<'de>,
   1618     {
   1619         deserializer.deserialize_struct(
   1620             "ClientExtensionsOutputs",
   1621             EXT_FIELDS,
   1622             ClientExtensionsOutputsVisitor::<
   1623                 false,
   1624                 CredentialPropertiesOutput,
   1625                 AuthenticationExtensionsPrfOutputs,
   1626             >(PhantomData),
   1627         )
   1628     }
   1629 }
   1630 impl<'de> Deserialize<'de> for Registration {
   1631     /// Deserializes a `struct` based on
   1632     /// [`RegistrationResponseJSON`](https://www.w3.org/TR/webauthn-3/#dictdef-registrationresponsejson).
   1633     ///
   1634     /// Note that unknown and duplicate keys are forbidden;
   1635     /// [`id`](https://www.w3.org/TR/webauthn-3/#dom-registrationresponsejson-id) and
   1636     /// [`rawId`](https://www.w3.org/TR/webauthn-3/#dom-registrationresponsejson-rawid) are deserialized
   1637     /// via [`CredentialId::deserialize`];
   1638     /// [`response`](https://www.w3.org/TR/webauthn-3/#dom-registrationresponsejson-response) is deserialized
   1639     /// via [`AuthenticatorAttestation::deserialize`];
   1640     /// [`authenticatorAttachment`](https://www.w3.org/TR/webauthn-3/#dom-registrationresponsejson-authenticatorattachment)
   1641     /// is `null` or deserialized via [`AuthenticatorAttachment::deserialize`];
   1642     /// [`clientExtensionResults`](https://www.w3.org/TR/webauthn-3/#dom-registrationresponsejson-clientextensionresults)
   1643     /// is deserialized via [`ClientExtensionsOutputs::deserialize`]; all `required` fields in the
   1644     /// `RegistrationResponseJSON` Web IDL `dictionary` exist (and are not `null`);
   1645     /// [`type`](https://www.w3.org/TR/webauthn-3/#dom-registrationresponsejson-type) is `"public-key"`;
   1646     /// and the decoded `id`, decoded `rawId`, and
   1647     /// [`credentialId`](https://www.w3.org/TR/webauthn-3/#authdata-attestedcredentialdata-credentialid) within
   1648     /// [`attestedCredentialData`](https://www.w3.org/TR/webauthn-3/#authdata-attestedcredentialdata) within
   1649     /// [`authData`](https://www.w3.org/TR/webauthn-3/#attestation-object) within the decoded
   1650     /// [`attestationObject`](https://www.w3.org/TR/webauthn-3/#dom-authenticatorattestationresponsejson-attestationobject)
   1651     /// are all the same.
   1652     #[expect(clippy::unreachable, reason = "when there is a bug, we want to crash")]
   1653     #[expect(clippy::indexing_slicing, reason = "comment justifies its correctness")]
   1654     #[inline]
   1655     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
   1656     where
   1657         D: Deserializer<'de>,
   1658     {
   1659         PublicKeyCredential::<false, true, AuthAttest, ClientExtensionsOutputs>::deserialize(deserializer).and_then(|cred| {
   1660             let id = cred.id.unwrap_or_else(|| unreachable!("there is a bug in PublicKeyCredential::deserialize"));
   1661             cred.response.cred_info.map_or_else(
   1662                 || AttestationObject::try_from(cred.response.attest.attestation_object()).map_err(Error::custom).and_then(|att_obj| {
   1663                     if id.as_ref() == att_obj.auth_data.attested_credential_data.credential_id.as_ref() {
   1664                         Ok(())
   1665                     } else {
   1666                         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()))
   1667                     }
   1668                 }),
   1669                 // `start` and `last` were calculated based on `cred.response.attest.attestation_object()`
   1670                 // and represent the starting and ending index of the `CredentialId`; therefore this is correct
   1671                 // let alone won't `panic`.
   1672                 |(start, last)| if *id.0 == cred.response.attest.attestation_object()[start..last] {
   1673                     Ok(())
   1674                 } else {
   1675                     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.attest.attestation_object()[start..last]).as_str()))
   1676                 },
   1677             ).map(|()| Self { response: cred.response.attest, authenticator_attachment: cred.authenticator_attachment, client_extension_results: cred.client_extension_results, })
   1678         })
   1679     }
   1680 }
   1681 #[cfg(test)]
   1682 mod tests {
   1683     use super::{
   1684         super::{
   1685             AKP, ALG, AuthenticatorAttachment, EC2, EDDSA, ES256, ES384, Ed25519PubKey, KTY,
   1686             MLDSA44, MLDSA65, MLDSA87, MlDsa44PubKey, MlDsa65PubKey, MlDsa87PubKey, OKP, RSA,
   1687             Registration, RsaPubKey, UncompressedP256PubKey, UncompressedP384PubKey, cbor,
   1688         },
   1689         CoseAlgorithmIdentifier,
   1690         spki::SubjectPublicKeyInfo as _,
   1691     };
   1692     use ed25519_dalek::{VerifyingKey, pkcs8::EncodePublicKey as _};
   1693     use ml_dsa::{MlDsa44, MlDsa65, MlDsa87, VerifyingKey as MlDsaVerKey};
   1694     use p256::{
   1695         PublicKey as P256PubKey, Sec1Point as P256Pt, SecretKey as P256Key,
   1696         elliptic_curve::sec1::{FromSec1Point as _, ToSec1Point as _},
   1697     };
   1698     use p384::{PublicKey as P384PubKey, Sec1Point as P384Pt, SecretKey as P384Key};
   1699     use rsa::{
   1700         BoxedUint, RsaPrivateKey,
   1701         sha2::{Digest as _, Sha256},
   1702         traits::PublicKeyParts as _,
   1703     };
   1704     use serde::de::{Error as _, Unexpected};
   1705     use serde_json::Error;
   1706     #[expect(clippy::unwrap_used, reason = "OK in tests")]
   1707     #[test]
   1708     fn mldsa87_spki() {
   1709         assert!(
   1710             MlDsa87PubKey::from_der(
   1711                 MlDsaVerKey::<MlDsa87>::decode(&[1; 2592].into())
   1712                     .to_public_key_der()
   1713                     .unwrap()
   1714                     .as_bytes()
   1715             )
   1716             .is_ok_and(|k| k.0 == [1; 2592])
   1717         );
   1718     }
   1719     #[expect(clippy::unwrap_used, reason = "OK in tests")]
   1720     #[test]
   1721     fn mldsa65_spki() {
   1722         assert!(
   1723             MlDsa65PubKey::from_der(
   1724                 MlDsaVerKey::<MlDsa65>::decode(&[1; 1952].into())
   1725                     .to_public_key_der()
   1726                     .unwrap()
   1727                     .as_bytes()
   1728             )
   1729             .is_ok_and(|k| k.0 == [1; 1952])
   1730         );
   1731     }
   1732     #[expect(clippy::unwrap_used, reason = "OK in tests")]
   1733     #[test]
   1734     fn mldsa44_spki() {
   1735         assert!(
   1736             MlDsa44PubKey::from_der(
   1737                 MlDsaVerKey::<MlDsa44>::decode(&[1; 1312].into())
   1738                     .to_public_key_der()
   1739                     .unwrap()
   1740                     .as_bytes()
   1741             )
   1742             .is_ok_and(|k| k.0 == [1; 1312])
   1743         );
   1744     }
   1745     #[expect(clippy::unwrap_used, reason = "OK in tests")]
   1746     #[test]
   1747     fn ed25519_spki() {
   1748         assert!(
   1749             Ed25519PubKey::from_der(
   1750                 VerifyingKey::from_bytes(&[1; 32])
   1751                     .unwrap()
   1752                     .to_public_key_der()
   1753                     .unwrap()
   1754                     .as_bytes()
   1755             )
   1756             .is_ok_and(|k| k.0 == [1; 32])
   1757         );
   1758     }
   1759     #[expect(clippy::unwrap_used, reason = "OK in tests")]
   1760     #[test]
   1761     fn p256_spki() {
   1762         let key = P256Key::from_bytes(
   1763             &[
   1764                 137, 133, 36, 206, 163, 47, 255, 5, 76, 144, 163, 141, 40, 109, 108, 240, 246, 115,
   1765                 178, 237, 169, 68, 6, 129, 92, 21, 238, 127, 55, 158, 207, 95,
   1766             ]
   1767             .into(),
   1768         )
   1769         .unwrap()
   1770         .public_key();
   1771         let enc_key = key.to_sec1_point(false);
   1772         assert!(
   1773             UncompressedP256PubKey::from_der(key.to_public_key_der().unwrap().as_bytes())
   1774                 .is_ok_and(|k| *k.0 == **enc_key.x().unwrap() && *k.1 == **enc_key.y().unwrap())
   1775         );
   1776     }
   1777     #[expect(clippy::unwrap_used, reason = "OK in tests")]
   1778     #[test]
   1779     fn p384_spki() {
   1780         let key = P384Key::from_bytes(
   1781             &[
   1782                 158, 99, 156, 49, 190, 211, 85, 167, 28, 2, 80, 57, 31, 22, 17, 38, 85, 78, 232,
   1783                 42, 45, 199, 154, 243, 136, 251, 84, 34, 5, 120, 208, 91, 61, 248, 64, 144, 87, 1,
   1784                 32, 86, 220, 68, 182, 11, 105, 223, 75, 70,
   1785             ]
   1786             .into(),
   1787         )
   1788         .unwrap()
   1789         .public_key();
   1790         let enc_key = key.to_sec1_point(false);
   1791         assert!(
   1792             UncompressedP384PubKey::from_der(key.to_public_key_der().unwrap().as_bytes())
   1793                 .is_ok_and(|k| *k.0 == **enc_key.x().unwrap() && *k.1 == **enc_key.y().unwrap())
   1794         );
   1795     }
   1796     #[expect(clippy::unwrap_used, reason = "OK in tests")]
   1797     #[test]
   1798     fn rsa_spki() {
   1799         let n = [
   1800             111, 183, 124, 133, 38, 167, 70, 148, 44, 50, 30, 60, 121, 14, 38, 37, 96, 114, 107,
   1801             195, 248, 64, 79, 36, 237, 140, 43, 27, 94, 74, 102, 152, 135, 102, 184, 150, 186, 206,
   1802             185, 19, 165, 209, 48, 98, 98, 9, 3, 205, 208, 82, 250, 105, 132, 201, 73, 62, 60, 165,
   1803             100, 128, 153, 9, 41, 118, 66, 95, 236, 214, 73, 135, 197, 68, 184, 10, 27, 116, 204,
   1804             145, 50, 174, 58, 42, 183, 181, 119, 232, 126, 252, 217, 96, 162, 190, 103, 122, 64,
   1805             87, 145, 45, 32, 207, 17, 239, 223, 3, 35, 14, 112, 119, 124, 141, 123, 208, 239, 105,
   1806             81, 217, 151, 162, 190, 17, 88, 182, 176, 158, 81, 200, 42, 166, 133, 48, 23, 236, 55,
   1807             117, 248, 233, 151, 203, 122, 155, 231, 46, 177, 20, 20, 151, 64, 222, 239, 226, 7, 21,
   1808             254, 81, 202, 64, 232, 161, 235, 22, 51, 246, 207, 213, 0, 229, 138, 46, 222, 205, 157,
   1809             108, 139, 253, 230, 80, 50, 2, 122, 212, 163, 100, 180, 114, 12, 113, 52, 56, 99, 188,
   1810             42, 198, 212, 23, 182, 222, 56, 221, 200, 79, 96, 239, 221, 135, 10, 17, 106, 183, 56,
   1811             104, 68, 94, 198, 196, 35, 200, 83, 204, 26, 185, 204, 212, 31, 183, 19, 111, 233, 13,
   1812             72, 93, 53, 65, 111, 59, 242, 122, 160, 244, 162, 126, 38, 235, 156, 47, 88, 39, 132,
   1813             153, 79, 0, 133, 78, 7, 218, 165, 241,
   1814         ];
   1815         let e = 0x0001_0001u32;
   1816         let d = [
   1817             145, 79, 21, 97, 233, 3, 192, 194, 177, 68, 181, 80, 120, 197, 23, 44, 185, 74, 144, 0,
   1818             132, 149, 139, 11, 16, 224, 4, 112, 236, 94, 238, 97, 121, 124, 213, 145, 24, 253, 168,
   1819             35, 190, 205, 132, 115, 33, 201, 38, 253, 246, 180, 66, 155, 165, 46, 3, 254, 68, 108,
   1820             154, 247, 246, 45, 187, 0, 204, 96, 185, 157, 249, 174, 158, 38, 62, 244, 183, 76, 102,
   1821             6, 219, 92, 212, 138, 59, 147, 163, 219, 111, 39, 105, 21, 236, 196, 38, 255, 114, 247,
   1822             82, 104, 113, 204, 29, 152, 209, 219, 48, 239, 74, 129, 19, 247, 33, 239, 119, 166,
   1823             216, 152, 94, 138, 238, 164, 242, 129, 50, 150, 57, 20, 53, 224, 56, 241, 138, 97, 111,
   1824             215, 107, 212, 195, 146, 108, 143, 0, 229, 181, 171, 73, 152, 105, 146, 25, 243, 242,
   1825             140, 252, 248, 162, 247, 63, 168, 180, 20, 153, 120, 10, 248, 211, 1, 71, 127, 212,
   1826             249, 237, 203, 202, 48, 26, 216, 226, 228, 186, 13, 204, 70, 255, 240, 89, 255, 59, 83,
   1827             31, 253, 55, 43, 158, 90, 248, 83, 32, 159, 105, 57, 134, 34, 96, 18, 255, 245, 153,
   1828             162, 60, 91, 99, 220, 51, 44, 85, 114, 67, 125, 202, 65, 217, 245, 40, 8, 81, 165, 142,
   1829             24, 245, 127, 122, 247, 152, 212, 75, 45, 59, 90, 184, 234, 31, 147, 36, 8, 212, 45,
   1830             50, 23, 3, 25, 253, 87, 227, 79, 119, 161,
   1831         ];
   1832         let p = BoxedUint::from_le_slice_vartime(
   1833             [
   1834                 215, 166, 5, 21, 11, 179, 41, 77, 198, 92, 165, 48, 77, 162, 42, 41, 206, 141, 60,
   1835                 69, 47, 164, 19, 92, 46, 72, 100, 238, 100, 53, 214, 197, 163, 185, 6, 140, 229,
   1836                 250, 195, 77, 8, 12, 5, 236, 178, 173, 86, 201, 43, 213, 165, 51, 108, 101, 161,
   1837                 99, 76, 240, 14, 234, 76, 197, 137, 53, 198, 168, 135, 205, 212, 198, 120, 29, 16,
   1838                 82, 98, 233, 236, 177, 12, 171, 141, 100, 107, 146, 33, 176, 125, 202, 172, 79,
   1839                 147, 179, 30, 62, 247, 206, 169, 19, 168, 114, 26, 73, 108, 178, 105, 84, 89, 191,
   1840                 168, 253, 228, 214, 54, 16, 212, 199, 111, 72, 3, 41, 247, 227, 165, 244, 32, 188,
   1841                 24, 247,
   1842             ]
   1843             .as_slice(),
   1844         );
   1845         let p_2 = BoxedUint::from_le_slice_vartime(
   1846             [
   1847                 41, 25, 198, 240, 134, 206, 121, 57, 11, 5, 134, 192, 212, 77, 229, 197, 14, 78,
   1848                 85, 212, 190, 114, 179, 188, 21, 171, 174, 12, 104, 74, 15, 164, 136, 173, 62, 177,
   1849                 141, 213, 93, 102, 147, 83, 59, 124, 146, 59, 175, 213, 55, 27, 25, 248, 154, 29,
   1850                 39, 85, 50, 235, 134, 60, 203, 106, 186, 195, 190, 185, 71, 169, 142, 236, 92, 11,
   1851                 250, 187, 198, 8, 201, 184, 120, 178, 227, 87, 63, 243, 89, 227, 234, 184, 28, 252,
   1852                 112, 211, 193, 69, 23, 92, 5, 72, 93, 53, 69, 159, 73, 160, 105, 244, 249, 94, 214,
   1853                 173, 9, 236, 4, 255, 129, 11, 224, 140, 252, 168, 57, 143, 176, 241, 60, 219, 90,
   1854                 250,
   1855             ]
   1856             .as_slice(),
   1857         );
   1858         let key = RsaPrivateKey::from_components(
   1859             BoxedUint::from_le_slice_vartime(n.as_slice()),
   1860             e.into(),
   1861             BoxedUint::from_le_slice_vartime(d.as_slice()),
   1862             vec![p, p_2],
   1863         )
   1864         .unwrap()
   1865         .to_public_key();
   1866         assert!(
   1867             RsaPubKey::from_der(key.to_public_key_der().unwrap().as_bytes())
   1868                 .is_ok_and(|k| *k.0 == *key.n().to_be_bytes() && BoxedUint::from(k.1) == *key.e())
   1869         );
   1870     }
   1871     #[expect(clippy::unwrap_used, reason = "OK in tests")]
   1872     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
   1873     #[expect(
   1874         clippy::cognitive_complexity,
   1875         clippy::too_many_lines,
   1876         reason = "a lot to test"
   1877     )]
   1878     #[test]
   1879     fn eddsa_registration_deserialize_data_mismatch() {
   1880         let c_data_json = serde_json::json!({}).to_string();
   1881         let att_obj: [u8; 143] = [
   1882             cbor::MAP_3,
   1883             cbor::TEXT_3,
   1884             b'f',
   1885             b'm',
   1886             b't',
   1887             cbor::TEXT_4,
   1888             b'n',
   1889             b'o',
   1890             b'n',
   1891             b'e',
   1892             cbor::TEXT_7,
   1893             b'a',
   1894             b't',
   1895             b't',
   1896             b'S',
   1897             b't',
   1898             b'm',
   1899             b't',
   1900             cbor::MAP_0,
   1901             cbor::TEXT_8,
   1902             b'a',
   1903             b'u',
   1904             b't',
   1905             b'h',
   1906             b'D',
   1907             b'a',
   1908             b't',
   1909             b'a',
   1910             cbor::BYTES_INFO_24,
   1911             115,
   1912             // `rpIdHash`.
   1913             0,
   1914             0,
   1915             0,
   1916             0,
   1917             0,
   1918             0,
   1919             0,
   1920             0,
   1921             0,
   1922             0,
   1923             0,
   1924             0,
   1925             0,
   1926             0,
   1927             0,
   1928             0,
   1929             0,
   1930             0,
   1931             0,
   1932             0,
   1933             0,
   1934             0,
   1935             0,
   1936             0,
   1937             0,
   1938             0,
   1939             0,
   1940             0,
   1941             0,
   1942             0,
   1943             0,
   1944             0,
   1945             // `flags`.
   1946             0b0100_0101,
   1947             // `signCount`.
   1948             0,
   1949             0,
   1950             0,
   1951             0,
   1952             // `aaguid`.
   1953             0,
   1954             0,
   1955             0,
   1956             0,
   1957             0,
   1958             0,
   1959             0,
   1960             0,
   1961             0,
   1962             0,
   1963             0,
   1964             0,
   1965             0,
   1966             0,
   1967             0,
   1968             0,
   1969             // `credentialIdLength`.
   1970             0,
   1971             16,
   1972             // `credentialId`.
   1973             0,
   1974             0,
   1975             0,
   1976             0,
   1977             0,
   1978             0,
   1979             0,
   1980             0,
   1981             0,
   1982             0,
   1983             0,
   1984             0,
   1985             0,
   1986             0,
   1987             0,
   1988             0,
   1989             // Ed25519 COSE key.
   1990             cbor::MAP_4,
   1991             KTY,
   1992             OKP,
   1993             ALG,
   1994             EDDSA,
   1995             // `crv`.
   1996             cbor::NEG_ONE,
   1997             // `Ed25519`.
   1998             cbor::SIX,
   1999             // `x`.
   2000             cbor::NEG_TWO,
   2001             cbor::BYTES_INFO_24,
   2002             32,
   2003             // Compressed y-coordinate.
   2004             1,
   2005             1,
   2006             1,
   2007             1,
   2008             1,
   2009             1,
   2010             1,
   2011             1,
   2012             1,
   2013             1,
   2014             1,
   2015             1,
   2016             1,
   2017             1,
   2018             1,
   2019             1,
   2020             1,
   2021             1,
   2022             1,
   2023             1,
   2024             1,
   2025             1,
   2026             1,
   2027             1,
   2028             1,
   2029             1,
   2030             1,
   2031             1,
   2032             1,
   2033             1,
   2034             1,
   2035             1,
   2036         ];
   2037         let pub_key = VerifyingKey::from_bytes(&[1; 32])
   2038             .unwrap()
   2039             .to_public_key_der()
   2040             .unwrap();
   2041         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
   2042         let att_obj_len = att_obj.len();
   2043         let auth_data_start = att_obj_len - 113;
   2044         let b64_adata = base64url_nopad::encode(&att_obj[auth_data_start..]);
   2045         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
   2046         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
   2047         // Base case is valid.
   2048         assert!(
   2049             serde_json::from_str::<Registration>(
   2050                 serde_json::json!({
   2051                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2052                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2053                     "response": {
   2054                         "clientDataJSON": b64_cdata_json,
   2055                         "authenticatorData": b64_adata,
   2056                         "transports": ["ble", "usb", "hybrid", "internal", "nfc", "smart-card"],
   2057                         "publicKey": b64_key,
   2058                         "publicKeyAlgorithm": -8i8,
   2059                         "attestationObject": b64_aobj,
   2060                     },
   2061                     "authenticatorAttachment": "cross-platform",
   2062                     "clientExtensionResults": {},
   2063                     "type": "public-key"
   2064                 })
   2065                 .to_string()
   2066                 .as_str()
   2067             )
   2068             .is_ok_and(
   2069                 |reg| reg.response.client_data_json == c_data_json.as_bytes()
   2070                     && reg.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
   2071                     && reg.response.attestation_object_and_c_data_hash[att_obj_len..]
   2072                         == *Sha256::digest(c_data_json.as_bytes())
   2073                     && reg.response.transports.count() == 6
   2074                     && matches!(
   2075                         reg.authenticator_attachment,
   2076                         AuthenticatorAttachment::CrossPlatform
   2077                     )
   2078                     && reg.client_extension_results.cred_props.is_none()
   2079                     && reg.client_extension_results.prf.is_none()
   2080             )
   2081         );
   2082         // `id` and `rawId` mismatch.
   2083         let mut err = Error::invalid_value(
   2084             Unexpected::Bytes(
   2085                 base64url_nopad::decode(b"ABABABABABABABABABABAA")
   2086                     .unwrap()
   2087                     .as_slice(),
   2088             ),
   2089             &format!("id and rawId to match: CredentialId({:?})", [0u8; 16]).as_str(),
   2090         )
   2091         .to_string()
   2092         .into_bytes();
   2093         assert_eq!(
   2094             serde_json::from_str::<Registration>(
   2095                 serde_json::json!({
   2096                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2097                     "rawId": "ABABABABABABABABABABAA",
   2098                     "response": {
   2099                         "clientDataJSON": b64_cdata_json,
   2100                         "authenticatorData": b64_adata,
   2101                         "transports": [],
   2102                         "publicKey": b64_key,
   2103                         "publicKeyAlgorithm": -8i8,
   2104                         "attestationObject": b64_aobj,
   2105                     },
   2106                     "clientExtensionResults": {},
   2107                     "type": "public-key"
   2108                 })
   2109                 .to_string()
   2110                 .as_str()
   2111             )
   2112             .unwrap_err()
   2113             .to_string()
   2114             .into_bytes()
   2115             .get(..err.len()),
   2116             Some(err.as_slice())
   2117         );
   2118         // missing `id`.
   2119         err = Error::missing_field("id").to_string().into_bytes();
   2120         assert_eq!(
   2121             serde_json::from_str::<Registration>(
   2122                 serde_json::json!({
   2123                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2124                     "response": {
   2125                         "clientDataJSON": b64_cdata_json,
   2126                         "authenticatorData": b64_adata,
   2127                         "transports": [],
   2128                         "publicKey": b64_key,
   2129                         "publicKeyAlgorithm": -8i8,
   2130                         "attestationObject": b64_aobj,
   2131                     },
   2132                     "clientExtensionResults": {},
   2133                     "type": "public-key"
   2134                 })
   2135                 .to_string()
   2136                 .as_str()
   2137             )
   2138             .unwrap_err()
   2139             .to_string()
   2140             .into_bytes()
   2141             .get(..err.len()),
   2142             Some(err.as_slice())
   2143         );
   2144         // `null` `id`.
   2145         err = Error::invalid_type(Unexpected::Other("null"), &"CredentialId")
   2146             .to_string()
   2147             .into_bytes();
   2148         assert_eq!(
   2149             serde_json::from_str::<Registration>(
   2150                 serde_json::json!({
   2151                     "id": null,
   2152                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2153                     "response": {
   2154                         "clientDataJSON": b64_cdata_json,
   2155                         "authenticatorData": b64_adata,
   2156                         "transports": [],
   2157                         "publicKey": b64_key,
   2158                         "publicKeyAlgorithm": -8i8,
   2159                         "attestationObject": b64_aobj,
   2160                     },
   2161                     "clientExtensionResults": {},
   2162                     "type": "public-key"
   2163                 })
   2164                 .to_string()
   2165                 .as_str()
   2166             )
   2167             .unwrap_err()
   2168             .to_string()
   2169             .into_bytes()
   2170             .get(..err.len()),
   2171             Some(err.as_slice())
   2172         );
   2173         // missing `rawId`.
   2174         err = Error::missing_field("rawId").to_string().into_bytes();
   2175         assert_eq!(
   2176             serde_json::from_str::<Registration>(
   2177                 serde_json::json!({
   2178                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2179                     "response": {
   2180                         "clientDataJSON": b64_cdata_json,
   2181                         "authenticatorData": b64_adata,
   2182                         "transports": [],
   2183                         "publicKey": b64_key,
   2184                         "publicKeyAlgorithm": -8i8,
   2185                         "attestationObject": b64_aobj,
   2186                     },
   2187                     "clientExtensionResults": {},
   2188                     "type": "public-key"
   2189                 })
   2190                 .to_string()
   2191                 .as_str()
   2192             )
   2193             .unwrap_err()
   2194             .to_string()
   2195             .into_bytes()
   2196             .get(..err.len()),
   2197             Some(err.as_slice())
   2198         );
   2199         // `null` `rawId`.
   2200         err = Error::invalid_type(Unexpected::Other("null"), &"CredentialId")
   2201             .to_string()
   2202             .into_bytes();
   2203         assert_eq!(
   2204             serde_json::from_str::<Registration>(
   2205                 serde_json::json!({
   2206                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2207                     "rawId": null,
   2208                     "response": {
   2209                         "clientDataJSON": b64_cdata_json,
   2210                         "authenticatorData": b64_adata,
   2211                         "transports": [],
   2212                         "publicKey": b64_key,
   2213                         "publicKeyAlgorithm": -8i8,
   2214                         "attestationObject": b64_aobj,
   2215                     },
   2216                     "clientExtensionResults": {},
   2217                     "type": "public-key"
   2218                 })
   2219                 .to_string()
   2220                 .as_str()
   2221             )
   2222             .unwrap_err()
   2223             .to_string()
   2224             .into_bytes()
   2225             .get(..err.len()),
   2226             Some(err.as_slice())
   2227         );
   2228         // `id` and the credential id in authenticator data mismatch.
   2229         err = Error::invalid_value(
   2230             Unexpected::Bytes(
   2231                 base64url_nopad
   2232                     ::decode(b"ABABABABABABABABABABAA")
   2233                     .unwrap()
   2234                     .as_slice(),
   2235             ),
   2236             &format!("id, rawId, and the credential id in the attested credential data to all match: {:?}", [0u8; 16]).as_str(),
   2237         )
   2238         .to_string().into_bytes();
   2239         assert_eq!(
   2240             serde_json::from_str::<Registration>(
   2241                 serde_json::json!({
   2242                     "id": "ABABABABABABABABABABAA",
   2243                     "rawId": "ABABABABABABABABABABAA",
   2244                     "response": {
   2245                         "clientDataJSON": b64_cdata_json,
   2246                         "authenticatorData": b64_adata,
   2247                         "transports": [],
   2248                         "publicKey": b64_key,
   2249                         "publicKeyAlgorithm": -8i8,
   2250                         "attestationObject": b64_aobj,
   2251                     },
   2252                     "clientExtensionResults": {},
   2253                     "type": "public-key"
   2254                 })
   2255                 .to_string()
   2256                 .as_str()
   2257             )
   2258             .unwrap_err()
   2259             .to_string()
   2260             .into_bytes()
   2261             .get(..err.len()),
   2262             Some(err.as_slice())
   2263         );
   2264         // `authenticatorData` mismatches `authData` in attestation object.
   2265         let mut bad_auth = [0; 113];
   2266         bad_auth.copy_from_slice(&att_obj[auth_data_start..]);
   2267         bad_auth[113 - 32..].copy_from_slice([0; 32].as_slice());
   2268         err = Error::invalid_value(
   2269             Unexpected::Bytes(bad_auth.as_slice()),
   2270             &format!("authenticator data to match the authenticator data portion of attestation object: {:?}", &att_obj[att_obj_len - bad_auth.len()..]).as_str(),
   2271         )
   2272         .to_string().into_bytes();
   2273         assert_eq!(
   2274             serde_json::from_str::<Registration>(
   2275                 serde_json::json!({
   2276                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2277                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2278                     "response": {
   2279                         "clientDataJSON": b64_cdata_json,
   2280                         "authenticatorData": base64url_nopad::encode(bad_auth.as_slice()),
   2281                         "transports": [],
   2282                         "publicKey": b64_key,
   2283                         "publicKeyAlgorithm": -8i8,
   2284                         "attestationObject": b64_aobj,
   2285                     },
   2286                     "clientExtensionResults": {},
   2287                     "type": "public-key"
   2288                 })
   2289                 .to_string()
   2290                 .as_str()
   2291             )
   2292             .unwrap_err()
   2293             .to_string()
   2294             .into_bytes()
   2295             .get(..err.len()),
   2296             Some(err.as_slice())
   2297         );
   2298         // Missing `authenticatorData`.
   2299         err = Error::missing_field("authenticatorData")
   2300             .to_string()
   2301             .into_bytes();
   2302         assert_eq!(
   2303             serde_json::from_str::<Registration>(
   2304                 serde_json::json!({
   2305                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2306                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2307                     "response": {
   2308                         "clientDataJSON": b64_cdata_json,
   2309                         "transports": [],
   2310                         "publicKey": b64_key,
   2311                         "publicKeyAlgorithm": -8i8,
   2312                         "attestationObject": b64_aobj,
   2313                     },
   2314                     "clientExtensionResults": {},
   2315                     "type": "public-key"
   2316                 })
   2317                 .to_string()
   2318                 .as_str()
   2319             )
   2320             .unwrap_err()
   2321             .to_string()
   2322             .into_bytes()
   2323             .get(..err.len()),
   2324             Some(err.as_slice())
   2325         );
   2326         // `null` `authenticatorData`.
   2327         err = Error::invalid_type(Unexpected::Other("null"), &"authenticatorData")
   2328             .to_string()
   2329             .into_bytes();
   2330         assert_eq!(
   2331             serde_json::from_str::<Registration>(
   2332                 serde_json::json!({
   2333                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2334                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2335                     "response": {
   2336                         "clientDataJSON": b64_cdata_json,
   2337                         "transports": [],
   2338                         "authenticatorData": null,
   2339                         "publicKey": b64_key,
   2340                         "publicKeyAlgorithm": -8i8,
   2341                         "attestationObject": b64_aobj,
   2342                     },
   2343                     "clientExtensionResults": {},
   2344                     "type": "public-key"
   2345                 })
   2346                 .to_string()
   2347                 .as_str()
   2348             )
   2349             .unwrap_err()
   2350             .to_string()
   2351             .into_bytes()
   2352             .get(..err.len()),
   2353             Some(err.as_slice())
   2354         );
   2355         // `publicKeyAlgorithm` mismatch.
   2356         err = Error::invalid_value(
   2357             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   2358             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Eddsa).as_str()
   2359         )
   2360         .to_string().into_bytes();
   2361         assert_eq!(
   2362             serde_json::from_str::<Registration>(
   2363                 serde_json::json!({
   2364                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2365                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2366                     "response": {
   2367                         "clientDataJSON": b64_cdata_json,
   2368                         "authenticatorData": b64_adata,
   2369                         "transports": [],
   2370                         "publicKey": b64_key,
   2371                         "publicKeyAlgorithm": -7i8,
   2372                         "attestationObject": b64_aobj,
   2373                     },
   2374                     "clientExtensionResults": {},
   2375                     "type": "public-key"
   2376                 })
   2377                 .to_string()
   2378                 .as_str()
   2379             )
   2380             .unwrap_err()
   2381             .to_string()
   2382             .into_bytes()
   2383             .get(..err.len()),
   2384             Some(err.as_slice())
   2385         );
   2386         // Missing `publicKeyAlgorithm`.
   2387         err = Error::missing_field("publicKeyAlgorithm")
   2388             .to_string()
   2389             .into_bytes();
   2390         assert_eq!(
   2391             serde_json::from_str::<Registration>(
   2392                 serde_json::json!({
   2393                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2394                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2395                     "response": {
   2396                         "clientDataJSON": b64_cdata_json,
   2397                         "authenticatorData": b64_adata,
   2398                         "transports": [],
   2399                         "publicKey": b64_key,
   2400                         "attestationObject": b64_aobj,
   2401                     },
   2402                     "clientExtensionResults": {},
   2403                     "type": "public-key"
   2404                 })
   2405                 .to_string()
   2406                 .as_str()
   2407             )
   2408             .unwrap_err()
   2409             .to_string()
   2410             .into_bytes()
   2411             .get(..err.len()),
   2412             Some(err.as_slice())
   2413         );
   2414         // `null` `publicKeyAlgorithm`.
   2415         err = Error::invalid_type(Unexpected::Other("null"), &"publicKeyAlgorithm")
   2416             .to_string()
   2417             .into_bytes();
   2418         assert_eq!(
   2419             serde_json::from_str::<Registration>(
   2420                 serde_json::json!({
   2421                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2422                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2423                     "response": {
   2424                         "clientDataJSON": b64_cdata_json,
   2425                         "authenticatorData": b64_adata,
   2426                         "transports": [],
   2427                         "publicKey": b64_key,
   2428                         "publicKeyAlgorithm": null,
   2429                         "attestationObject": b64_aobj,
   2430                     },
   2431                     "clientExtensionResults": {},
   2432                     "type": "public-key"
   2433                 })
   2434                 .to_string()
   2435                 .as_str()
   2436             )
   2437             .unwrap_err()
   2438             .to_string()
   2439             .into_bytes()
   2440             .get(..err.len()),
   2441             Some(err.as_slice())
   2442         );
   2443         // `publicKey` mismatch.
   2444         err = Error::invalid_value(
   2445             Unexpected::Bytes([0; 32].as_slice()),
   2446             &format!(
   2447                 "DER-encoded public key to match the public key within the attestation object: Ed25519(Ed25519PubKey({:?}))",
   2448                 &att_obj[att_obj.len() - 32..],
   2449             )
   2450             .as_str(),
   2451         )
   2452         .to_string().into_bytes();
   2453         assert_eq!(serde_json::from_str::<Registration>(
   2454             serde_json::json!({
   2455                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2456                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2457                 "response": {
   2458                     "clientDataJSON": b64_cdata_json,
   2459                     "authenticatorData": b64_adata,
   2460                     "transports": [],
   2461                     "publicKey": base64url_nopad::encode(VerifyingKey::from_bytes(&[0; 32]).unwrap().to_public_key_der().unwrap().as_bytes()),
   2462                     "publicKeyAlgorithm": -8i8,
   2463                     "attestationObject": b64_aobj,
   2464                 },
   2465                 "clientExtensionResults": {},
   2466                 "type": "public-key"
   2467             })
   2468             .to_string()
   2469             .as_str()
   2470             )
   2471             .unwrap_err().to_string().into_bytes().get(..err.len()),
   2472             Some(err.as_slice())
   2473         );
   2474         // Missing `publicKey` when using EdDSA, ES256, or RS256.
   2475         err = Error::missing_field("publicKey").to_string().into_bytes();
   2476         assert_eq!(
   2477             serde_json::from_str::<Registration>(
   2478                 serde_json::json!({
   2479                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2480                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2481                     "response": {
   2482                         "clientDataJSON": b64_cdata_json,
   2483                         "authenticatorData": b64_adata,
   2484                         "transports": [],
   2485                         "publicKeyAlgorithm": -8i8,
   2486                         "attestationObject": b64_aobj,
   2487                     },
   2488                     "clientExtensionResults": {},
   2489                     "type": "public-key"
   2490                 })
   2491                 .to_string()
   2492                 .as_str()
   2493             )
   2494             .unwrap_err()
   2495             .to_string()
   2496             .into_bytes()
   2497             .get(..err.len()),
   2498             Some(err.as_slice())
   2499         );
   2500         // `null` `publicKey` when using EdDSA, ES256, or RS256.
   2501         err = Error::invalid_type(Unexpected::Other("null"), &"publicKey")
   2502             .to_string()
   2503             .into_bytes();
   2504         assert_eq!(
   2505             serde_json::from_str::<Registration>(
   2506                 serde_json::json!({
   2507                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2508                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2509                     "response": {
   2510                         "clientDataJSON": b64_cdata_json,
   2511                         "authenticatorData": b64_adata,
   2512                         "transports": [],
   2513                         "publicKey": null,
   2514                         "publicKeyAlgorithm": -8i8,
   2515                         "attestationObject": b64_aobj,
   2516                     },
   2517                     "clientExtensionResults": {},
   2518                     "type": "public-key"
   2519                 })
   2520                 .to_string()
   2521                 .as_str()
   2522             )
   2523             .unwrap_err()
   2524             .to_string()
   2525             .into_bytes()
   2526             .get(..err.len()),
   2527             Some(err.as_slice())
   2528         );
   2529         // Missing `transports`.
   2530         err = Error::missing_field("transports").to_string().into_bytes();
   2531         assert_eq!(
   2532             serde_json::from_str::<Registration>(
   2533                 serde_json::json!({
   2534                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2535                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2536                     "response": {
   2537                         "clientDataJSON": b64_cdata_json,
   2538                         "authenticatorData": b64_adata,
   2539                         "publicKey": b64_key,
   2540                         "publicKeyAlgorithm": -8i8,
   2541                         "attestationObject": b64_aobj,
   2542                     },
   2543                     "clientExtensionResults": {},
   2544                     "type": "public-key"
   2545                 })
   2546                 .to_string()
   2547                 .as_str()
   2548             )
   2549             .unwrap_err()
   2550             .to_string()
   2551             .into_bytes()
   2552             .get(..err.len()),
   2553             Some(err.as_slice())
   2554         );
   2555         // Duplicate `transports` are allowed.
   2556         assert!(
   2557             serde_json::from_str::<Registration>(
   2558                 serde_json::json!({
   2559                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2560                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2561                     "response": {
   2562                         "clientDataJSON": b64_cdata_json,
   2563                         "authenticatorData": b64_adata,
   2564                         "transports": ["usb", "usb"],
   2565                         "publicKey": b64_key,
   2566                         "publicKeyAlgorithm": -8i8,
   2567                         "attestationObject": b64_aobj,
   2568                     },
   2569                     "clientExtensionResults": {},
   2570                     "type": "public-key"
   2571                 })
   2572                 .to_string()
   2573                 .as_str()
   2574             )
   2575             .is_ok_and(|reg| reg.response.transports.count() == 1)
   2576         );
   2577         // `null` `transports`.
   2578         err = Error::invalid_type(Unexpected::Other("null"), &"transports")
   2579             .to_string()
   2580             .into_bytes();
   2581         assert_eq!(
   2582             serde_json::from_str::<Registration>(
   2583                 serde_json::json!({
   2584                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2585                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2586                     "response": {
   2587                         "clientDataJSON": b64_cdata_json,
   2588                         "authenticatorData": b64_adata,
   2589                         "transports": null,
   2590                         "publicKey": b64_key,
   2591                         "publicKeyAlgorithm": -8i8,
   2592                         "attestationObject": b64_aobj,
   2593                     },
   2594                     "clientExtensionResults": {},
   2595                     "type": "public-key"
   2596                 })
   2597                 .to_string()
   2598                 .as_str()
   2599             )
   2600             .unwrap_err()
   2601             .to_string()
   2602             .into_bytes()
   2603             .get(..err.len()),
   2604             Some(err.as_slice())
   2605         );
   2606         // Unknown `transports`.
   2607         err = Error::invalid_value(
   2608             Unexpected::Str("Usb"),
   2609             &"'ble', 'cable', 'hybrid', 'internal', 'nfc', 'smart-card', or 'usb'",
   2610         )
   2611         .to_string()
   2612         .into_bytes();
   2613         assert_eq!(
   2614             serde_json::from_str::<Registration>(
   2615                 serde_json::json!({
   2616                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2617                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2618                     "response": {
   2619                         "clientDataJSON": b64_cdata_json,
   2620                         "authenticatorData": b64_adata,
   2621                         "transports": ["Usb"],
   2622                         "publicKey": b64_key,
   2623                         "publicKeyAlgorithm": -8i8,
   2624                         "attestationObject": b64_aobj,
   2625                     },
   2626                     "clientExtensionResults": {},
   2627                     "type": "public-key"
   2628                 })
   2629                 .to_string()
   2630                 .as_str()
   2631             )
   2632             .unwrap_err()
   2633             .to_string()
   2634             .into_bytes()
   2635             .get(..err.len()),
   2636             Some(err.as_slice())
   2637         );
   2638         // `null` `authenticatorAttachment`.
   2639         assert!(
   2640             serde_json::from_str::<Registration>(
   2641                 serde_json::json!({
   2642                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2643                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2644                     "response": {
   2645                         "clientDataJSON": b64_cdata_json,
   2646                         "authenticatorData": b64_adata,
   2647                         "transports": [],
   2648                         "publicKey": b64_key,
   2649                         "publicKeyAlgorithm": -8i8,
   2650                         "attestationObject": b64_aobj,
   2651                     },
   2652                     "authenticatorAttachment": null,
   2653                     "clientExtensionResults": {},
   2654                     "type": "public-key"
   2655                 })
   2656                 .to_string()
   2657                 .as_str()
   2658             )
   2659             .is_ok_and(|reg| matches!(reg.authenticator_attachment, AuthenticatorAttachment::None))
   2660         );
   2661         // Unknown `authenticatorAttachment`.
   2662         err = Error::invalid_value(
   2663             Unexpected::Str("Platform"),
   2664             &"'platform' or 'cross-platform'",
   2665         )
   2666         .to_string()
   2667         .into_bytes();
   2668         assert_eq!(
   2669             serde_json::from_str::<Registration>(
   2670                 serde_json::json!({
   2671                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2672                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2673                     "response": {
   2674                         "clientDataJSON": b64_cdata_json,
   2675                         "authenticatorData": b64_adata,
   2676                         "transports": [],
   2677                         "publicKey": b64_key,
   2678                         "publicKeyAlgorithm": -8i8,
   2679                         "attestationObject": b64_aobj,
   2680                     },
   2681                     "authenticatorAttachment": "Platform",
   2682                     "clientExtensionResults": {},
   2683                     "type": "public-key"
   2684                 })
   2685                 .to_string()
   2686                 .as_str()
   2687             )
   2688             .unwrap_err()
   2689             .to_string()
   2690             .into_bytes()
   2691             .get(..err.len()),
   2692             Some(err.as_slice())
   2693         );
   2694         // Missing `clientDataJSON`.
   2695         err = Error::missing_field("clientDataJSON")
   2696             .to_string()
   2697             .into_bytes();
   2698         assert_eq!(
   2699             serde_json::from_str::<Registration>(
   2700                 serde_json::json!({
   2701                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2702                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2703                     "response": {
   2704                         "authenticatorData": b64_adata,
   2705                         "transports": [],
   2706                         "publicKey": b64_key,
   2707                         "publicKeyAlgorithm": -8i8,
   2708                         "attestationObject": b64_aobj,
   2709                     },
   2710                     "clientExtensionResults": {},
   2711                     "type": "public-key"
   2712                 })
   2713                 .to_string()
   2714                 .as_str()
   2715             )
   2716             .unwrap_err()
   2717             .to_string()
   2718             .into_bytes()
   2719             .get(..err.len()),
   2720             Some(err.as_slice())
   2721         );
   2722         // `null` `clientDataJSON`.
   2723         err = Error::invalid_type(Unexpected::Other("null"), &"base64url-encoded data")
   2724             .to_string()
   2725             .into_bytes();
   2726         assert_eq!(
   2727             serde_json::from_str::<Registration>(
   2728                 serde_json::json!({
   2729                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2730                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2731                     "response": {
   2732                         "clientDataJSON": null,
   2733                         "authenticatorData": b64_adata,
   2734                         "transports": [],
   2735                         "publicKey": b64_key,
   2736                         "publicKeyAlgorithm": -8i8,
   2737                         "attestationObject": b64_aobj,
   2738                     },
   2739                     "clientExtensionResults": {},
   2740                     "type": "public-key"
   2741                 })
   2742                 .to_string()
   2743                 .as_str()
   2744             )
   2745             .unwrap_err()
   2746             .to_string()
   2747             .into_bytes()
   2748             .get(..err.len()),
   2749             Some(err.as_slice())
   2750         );
   2751         // Missing `attestationObject`.
   2752         err = Error::missing_field("attestationObject")
   2753             .to_string()
   2754             .into_bytes();
   2755         assert_eq!(
   2756             serde_json::from_str::<Registration>(
   2757                 serde_json::json!({
   2758                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2759                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2760                     "response": {
   2761                         "clientDataJSON": b64_cdata_json,
   2762                         "authenticatorData": b64_adata,
   2763                         "transports": [],
   2764                         "publicKey": b64_key,
   2765                         "publicKeyAlgorithm": -8i8,
   2766                     },
   2767                     "clientExtensionResults": {},
   2768                     "type": "public-key"
   2769                 })
   2770                 .to_string()
   2771                 .as_str()
   2772             )
   2773             .unwrap_err()
   2774             .to_string()
   2775             .into_bytes()
   2776             .get(..err.len()),
   2777             Some(err.as_slice())
   2778         );
   2779         // `null` `attestationObject`.
   2780         err = Error::invalid_type(
   2781             Unexpected::Other("null"),
   2782             &"base64url-encoded attestation object",
   2783         )
   2784         .to_string()
   2785         .into_bytes();
   2786         assert_eq!(
   2787             serde_json::from_str::<Registration>(
   2788                 serde_json::json!({
   2789                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2790                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2791                     "response": {
   2792                         "clientDataJSON": b64_cdata_json,
   2793                         "authenticatorData": b64_adata,
   2794                         "transports": [],
   2795                         "publicKey": b64_key,
   2796                         "publicKeyAlgorithm": -8i8,
   2797                         "attestationObject": null,
   2798                     },
   2799                     "clientExtensionResults": {},
   2800                     "type": "public-key"
   2801                 })
   2802                 .to_string()
   2803                 .as_str()
   2804             )
   2805             .unwrap_err()
   2806             .to_string()
   2807             .into_bytes()
   2808             .get(..err.len()),
   2809             Some(err.as_slice())
   2810         );
   2811         // Missing `response`.
   2812         err = Error::missing_field("response").to_string().into_bytes();
   2813         assert_eq!(
   2814             serde_json::from_str::<Registration>(
   2815                 serde_json::json!({
   2816                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2817                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2818                     "clientExtensionResults": {},
   2819                     "type": "public-key"
   2820                 })
   2821                 .to_string()
   2822                 .as_str()
   2823             )
   2824             .unwrap_err()
   2825             .to_string()
   2826             .into_bytes()
   2827             .get(..err.len()),
   2828             Some(err.as_slice())
   2829         );
   2830         // `null` `response`.
   2831         err = Error::invalid_type(Unexpected::Other("null"), &"AuthenticatorAttestation")
   2832             .to_string()
   2833             .into_bytes();
   2834         assert_eq!(
   2835             serde_json::from_str::<Registration>(
   2836                 serde_json::json!({
   2837                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2838                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2839                     "response": null,
   2840                     "clientExtensionResults": {},
   2841                     "type": "public-key"
   2842                 })
   2843                 .to_string()
   2844                 .as_str()
   2845             )
   2846             .unwrap_err()
   2847             .to_string()
   2848             .into_bytes()
   2849             .get(..err.len()),
   2850             Some(err.as_slice())
   2851         );
   2852         // Empty `response`.
   2853         err = Error::missing_field("clientDataJSON")
   2854             .to_string()
   2855             .into_bytes();
   2856         assert_eq!(
   2857             serde_json::from_str::<Registration>(
   2858                 serde_json::json!({
   2859                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2860                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2861                     "response": {},
   2862                     "clientExtensionResults": {},
   2863                     "type": "public-key"
   2864                 })
   2865                 .to_string()
   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 `clientExtensionResults`.
   2875         err = Error::missing_field("clientExtensionResults")
   2876             .to_string()
   2877             .into_bytes();
   2878         assert_eq!(
   2879             serde_json::from_str::<Registration>(
   2880                 serde_json::json!({
   2881                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2882                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2883                     "response": {
   2884                         "clientDataJSON": b64_cdata_json,
   2885                         "authenticatorData": b64_adata,
   2886                         "transports": [],
   2887                         "publicKey": b64_key,
   2888                         "publicKeyAlgorithm": -8i8,
   2889                         "attestationObject": b64_aobj,
   2890                     },
   2891                     "type": "public-key"
   2892                 })
   2893                 .to_string()
   2894                 .as_str()
   2895             )
   2896             .unwrap_err()
   2897             .to_string()
   2898             .into_bytes()
   2899             .get(..err.len()),
   2900             Some(err.as_slice())
   2901         );
   2902         // `null` `clientExtensionResults`.
   2903         err = Error::invalid_type(
   2904             Unexpected::Other("null"),
   2905             &"clientExtensionResults to be a map of allowed client extensions",
   2906         )
   2907         .to_string()
   2908         .into_bytes();
   2909         assert_eq!(
   2910             serde_json::from_str::<Registration>(
   2911                 serde_json::json!({
   2912                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2913                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2914                     "response": {
   2915                         "clientDataJSON": b64_cdata_json,
   2916                         "authenticatorData": b64_adata,
   2917                         "transports": [],
   2918                         "publicKey": b64_key,
   2919                         "publicKeyAlgorithm": -8i8,
   2920                         "attestationObject": b64_aobj,
   2921                     },
   2922                     "clientExtensionResults": null,
   2923                     "type": "public-key"
   2924                 })
   2925                 .to_string()
   2926                 .as_str()
   2927             )
   2928             .unwrap_err()
   2929             .to_string()
   2930             .into_bytes()
   2931             .get(..err.len()),
   2932             Some(err.as_slice())
   2933         );
   2934         // Missing `type`.
   2935         err = Error::missing_field("type").to_string().into_bytes();
   2936         assert_eq!(
   2937             serde_json::from_str::<Registration>(
   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                 })
   2951                 .to_string()
   2952                 .as_str()
   2953             )
   2954             .unwrap_err()
   2955             .to_string()
   2956             .into_bytes()
   2957             .get(..err.len()),
   2958             Some(err.as_slice())
   2959         );
   2960         // `null` `type`.
   2961         err = Error::invalid_type(Unexpected::Other("null"), &"public-key")
   2962             .to_string()
   2963             .into_bytes();
   2964         assert_eq!(
   2965             serde_json::from_str::<Registration>(
   2966                 serde_json::json!({
   2967                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2968                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2969                     "response": {
   2970                         "clientDataJSON": b64_cdata_json,
   2971                         "authenticatorData": b64_adata,
   2972                         "transports": [],
   2973                         "publicKey": b64_key,
   2974                         "publicKeyAlgorithm": -8i8,
   2975                         "attestationObject": b64_aobj,
   2976                     },
   2977                     "clientExtensionResults": {},
   2978                     "type": null
   2979                 })
   2980                 .to_string()
   2981                 .as_str()
   2982             )
   2983             .unwrap_err()
   2984             .to_string()
   2985             .into_bytes()
   2986             .get(..err.len()),
   2987             Some(err.as_slice())
   2988         );
   2989         // Not exactly `public-type` `type`.
   2990         err = Error::invalid_value(Unexpected::Str("Public-key"), &"public-key")
   2991             .to_string()
   2992             .into_bytes();
   2993         assert_eq!(
   2994             serde_json::from_str::<Registration>(
   2995                 serde_json::json!({
   2996                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2997                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2998                     "response": {
   2999                         "clientDataJSON": b64_cdata_json,
   3000                         "authenticatorData": b64_adata,
   3001                         "transports": [],
   3002                         "publicKey": b64_key,
   3003                         "publicKeyAlgorithm": -8i8,
   3004                         "attestationObject": b64_aobj,
   3005                     },
   3006                     "clientExtensionResults": {},
   3007                     "type": "Public-key"
   3008                 })
   3009                 .to_string()
   3010                 .as_str()
   3011             )
   3012             .unwrap_err()
   3013             .to_string()
   3014             .into_bytes()
   3015             .get(..err.len()),
   3016             Some(err.as_slice())
   3017         );
   3018         // `null`.
   3019         err = Error::invalid_type(Unexpected::Other("null"), &"PublicKeyCredential")
   3020             .to_string()
   3021             .into_bytes();
   3022         assert_eq!(
   3023             serde_json::from_str::<Registration>(serde_json::json!(null).to_string().as_str())
   3024                 .unwrap_err()
   3025                 .to_string()
   3026                 .into_bytes()
   3027                 .get(..err.len()),
   3028             Some(err.as_slice())
   3029         );
   3030         // Empty.
   3031         err = Error::missing_field("response").to_string().into_bytes();
   3032         assert_eq!(
   3033             serde_json::from_str::<Registration>(serde_json::json!({}).to_string().as_str())
   3034                 .unwrap_err()
   3035                 .to_string()
   3036                 .into_bytes()
   3037                 .get(..err.len()),
   3038             Some(err.as_slice())
   3039         );
   3040         // Unknown field in `response`.
   3041         err = Error::unknown_field(
   3042             "foo",
   3043             [
   3044                 "clientDataJSON",
   3045                 "attestationObject",
   3046                 "authenticatorData",
   3047                 "transports",
   3048                 "publicKey",
   3049                 "publicKeyAlgorithm",
   3050             ]
   3051             .as_slice(),
   3052         )
   3053         .to_string()
   3054         .into_bytes();
   3055         assert_eq!(
   3056             serde_json::from_str::<Registration>(
   3057                 serde_json::json!({
   3058                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3059                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3060                     "response": {
   3061                         "clientDataJSON": b64_cdata_json,
   3062                         "authenticatorData": b64_adata,
   3063                         "transports": [],
   3064                         "publicKey": b64_key,
   3065                         "publicKeyAlgorithm": -8i8,
   3066                         "attestationObject": b64_aobj,
   3067                         "foo": true,
   3068                     },
   3069                     "clientExtensionResults": {},
   3070                     "type": "public-key"
   3071                 })
   3072                 .to_string()
   3073                 .as_str()
   3074             )
   3075             .unwrap_err()
   3076             .to_string()
   3077             .into_bytes()
   3078             .get(..err.len()),
   3079             Some(err.as_slice())
   3080         );
   3081         // Duplicate field in `response`.
   3082         err = Error::duplicate_field("transports")
   3083             .to_string()
   3084             .into_bytes();
   3085         assert_eq!(
   3086             serde_json::from_str::<Registration>(
   3087                 format!(
   3088                     "{{
   3089                        \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   3090                        \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   3091                        \"response\": {{
   3092                            \"clientDataJSON\": \"{b64_cdata_json}\",
   3093                            \"authenticatorData\": \"{b64_adata}\",
   3094                            \"transports\": [],
   3095                            \"publicKey\": \"{b64_key}\",
   3096                            \"publicKeyAlgorithm\": -8,
   3097                            \"attestationObject\": \"{b64_aobj}\",
   3098                            \"transports\": []
   3099                        }},
   3100                        \"clientExtensionResults\": {{}},
   3101                        \"type\": \"public-key\"
   3102                             
   3103                      }}"
   3104                 )
   3105                 .as_str()
   3106             )
   3107             .unwrap_err()
   3108             .to_string()
   3109             .into_bytes()
   3110             .get(..err.len()),
   3111             Some(err.as_slice())
   3112         );
   3113         // Unknown field in `PublicKeyCredential`.
   3114         err = Error::unknown_field(
   3115             "foo",
   3116             [
   3117                 "id",
   3118                 "type",
   3119                 "rawId",
   3120                 "response",
   3121                 "authenticatorAttachment",
   3122                 "clientExtensionResults",
   3123             ]
   3124             .as_slice(),
   3125         )
   3126         .to_string()
   3127         .into_bytes();
   3128         assert_eq!(
   3129             serde_json::from_str::<Registration>(
   3130                 serde_json::json!({
   3131                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3132                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3133                     "response": {
   3134                         "clientDataJSON": b64_cdata_json,
   3135                         "authenticatorData": b64_adata,
   3136                         "transports": [],
   3137                         "publicKey": b64_key,
   3138                         "publicKeyAlgorithm": -8i8,
   3139                         "attestationObject": b64_aobj
   3140                     },
   3141                     "clientExtensionResults": {},
   3142                     "type": "public-key",
   3143                     "foo": true,
   3144                 })
   3145                 .to_string()
   3146                 .as_str()
   3147             )
   3148             .unwrap_err()
   3149             .to_string()
   3150             .into_bytes()
   3151             .get(..err.len()),
   3152             Some(err.as_slice())
   3153         );
   3154         // Duplicate field in `PublicKeyCredential`.
   3155         err = Error::duplicate_field("id").to_string().into_bytes();
   3156         assert_eq!(
   3157             serde_json::from_str::<Registration>(
   3158                 format!(
   3159                     "{{
   3160                        \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   3161                        \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   3162                        \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   3163                        \"response\": {{
   3164                            \"clientDataJSON\": \"{b64_cdata_json}\",
   3165                            \"authenticatorData\": \"{b64_adata}\",
   3166                            \"transports\": [],
   3167                            \"publicKey\": \"{b64_key}\",
   3168                            \"publicKeyAlgorithm\": -8,
   3169                            \"attestationObject\": \"{b64_aobj}\"
   3170                        }},
   3171                        \"clientExtensionResults\": {{}},
   3172                        \"type\": \"public-key\"
   3173                             
   3174                      }}"
   3175                 )
   3176                 .as_str()
   3177             )
   3178             .unwrap_err()
   3179             .to_string()
   3180             .into_bytes()
   3181             .get(..err.len()),
   3182             Some(err.as_slice())
   3183         );
   3184     }
   3185     #[expect(clippy::unwrap_used, reason = "OK in tests")]
   3186     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
   3187     #[expect(
   3188         clippy::cognitive_complexity,
   3189         clippy::too_many_lines,
   3190         reason = "a lot to test"
   3191     )]
   3192     #[test]
   3193     fn client_extensions() {
   3194         let c_data_json = serde_json::json!({}).to_string();
   3195         let att_obj: [u8; 143] = [
   3196             cbor::MAP_3,
   3197             cbor::TEXT_3,
   3198             b'f',
   3199             b'm',
   3200             b't',
   3201             cbor::TEXT_4,
   3202             b'n',
   3203             b'o',
   3204             b'n',
   3205             b'e',
   3206             cbor::TEXT_7,
   3207             b'a',
   3208             b't',
   3209             b't',
   3210             b'S',
   3211             b't',
   3212             b'm',
   3213             b't',
   3214             cbor::MAP_0,
   3215             cbor::TEXT_8,
   3216             b'a',
   3217             b'u',
   3218             b't',
   3219             b'h',
   3220             b'D',
   3221             b'a',
   3222             b't',
   3223             b'a',
   3224             cbor::BYTES_INFO_24,
   3225             113,
   3226             // `rpIdHash`.
   3227             0,
   3228             0,
   3229             0,
   3230             0,
   3231             0,
   3232             0,
   3233             0,
   3234             0,
   3235             0,
   3236             0,
   3237             0,
   3238             0,
   3239             0,
   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             0,
   3257             0,
   3258             0,
   3259             // `flags`.
   3260             0b0100_0101,
   3261             // `signCount`.
   3262             0,
   3263             0,
   3264             0,
   3265             0,
   3266             // `aaguid`.
   3267             0,
   3268             0,
   3269             0,
   3270             0,
   3271             0,
   3272             0,
   3273             0,
   3274             0,
   3275             0,
   3276             0,
   3277             0,
   3278             0,
   3279             0,
   3280             0,
   3281             0,
   3282             0,
   3283             // `credentialIdLength`.
   3284             0,
   3285             16,
   3286             // `credentialId`.
   3287             0,
   3288             0,
   3289             0,
   3290             0,
   3291             0,
   3292             0,
   3293             0,
   3294             0,
   3295             0,
   3296             0,
   3297             0,
   3298             0,
   3299             0,
   3300             0,
   3301             0,
   3302             0,
   3303             // Ed25519 COSE key.
   3304             cbor::MAP_4,
   3305             KTY,
   3306             OKP,
   3307             ALG,
   3308             EDDSA,
   3309             // `crv`.
   3310             cbor::NEG_ONE,
   3311             // `Ed25519`.
   3312             cbor::SIX,
   3313             // `x`.
   3314             cbor::NEG_TWO,
   3315             cbor::BYTES_INFO_24,
   3316             32,
   3317             // Compressed y-coordinate.
   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         ];
   3351         let pub_key = VerifyingKey::from_bytes(&[1; 32])
   3352             .unwrap()
   3353             .to_public_key_der()
   3354             .unwrap();
   3355         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
   3356         let b64_adata = base64url_nopad::encode(&att_obj[att_obj.len() - 113..]);
   3357         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
   3358         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
   3359         // Base case is valid.
   3360         assert!(
   3361             serde_json::from_str::<Registration>(
   3362                 serde_json::json!({
   3363                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3364                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3365                     "response": {
   3366                         "clientDataJSON": b64_cdata_json,
   3367                         "authenticatorData": b64_adata,
   3368                         "transports": [],
   3369                         "publicKey": b64_key,
   3370                         "publicKeyAlgorithm": -8i8,
   3371                         "attestationObject": b64_aobj,
   3372                     },
   3373                     "clientExtensionResults": {},
   3374                     "type": "public-key"
   3375                 })
   3376                 .to_string()
   3377                 .as_str()
   3378             )
   3379             .is_ok_and(
   3380                 |reg| reg.response.client_data_json == c_data_json.as_bytes()
   3381                     && reg.response.attestation_object_and_c_data_hash[..att_obj.len()] == att_obj
   3382                     && reg.response.attestation_object_and_c_data_hash[att_obj.len()..]
   3383                         == *Sha256::digest(c_data_json.as_bytes())
   3384                     && reg.response.transports.is_empty()
   3385                     && matches!(reg.authenticator_attachment, AuthenticatorAttachment::None)
   3386                     && reg.client_extension_results.cred_props.is_none()
   3387                     && reg.client_extension_results.prf.is_none()
   3388             )
   3389         );
   3390         // `null` `credProps`.
   3391         assert!(
   3392             serde_json::from_str::<Registration>(
   3393                 serde_json::json!({
   3394                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3395                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3396                     "response": {
   3397                         "clientDataJSON": b64_cdata_json,
   3398                         "authenticatorData": b64_adata,
   3399                         "transports": [],
   3400                         "publicKey": b64_key,
   3401                         "publicKeyAlgorithm": -8i8,
   3402                         "attestationObject": b64_aobj,
   3403                     },
   3404                     "clientExtensionResults": {
   3405                         "credProps": null
   3406                     },
   3407                     "type": "public-key"
   3408                 })
   3409                 .to_string()
   3410                 .as_str()
   3411             )
   3412             .is_ok_and(|reg| reg.client_extension_results.cred_props.is_none()
   3413                 && reg.client_extension_results.prf.is_none())
   3414         );
   3415         // `null` `prf`.
   3416         assert!(
   3417             serde_json::from_str::<Registration>(
   3418                 serde_json::json!({
   3419                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3420                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3421                     "response": {
   3422                         "clientDataJSON": b64_cdata_json,
   3423                         "authenticatorData": b64_adata,
   3424                         "transports": [],
   3425                         "publicKey": b64_key,
   3426                         "publicKeyAlgorithm": -8i8,
   3427                         "attestationObject": b64_aobj,
   3428                     },
   3429                     "clientExtensionResults": {
   3430                         "prf": null
   3431                     },
   3432                     "type": "public-key"
   3433                 })
   3434                 .to_string()
   3435                 .as_str()
   3436             )
   3437             .is_ok_and(|reg| reg.client_extension_results.cred_props.is_none()
   3438                 && reg.client_extension_results.prf.is_none())
   3439         );
   3440         // Unknown `clientExtensionResults`.
   3441         let mut err = Error::unknown_field("CredProps", ["credProps", "prf"].as_slice())
   3442             .to_string()
   3443             .into_bytes();
   3444         assert_eq!(
   3445             serde_json::from_str::<Registration>(
   3446                 serde_json::json!({
   3447                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3448                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3449                     "response": {
   3450                         "clientDataJSON": b64_cdata_json,
   3451                         "authenticatorData": b64_adata,
   3452                         "transports": [],
   3453                         "publicKey": b64_key,
   3454                         "publicKeyAlgorithm": -8i8,
   3455                         "attestationObject": b64_aobj,
   3456                     },
   3457                     "clientExtensionResults": {
   3458                         "CredProps": {
   3459                             "rk": true
   3460                         }
   3461                     },
   3462                     "type": "public-key"
   3463                 })
   3464                 .to_string()
   3465                 .as_str()
   3466             )
   3467             .unwrap_err()
   3468             .to_string()
   3469             .into_bytes()
   3470             .get(..err.len()),
   3471             Some(err.as_slice())
   3472         );
   3473         // Duplicate field.
   3474         err = Error::duplicate_field("credProps").to_string().into_bytes();
   3475         assert_eq!(
   3476             serde_json::from_str::<Registration>(
   3477                 format!(
   3478                     "{{
   3479                        \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   3480                        \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   3481                        \"response\": {{
   3482                            \"clientDataJSON\": \"{b64_cdata_json}\",
   3483                            \"authenticatorData\": \"{b64_adata}\",
   3484                            \"transports\": [],
   3485                            \"publicKey\": \"{b64_key}\",
   3486                            \"publicKeyAlgorithm\": -8,
   3487                            \"attestationObject\": \"{b64_aobj}\"
   3488                        }},
   3489                        \"clientExtensionResults\": {{
   3490                            \"credProps\": null,
   3491                            \"credProps\": null
   3492                        }},
   3493                        \"type\": \"public-key\"
   3494                      }}"
   3495                 )
   3496                 .as_str()
   3497             )
   3498             .unwrap_err()
   3499             .to_string()
   3500             .into_bytes()
   3501             .get(..err.len()),
   3502             Some(err.as_slice())
   3503         );
   3504         // `null` `rk`.
   3505         assert!(
   3506             serde_json::from_str::<Registration>(
   3507                 serde_json::json!({
   3508                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3509                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3510                     "response": {
   3511                         "clientDataJSON": b64_cdata_json,
   3512                         "authenticatorData": b64_adata,
   3513                         "transports": [],
   3514                         "publicKey": b64_key,
   3515                         "publicKeyAlgorithm": -8i8,
   3516                         "attestationObject": b64_aobj,
   3517                     },
   3518                     "clientExtensionResults": {
   3519                         "credProps": {
   3520                             "rk": null
   3521                         }
   3522                     },
   3523                     "type": "public-key"
   3524                 })
   3525                 .to_string()
   3526                 .as_str()
   3527             )
   3528             .is_ok_and(|reg| reg
   3529                 .client_extension_results
   3530                 .cred_props
   3531                 .is_some_and(|props| props.rk.is_none())
   3532                 && reg.client_extension_results.prf.is_none())
   3533         );
   3534         // Missing `rk`.
   3535         assert!(
   3536             serde_json::from_str::<Registration>(
   3537                 serde_json::json!({
   3538                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3539                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3540                     "response": {
   3541                         "clientDataJSON": b64_cdata_json,
   3542                         "authenticatorData": b64_adata,
   3543                         "transports": [],
   3544                         "publicKey": b64_key,
   3545                         "publicKeyAlgorithm": -8i8,
   3546                         "attestationObject": b64_aobj,
   3547                     },
   3548                     "clientExtensionResults": {
   3549                         "credProps": {}
   3550                     },
   3551                     "type": "public-key"
   3552                 })
   3553                 .to_string()
   3554                 .as_str()
   3555             )
   3556             .is_ok_and(|reg| reg
   3557                 .client_extension_results
   3558                 .cred_props
   3559                 .is_some_and(|props| props.rk.is_none())
   3560                 && reg.client_extension_results.prf.is_none())
   3561         );
   3562         // `true` rk`.
   3563         assert!(
   3564             serde_json::from_str::<Registration>(
   3565                 serde_json::json!({
   3566                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3567                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3568                     "response": {
   3569                         "clientDataJSON": b64_cdata_json,
   3570                         "authenticatorData": b64_adata,
   3571                         "transports": [],
   3572                         "publicKey": b64_key,
   3573                         "publicKeyAlgorithm": -8i8,
   3574                         "attestationObject": b64_aobj,
   3575                     },
   3576                     "clientExtensionResults": {
   3577                         "credProps": {
   3578                             "rk": true
   3579                         }
   3580                     },
   3581                     "type": "public-key"
   3582                 })
   3583                 .to_string()
   3584                 .as_str()
   3585             )
   3586             .is_ok_and(|reg| reg
   3587                 .client_extension_results
   3588                 .cred_props
   3589                 .is_some_and(|props| props.rk.unwrap_or_default())
   3590                 && reg.client_extension_results.prf.is_none())
   3591         );
   3592         // `false` rk`.
   3593         assert!(
   3594             serde_json::from_str::<Registration>(
   3595                 serde_json::json!({
   3596                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3597                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3598                     "response": {
   3599                         "clientDataJSON": b64_cdata_json,
   3600                         "authenticatorData": b64_adata,
   3601                         "transports": [],
   3602                         "publicKey": b64_key,
   3603                         "publicKeyAlgorithm": -8i8,
   3604                         "attestationObject": b64_aobj,
   3605                     },
   3606                     "clientExtensionResults": {
   3607                         "credProps": {
   3608                             "rk": false
   3609                         }
   3610                     },
   3611                     "type": "public-key"
   3612                 })
   3613                 .to_string()
   3614                 .as_str()
   3615             )
   3616             .is_ok_and(|reg| reg
   3617                 .client_extension_results
   3618                 .cred_props
   3619                 .is_some_and(|props| props.rk.is_some_and(|rk| !rk))
   3620                 && reg.client_extension_results.prf.is_none())
   3621         );
   3622         // Invalid `rk`.
   3623         err = Error::invalid_type(Unexpected::Unsigned(3), &"a boolean")
   3624             .to_string()
   3625             .into_bytes();
   3626         assert_eq!(
   3627             serde_json::from_str::<Registration>(
   3628                 serde_json::json!({
   3629                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3630                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3631                     "response": {
   3632                         "clientDataJSON": b64_cdata_json,
   3633                         "authenticatorData": b64_adata,
   3634                         "transports": [],
   3635                         "publicKey": b64_key,
   3636                         "publicKeyAlgorithm": -8i8,
   3637                         "attestationObject": b64_aobj,
   3638                     },
   3639                     "clientExtensionResults": {
   3640                         "credProps": {
   3641                             "rk": 3u8
   3642                         }
   3643                     },
   3644                     "type": "public-key"
   3645                 })
   3646                 .to_string()
   3647                 .as_str()
   3648             )
   3649             .unwrap_err()
   3650             .to_string()
   3651             .into_bytes()
   3652             .get(..err.len()),
   3653             Some(err.as_slice())
   3654         );
   3655         // Unknown `credProps` field.
   3656         err = Error::unknown_field("Rk", ["rk"].as_slice())
   3657             .to_string()
   3658             .into_bytes();
   3659         assert_eq!(
   3660             serde_json::from_str::<Registration>(
   3661                 serde_json::json!({
   3662                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3663                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3664                     "response": {
   3665                         "clientDataJSON": b64_cdata_json,
   3666                         "authenticatorData": b64_adata,
   3667                         "transports": [],
   3668                         "publicKey": b64_key,
   3669                         "publicKeyAlgorithm": -8i8,
   3670                         "attestationObject": b64_aobj,
   3671                     },
   3672                     "clientExtensionResults": {
   3673                         "credProps": {
   3674                             "Rk": true,
   3675                         }
   3676                     },
   3677                     "type": "public-key"
   3678                 })
   3679                 .to_string()
   3680                 .as_str()
   3681             )
   3682             .unwrap_err()
   3683             .to_string()
   3684             .into_bytes()
   3685             .get(..err.len()),
   3686             Some(err.as_slice())
   3687         );
   3688         // Duplicate field in `credProps`.
   3689         err = Error::duplicate_field("rk").to_string().into_bytes();
   3690         assert_eq!(
   3691             serde_json::from_str::<Registration>(
   3692                 format!(
   3693                     "{{
   3694                        \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   3695                        \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   3696                        \"response\": {{
   3697                            \"clientDataJSON\": \"{b64_cdata_json}\",
   3698                            \"authenticatorData\": \"{b64_adata}\",
   3699                            \"transports\": [],
   3700                            \"publicKey\": \"{b64_key}\",
   3701                            \"publicKeyAlgorithm\": -8,
   3702                            \"attestationObject\": \"{b64_aobj}\"
   3703                        }},
   3704                        \"clientExtensionResults\": {{
   3705                            \"credProps\": {{
   3706                                \"rk\": true,
   3707                                \"rk\": true
   3708                            }}
   3709                        }},
   3710                        \"type\": \"public-key\"
   3711                      }}"
   3712                 )
   3713                 .as_str()
   3714             )
   3715             .unwrap_err()
   3716             .to_string()
   3717             .into_bytes()
   3718             .get(..err.len()),
   3719             Some(err.as_slice())
   3720         );
   3721         // `null` `enabled`.
   3722         err = Error::invalid_type(Unexpected::Other("null"), &"a boolean")
   3723             .to_string()
   3724             .into_bytes();
   3725         assert_eq!(
   3726             serde_json::from_str::<Registration>(
   3727                 serde_json::json!({
   3728                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3729                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3730                     "response": {
   3731                         "clientDataJSON": b64_cdata_json,
   3732                         "authenticatorData": b64_adata,
   3733                         "transports": [],
   3734                         "publicKey": b64_key,
   3735                         "publicKeyAlgorithm": -8i8,
   3736                         "attestationObject": b64_aobj,
   3737                     },
   3738                     "clientExtensionResults": {
   3739                         "prf": {
   3740                             "enabled": null
   3741                         }
   3742                     },
   3743                     "type": "public-key"
   3744                 })
   3745                 .to_string()
   3746                 .as_str()
   3747             )
   3748             .unwrap_err()
   3749             .to_string()
   3750             .into_bytes()
   3751             .get(..err.len()),
   3752             Some(err.as_slice())
   3753         );
   3754         // Missing `enabled`.
   3755         err = Error::missing_field("enabled").to_string().into_bytes();
   3756         assert_eq!(
   3757             serde_json::from_str::<Registration>(
   3758                 serde_json::json!({
   3759                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3760                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3761                     "response": {
   3762                         "clientDataJSON": b64_cdata_json,
   3763                         "authenticatorData": b64_adata,
   3764                         "transports": [],
   3765                         "publicKey": b64_key,
   3766                         "publicKeyAlgorithm": -8i8,
   3767                         "attestationObject": b64_aobj,
   3768                     },
   3769                     "clientExtensionResults": {
   3770                         "prf": {}
   3771                     },
   3772                     "type": "public-key"
   3773                 })
   3774                 .to_string()
   3775                 .as_str()
   3776             )
   3777             .unwrap_err()
   3778             .to_string()
   3779             .into_bytes()
   3780             .get(..err.len()),
   3781             Some(err.as_slice())
   3782         );
   3783         // `true` `enabled`.
   3784         assert!(
   3785             serde_json::from_str::<Registration>(
   3786                 serde_json::json!({
   3787                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3788                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3789                     "response": {
   3790                         "clientDataJSON": b64_cdata_json,
   3791                         "authenticatorData": b64_adata,
   3792                         "transports": [],
   3793                         "publicKey": b64_key,
   3794                         "publicKeyAlgorithm": -8i8,
   3795                         "attestationObject": b64_aobj,
   3796                     },
   3797                     "clientExtensionResults": {
   3798                         "prf": {
   3799                             "enabled": true
   3800                         }
   3801                     },
   3802                     "type": "public-key"
   3803                 })
   3804                 .to_string()
   3805                 .as_str()
   3806             )
   3807             .is_ok_and(|reg| reg.client_extension_results.cred_props.is_none()
   3808                 && reg
   3809                     .client_extension_results
   3810                     .prf
   3811                     .is_some_and(|prf| prf.enabled))
   3812         );
   3813         // `false` `enabled`.
   3814         assert!(
   3815             serde_json::from_str::<Registration>(
   3816                 serde_json::json!({
   3817                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3818                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3819                     "response": {
   3820                         "clientDataJSON": b64_cdata_json,
   3821                         "authenticatorData": b64_adata,
   3822                         "transports": [],
   3823                         "publicKey": b64_key,
   3824                         "publicKeyAlgorithm": -8i8,
   3825                         "attestationObject": b64_aobj,
   3826                     },
   3827                     "clientExtensionResults": {
   3828                         "prf": {
   3829                             "enabled": false,
   3830                         }
   3831                     },
   3832                     "type": "public-key"
   3833                 })
   3834                 .to_string()
   3835                 .as_str()
   3836             )
   3837             .is_ok_and(|reg| reg.client_extension_results.cred_props.is_none()
   3838                 && reg
   3839                     .client_extension_results
   3840                     .prf
   3841                     .is_some_and(|prf| !prf.enabled))
   3842         );
   3843         // Invalid `enabled`.
   3844         err = Error::invalid_type(Unexpected::Unsigned(3), &"a boolean")
   3845             .to_string()
   3846             .into_bytes();
   3847         assert_eq!(
   3848             serde_json::from_str::<Registration>(
   3849                 serde_json::json!({
   3850                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3851                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3852                     "response": {
   3853                         "clientDataJSON": b64_cdata_json,
   3854                         "authenticatorData": b64_adata,
   3855                         "transports": [],
   3856                         "publicKey": b64_key,
   3857                         "publicKeyAlgorithm": -8i8,
   3858                         "attestationObject": b64_aobj,
   3859                     },
   3860                     "clientExtensionResults": {
   3861                         "prf": {
   3862                             "enabled": 3u8
   3863                         }
   3864                     },
   3865                     "type": "public-key"
   3866                 })
   3867                 .to_string()
   3868                 .as_str()
   3869             )
   3870             .unwrap_err()
   3871             .to_string()
   3872             .into_bytes()
   3873             .get(..err.len()),
   3874             Some(err.as_slice())
   3875         );
   3876         // `null` `results` with `enabled` `true`.
   3877         assert!(
   3878             serde_json::from_str::<Registration>(
   3879                 serde_json::json!({
   3880                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3881                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3882                     "response": {
   3883                         "clientDataJSON": b64_cdata_json,
   3884                         "authenticatorData": b64_adata,
   3885                         "transports": [],
   3886                         "publicKey": b64_key,
   3887                         "publicKeyAlgorithm": -8i8,
   3888                         "attestationObject": b64_aobj,
   3889                     },
   3890                     "clientExtensionResults": {
   3891                         "prf": {
   3892                             "enabled": true,
   3893                             "results": null,
   3894                         }
   3895                     },
   3896                     "type": "public-key"
   3897                 })
   3898                 .to_string()
   3899                 .as_str()
   3900             )
   3901             .is_ok_and(|reg| reg.client_extension_results.cred_props.is_none()
   3902                 && reg
   3903                     .client_extension_results
   3904                     .prf
   3905                     .is_some_and(|prf| prf.enabled))
   3906         );
   3907         // `null` `results` with `enabled` `false`.
   3908         err = Error::custom(
   3909             "prf must not have 'results', including a null 'results', if 'enabled' is false",
   3910         )
   3911         .to_string()
   3912         .into_bytes();
   3913         assert_eq!(
   3914             serde_json::from_str::<Registration>(
   3915                 serde_json::json!({
   3916                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3917                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3918                     "response": {
   3919                         "clientDataJSON": b64_cdata_json,
   3920                         "authenticatorData": b64_adata,
   3921                         "transports": [],
   3922                         "publicKey": b64_key,
   3923                         "publicKeyAlgorithm": -8i8,
   3924                         "attestationObject": b64_aobj,
   3925                     },
   3926                     "clientExtensionResults": {
   3927                         "prf": {
   3928                             "enabled": false,
   3929                             "results": null
   3930                         }
   3931                     },
   3932                     "type": "public-key"
   3933                 })
   3934                 .to_string()
   3935                 .as_str()
   3936             )
   3937             .unwrap_err()
   3938             .to_string()
   3939             .into_bytes()
   3940             .get(..err.len()),
   3941             Some(err.as_slice())
   3942         );
   3943         // Duplicate field in `prf`.
   3944         err = Error::duplicate_field("enabled").to_string().into_bytes();
   3945         assert_eq!(
   3946             serde_json::from_str::<Registration>(
   3947                 format!(
   3948                     "{{
   3949                        \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   3950                        \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   3951                        \"response\": {{
   3952                            \"clientDataJSON\": \"{b64_cdata_json}\",
   3953                            \"authenticatorData\": \"{b64_adata}\",
   3954                            \"transports\": [],
   3955                            \"publicKey\": \"{b64_key}\",
   3956                            \"publicKeyAlgorithm\": -8,
   3957                            \"attestationObject\": \"{b64_aobj}\"
   3958                        }},
   3959                        \"clientExtensionResults\": {{
   3960                            \"prf\": {{
   3961                                \"enabled\": true,
   3962                                \"enabled\": true
   3963                            }}
   3964                        }},
   3965                        \"type\": \"public-key\"
   3966                      }}"
   3967                 )
   3968                 .as_str()
   3969             )
   3970             .unwrap_err()
   3971             .to_string()
   3972             .into_bytes()
   3973             .get(..err.len()),
   3974             Some(err.as_slice())
   3975         );
   3976         // Missing `first`.
   3977         err = Error::missing_field("first").to_string().into_bytes();
   3978         assert_eq!(
   3979             serde_json::from_str::<Registration>(
   3980                 serde_json::json!({
   3981                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   3982                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   3983                     "response": {
   3984                         "clientDataJSON": b64_cdata_json,
   3985                         "authenticatorData": b64_adata,
   3986                         "transports": [],
   3987                         "publicKey": b64_key,
   3988                         "publicKeyAlgorithm": -8i8,
   3989                         "attestationObject": b64_aobj,
   3990                     },
   3991                     "clientExtensionResults": {
   3992                         "prf": {
   3993                             "enabled": true,
   3994                             "results": {},
   3995                         }
   3996                     },
   3997                     "type": "public-key"
   3998                 })
   3999                 .to_string()
   4000                 .as_str()
   4001             )
   4002             .unwrap_err()
   4003             .to_string()
   4004             .into_bytes()
   4005             .get(..err.len()),
   4006             Some(err.as_slice())
   4007         );
   4008         // `null` `first`.
   4009         assert!(
   4010             serde_json::from_str::<Registration>(
   4011                 serde_json::json!({
   4012                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   4013                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   4014                     "response": {
   4015                         "clientDataJSON": b64_cdata_json,
   4016                         "authenticatorData": b64_adata,
   4017                         "transports": [],
   4018                         "publicKey": b64_key,
   4019                         "publicKeyAlgorithm": -8i8,
   4020                         "attestationObject": b64_aobj,
   4021                     },
   4022                     "clientExtensionResults": {
   4023                         "prf": {
   4024                             "enabled": true,
   4025                             "results": {
   4026                                 "first": null
   4027                             },
   4028                         }
   4029                     },
   4030                     "type": "public-key"
   4031                 })
   4032                 .to_string()
   4033                 .as_str()
   4034             )
   4035             .is_ok_and(|reg| reg.client_extension_results.cred_props.is_none()
   4036                 && reg
   4037                     .client_extension_results
   4038                     .prf
   4039                     .is_some_and(|prf| prf.enabled))
   4040         );
   4041         // `null` `second`.
   4042         assert!(
   4043             serde_json::from_str::<Registration>(
   4044                 serde_json::json!({
   4045                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   4046                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   4047                     "response": {
   4048                         "clientDataJSON": b64_cdata_json,
   4049                         "authenticatorData": b64_adata,
   4050                         "transports": [],
   4051                         "publicKey": b64_key,
   4052                         "publicKeyAlgorithm": -8i8,
   4053                         "attestationObject": b64_aobj,
   4054                     },
   4055                     "clientExtensionResults": {
   4056                         "prf": {
   4057                             "enabled": true,
   4058                             "results": {
   4059                                 "first": null,
   4060                                 "second": null
   4061                             },
   4062                         }
   4063                     },
   4064                     "type": "public-key"
   4065                 })
   4066                 .to_string()
   4067                 .as_str()
   4068             )
   4069             .is_ok_and(|reg| reg.client_extension_results.cred_props.is_none()
   4070                 && reg
   4071                     .client_extension_results
   4072                     .prf
   4073                     .is_some_and(|prf| prf.enabled))
   4074         );
   4075         // Non-`null` `first`.
   4076         err = Error::invalid_type(Unexpected::Option, &"null")
   4077             .to_string()
   4078             .into_bytes();
   4079         assert_eq!(
   4080             serde_json::from_str::<Registration>(
   4081                 serde_json::json!({
   4082                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   4083                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   4084                     "response": {
   4085                         "clientDataJSON": b64_cdata_json,
   4086                         "authenticatorData": b64_adata,
   4087                         "transports": [],
   4088                         "publicKey": b64_key,
   4089                         "publicKeyAlgorithm": -8i8,
   4090                         "attestationObject": b64_aobj,
   4091                     },
   4092                     "clientExtensionResults": {
   4093                         "prf": {
   4094                             "enabled": true,
   4095                             "results": {
   4096                                 "first": ""
   4097                             },
   4098                         }
   4099                     },
   4100                     "type": "public-key"
   4101                 })
   4102                 .to_string()
   4103                 .as_str()
   4104             )
   4105             .unwrap_err()
   4106             .to_string()
   4107             .into_bytes()
   4108             .get(..err.len()),
   4109             Some(err.as_slice())
   4110         );
   4111         // Non-`null` `second`.
   4112         err = Error::invalid_type(Unexpected::Option, &"null")
   4113             .to_string()
   4114             .into_bytes();
   4115         assert_eq!(
   4116             serde_json::from_str::<Registration>(
   4117                 serde_json::json!({
   4118                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   4119                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   4120                     "response": {
   4121                         "clientDataJSON": b64_cdata_json,
   4122                         "authenticatorData": b64_adata,
   4123                         "transports": [],
   4124                         "publicKey": b64_key,
   4125                         "publicKeyAlgorithm": -8i8,
   4126                         "attestationObject": b64_aobj,
   4127                     },
   4128                     "clientExtensionResults": {
   4129                         "prf": {
   4130                             "enabled": true,
   4131                             "results": {
   4132                                 "first": null,
   4133                                 "second": ""
   4134                             },
   4135                         }
   4136                     },
   4137                     "type": "public-key"
   4138                 })
   4139                 .to_string()
   4140                 .as_str()
   4141             )
   4142             .unwrap_err()
   4143             .to_string()
   4144             .into_bytes()
   4145             .get(..err.len()),
   4146             Some(err.as_slice())
   4147         );
   4148         // Unknown `prf` field.
   4149         err = Error::unknown_field("Results", ["enabled", "results"].as_slice())
   4150             .to_string()
   4151             .into_bytes();
   4152         assert_eq!(
   4153             serde_json::from_str::<Registration>(
   4154                 serde_json::json!({
   4155                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   4156                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   4157                     "response": {
   4158                         "clientDataJSON": b64_cdata_json,
   4159                         "authenticatorData": b64_adata,
   4160                         "transports": [],
   4161                         "publicKey": b64_key,
   4162                         "publicKeyAlgorithm": -8i8,
   4163                         "attestationObject": b64_aobj,
   4164                     },
   4165                     "clientExtensionResults": {
   4166                         "prf": {
   4167                             "enabled": true,
   4168                             "Results": null
   4169                         }
   4170                     },
   4171                     "type": "public-key"
   4172                 })
   4173                 .to_string()
   4174                 .as_str()
   4175             )
   4176             .unwrap_err()
   4177             .to_string()
   4178             .into_bytes()
   4179             .get(..err.len()),
   4180             Some(err.as_slice())
   4181         );
   4182         // Unknown `results` field.
   4183         err = Error::unknown_field("Second", ["first", "second"].as_slice())
   4184             .to_string()
   4185             .into_bytes();
   4186         assert_eq!(
   4187             serde_json::from_str::<Registration>(
   4188                 serde_json::json!({
   4189                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   4190                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   4191                     "response": {
   4192                         "clientDataJSON": b64_cdata_json,
   4193                         "authenticatorData": b64_adata,
   4194                         "transports": [],
   4195                         "publicKey": b64_key,
   4196                         "publicKeyAlgorithm": -8i8,
   4197                         "attestationObject": b64_aobj,
   4198                     },
   4199                     "clientExtensionResults": {
   4200                         "prf": {
   4201                             "enabled": true,
   4202                             "results": {
   4203                                 "first": null,
   4204                                 "Second": null
   4205                             }
   4206                         }
   4207                     },
   4208                     "type": "public-key"
   4209                 })
   4210                 .to_string()
   4211                 .as_str()
   4212             )
   4213             .unwrap_err()
   4214             .to_string()
   4215             .into_bytes()
   4216             .get(..err.len()),
   4217             Some(err.as_slice())
   4218         );
   4219         // Duplicate field in `results`.
   4220         err = Error::duplicate_field("first").to_string().into_bytes();
   4221         assert_eq!(
   4222             serde_json::from_str::<Registration>(
   4223                 format!(
   4224                     "{{
   4225                        \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   4226                        \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   4227                        \"response\": {{
   4228                            \"clientDataJSON\": \"{b64_cdata_json}\",
   4229                            \"authenticatorData\": \"{b64_adata}\",
   4230                            \"transports\": [],
   4231                            \"publicKey\": \"{b64_key}\",
   4232                            \"publicKeyAlgorithm\": -8,
   4233                            \"attestationObject\": \"{b64_aobj}\"
   4234                        }},
   4235                        \"clientExtensionResults\": {{
   4236                            \"prf\": {{
   4237                                \"enabled\": true,
   4238                                \"results\": {{
   4239                                    \"first\": null,
   4240                                    \"first\": null
   4241                                }}
   4242                            }}
   4243                        }},
   4244                        \"type\": \"public-key\"
   4245                      }}"
   4246                 )
   4247                 .as_str()
   4248             )
   4249             .unwrap_err()
   4250             .to_string()
   4251             .into_bytes()
   4252             .get(..err.len()),
   4253             Some(err.as_slice())
   4254         );
   4255     }
   4256     #[expect(
   4257         clippy::assertions_on_result_states,
   4258         clippy::unwrap_used,
   4259         reason = "OK in tests"
   4260     )]
   4261     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
   4262     #[expect(clippy::too_many_lines, reason = "a lot to test")]
   4263     #[test]
   4264     fn mldsa87_registration_deserialize_data_mismatch() {
   4265         let c_data_json = serde_json::json!({}).to_string();
   4266         let att_obj: [u8; 2704] = [
   4267             cbor::MAP_3,
   4268             cbor::TEXT_3,
   4269             b'f',
   4270             b'm',
   4271             b't',
   4272             cbor::TEXT_4,
   4273             b'n',
   4274             b'o',
   4275             b'n',
   4276             b'e',
   4277             cbor::TEXT_7,
   4278             b'a',
   4279             b't',
   4280             b't',
   4281             b'S',
   4282             b't',
   4283             b'm',
   4284             b't',
   4285             cbor::MAP_0,
   4286             cbor::TEXT_8,
   4287             b'a',
   4288             b'u',
   4289             b't',
   4290             b'h',
   4291             b'D',
   4292             b'a',
   4293             b't',
   4294             b'a',
   4295             cbor::BYTES_INFO_25,
   4296             10,
   4297             113,
   4298             // `rpIdHash`.
   4299             0,
   4300             0,
   4301             0,
   4302             0,
   4303             0,
   4304             0,
   4305             0,
   4306             0,
   4307             0,
   4308             0,
   4309             0,
   4310             0,
   4311             0,
   4312             0,
   4313             0,
   4314             0,
   4315             0,
   4316             0,
   4317             0,
   4318             0,
   4319             0,
   4320             0,
   4321             0,
   4322             0,
   4323             0,
   4324             0,
   4325             0,
   4326             0,
   4327             0,
   4328             0,
   4329             0,
   4330             0,
   4331             // `flags`.
   4332             0b0100_0101,
   4333             // `signCount`.
   4334             0,
   4335             0,
   4336             0,
   4337             0,
   4338             // `aaguid`.
   4339             0,
   4340             0,
   4341             0,
   4342             0,
   4343             0,
   4344             0,
   4345             0,
   4346             0,
   4347             0,
   4348             0,
   4349             0,
   4350             0,
   4351             0,
   4352             0,
   4353             0,
   4354             0,
   4355             // `credentialIdLength`.
   4356             0,
   4357             16,
   4358             // `credentialId`.
   4359             0,
   4360             0,
   4361             0,
   4362             0,
   4363             0,
   4364             0,
   4365             0,
   4366             0,
   4367             0,
   4368             0,
   4369             0,
   4370             0,
   4371             0,
   4372             0,
   4373             0,
   4374             0,
   4375             // ML-DSA-87 COSE key.
   4376             cbor::MAP_3,
   4377             KTY,
   4378             AKP,
   4379             ALG,
   4380             cbor::NEG_INFO_24,
   4381             MLDSA87,
   4382             // `pub`.
   4383             cbor::NEG_ONE,
   4384             cbor::BYTES_INFO_25,
   4385             10,
   4386             32,
   4387             // Encoded key.
   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             1,
   5862             1,
   5863             1,
   5864             1,
   5865             1,
   5866             1,
   5867             1,
   5868             1,
   5869             1,
   5870             1,
   5871             1,
   5872             1,
   5873             1,
   5874             1,
   5875             1,
   5876             1,
   5877             1,
   5878             1,
   5879             1,
   5880             1,
   5881             1,
   5882             1,
   5883             1,
   5884             1,
   5885             1,
   5886             1,
   5887             1,
   5888             1,
   5889             1,
   5890             1,
   5891             1,
   5892             1,
   5893             1,
   5894             1,
   5895             1,
   5896             1,
   5897             1,
   5898             1,
   5899             1,
   5900             1,
   5901             1,
   5902             1,
   5903             1,
   5904             1,
   5905             1,
   5906             1,
   5907             1,
   5908             1,
   5909             1,
   5910             1,
   5911             1,
   5912             1,
   5913             1,
   5914             1,
   5915             1,
   5916             1,
   5917             1,
   5918             1,
   5919             1,
   5920             1,
   5921             1,
   5922             1,
   5923             1,
   5924             1,
   5925             1,
   5926             1,
   5927             1,
   5928             1,
   5929             1,
   5930             1,
   5931             1,
   5932             1,
   5933             1,
   5934             1,
   5935             1,
   5936             1,
   5937             1,
   5938             1,
   5939             1,
   5940             1,
   5941             1,
   5942             1,
   5943             1,
   5944             1,
   5945             1,
   5946             1,
   5947             1,
   5948             1,
   5949             1,
   5950             1,
   5951             1,
   5952             1,
   5953             1,
   5954             1,
   5955             1,
   5956             1,
   5957             1,
   5958             1,
   5959             1,
   5960             1,
   5961             1,
   5962             1,
   5963             1,
   5964             1,
   5965             1,
   5966             1,
   5967             1,
   5968             1,
   5969             1,
   5970             1,
   5971             1,
   5972             1,
   5973             1,
   5974             1,
   5975             1,
   5976             1,
   5977             1,
   5978             1,
   5979             1,
   5980             1,
   5981             1,
   5982             1,
   5983             1,
   5984             1,
   5985             1,
   5986             1,
   5987             1,
   5988             1,
   5989             1,
   5990             1,
   5991             1,
   5992             1,
   5993             1,
   5994             1,
   5995             1,
   5996             1,
   5997             1,
   5998             1,
   5999             1,
   6000             1,
   6001             1,
   6002             1,
   6003             1,
   6004             1,
   6005             1,
   6006             1,
   6007             1,
   6008             1,
   6009             1,
   6010             1,
   6011             1,
   6012             1,
   6013             1,
   6014             1,
   6015             1,
   6016             1,
   6017             1,
   6018             1,
   6019             1,
   6020             1,
   6021             1,
   6022             1,
   6023             1,
   6024             1,
   6025             1,
   6026             1,
   6027             1,
   6028             1,
   6029             1,
   6030             1,
   6031             1,
   6032             1,
   6033             1,
   6034             1,
   6035             1,
   6036             1,
   6037             1,
   6038             1,
   6039             1,
   6040             1,
   6041             1,
   6042             1,
   6043             1,
   6044             1,
   6045             1,
   6046             1,
   6047             1,
   6048             1,
   6049             1,
   6050             1,
   6051             1,
   6052             1,
   6053             1,
   6054             1,
   6055             1,
   6056             1,
   6057             1,
   6058             1,
   6059             1,
   6060             1,
   6061             1,
   6062             1,
   6063             1,
   6064             1,
   6065             1,
   6066             1,
   6067             1,
   6068             1,
   6069             1,
   6070             1,
   6071             1,
   6072             1,
   6073             1,
   6074             1,
   6075             1,
   6076             1,
   6077             1,
   6078             1,
   6079             1,
   6080             1,
   6081             1,
   6082             1,
   6083             1,
   6084             1,
   6085             1,
   6086             1,
   6087             1,
   6088             1,
   6089             1,
   6090             1,
   6091             1,
   6092             1,
   6093             1,
   6094             1,
   6095             1,
   6096             1,
   6097             1,
   6098             1,
   6099             1,
   6100             1,
   6101             1,
   6102             1,
   6103             1,
   6104             1,
   6105             1,
   6106             1,
   6107             1,
   6108             1,
   6109             1,
   6110             1,
   6111             1,
   6112             1,
   6113             1,
   6114             1,
   6115             1,
   6116             1,
   6117             1,
   6118             1,
   6119             1,
   6120             1,
   6121             1,
   6122             1,
   6123             1,
   6124             1,
   6125             1,
   6126             1,
   6127             1,
   6128             1,
   6129             1,
   6130             1,
   6131             1,
   6132             1,
   6133             1,
   6134             1,
   6135             1,
   6136             1,
   6137             1,
   6138             1,
   6139             1,
   6140             1,
   6141             1,
   6142             1,
   6143             1,
   6144             1,
   6145             1,
   6146             1,
   6147             1,
   6148             1,
   6149             1,
   6150             1,
   6151             1,
   6152             1,
   6153             1,
   6154             1,
   6155             1,
   6156             1,
   6157             1,
   6158             1,
   6159             1,
   6160             1,
   6161             1,
   6162             1,
   6163             1,
   6164             1,
   6165             1,
   6166             1,
   6167             1,
   6168             1,
   6169             1,
   6170             1,
   6171             1,
   6172             1,
   6173             1,
   6174             1,
   6175             1,
   6176             1,
   6177             1,
   6178             1,
   6179             1,
   6180             1,
   6181             1,
   6182             1,
   6183             1,
   6184             1,
   6185             1,
   6186             1,
   6187             1,
   6188             1,
   6189             1,
   6190             1,
   6191             1,
   6192             1,
   6193             1,
   6194             1,
   6195             1,
   6196             1,
   6197             1,
   6198             1,
   6199             1,
   6200             1,
   6201             1,
   6202             1,
   6203             1,
   6204             1,
   6205             1,
   6206             1,
   6207             1,
   6208             1,
   6209             1,
   6210             1,
   6211             1,
   6212             1,
   6213             1,
   6214             1,
   6215             1,
   6216             1,
   6217             1,
   6218             1,
   6219             1,
   6220             1,
   6221             1,
   6222             1,
   6223             1,
   6224             1,
   6225             1,
   6226             1,
   6227             1,
   6228             1,
   6229             1,
   6230             1,
   6231             1,
   6232             1,
   6233             1,
   6234             1,
   6235             1,
   6236             1,
   6237             1,
   6238             1,
   6239             1,
   6240             1,
   6241             1,
   6242             1,
   6243             1,
   6244             1,
   6245             1,
   6246             1,
   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         ];
   6981         let pub_key = MlDsaVerKey::<MlDsa87>::decode(&[1u8; 2592].into())
   6982             .to_public_key_der()
   6983             .unwrap();
   6984         let att_obj_len = att_obj.len();
   6985         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
   6986         let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 2673..]);
   6987         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
   6988         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
   6989         // Base case is valid.
   6990         assert!(
   6991             serde_json::from_str::<Registration>(
   6992                 serde_json::json!({
   6993                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   6994                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   6995                     "response": {
   6996                         "clientDataJSON": b64_cdata_json,
   6997                         "authenticatorData": b64_adata,
   6998                         "transports": [],
   6999                         "publicKey": b64_key,
   7000                         "publicKeyAlgorithm": -50i8,
   7001                         "attestationObject": b64_aobj,
   7002                     },
   7003                     "clientExtensionResults": {},
   7004                     "type": "public-key"
   7005                 })
   7006                 .to_string()
   7007                 .as_str()
   7008             )
   7009             .is_ok_and(
   7010                 |reg| reg.response.client_data_json == c_data_json.as_bytes()
   7011                     && reg.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
   7012                     && reg.response.attestation_object_and_c_data_hash[att_obj_len..]
   7013                         == *Sha256::digest(c_data_json.as_bytes())
   7014                     && reg.response.transports.is_empty()
   7015                     && matches!(reg.authenticator_attachment, AuthenticatorAttachment::None)
   7016                     && reg.client_extension_results.cred_props.is_none()
   7017                     && reg.client_extension_results.prf.is_none()
   7018             )
   7019         );
   7020         // `publicKeyAlgorithm` mismatch.
   7021         let mut err = Error::invalid_value(
   7022             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
   7023             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa87).as_str()
   7024         )
   7025         .to_string().into_bytes();
   7026         assert_eq!(
   7027             serde_json::from_str::<Registration>(
   7028                 serde_json::json!({
   7029                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7030                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7031                     "response": {
   7032                         "clientDataJSON": b64_cdata_json,
   7033                         "authenticatorData": b64_adata,
   7034                         "transports": [],
   7035                         "publicKey": b64_key,
   7036                         "publicKeyAlgorithm": -8i8,
   7037                         "attestationObject": b64_aobj,
   7038                     },
   7039                     "clientExtensionResults": {},
   7040                     "type": "public-key"
   7041                 })
   7042                 .to_string()
   7043                 .as_str()
   7044             )
   7045             .unwrap_err()
   7046             .to_string()
   7047             .into_bytes()
   7048             .get(..err.len()),
   7049             Some(err.as_slice())
   7050         );
   7051         // Missing `publicKeyAlgorithm`.
   7052         err = Error::missing_field("publicKeyAlgorithm")
   7053             .to_string()
   7054             .into_bytes();
   7055         assert_eq!(
   7056             serde_json::from_str::<Registration>(
   7057                 serde_json::json!({
   7058                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7059                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7060                     "response": {
   7061                         "clientDataJSON": b64_cdata_json,
   7062                         "authenticatorData": b64_adata,
   7063                         "transports": [],
   7064                         "publicKey": b64_key,
   7065                         "attestationObject": b64_aobj,
   7066                     },
   7067                     "clientExtensionResults": {},
   7068                     "type": "public-key"
   7069                 })
   7070                 .to_string()
   7071                 .as_str()
   7072             )
   7073             .unwrap_err()
   7074             .to_string()
   7075             .into_bytes()
   7076             .get(..err.len()),
   7077             Some(err.as_slice())
   7078         );
   7079         // `null` `publicKeyAlgorithm`.
   7080         err = Error::invalid_type(Unexpected::Other("null"), &"publicKeyAlgorithm")
   7081             .to_string()
   7082             .into_bytes();
   7083         assert_eq!(
   7084             serde_json::from_str::<Registration>(
   7085                 serde_json::json!({
   7086                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7087                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7088                     "response": {
   7089                         "clientDataJSON": b64_cdata_json,
   7090                         "authenticatorData": b64_adata,
   7091                         "transports": [],
   7092                         "publicKey": b64_key,
   7093                         "publicKeyAlgorithm": null,
   7094                         "attestationObject": b64_aobj,
   7095                     },
   7096                     "clientExtensionResults": {},
   7097                     "type": "public-key"
   7098                 })
   7099                 .to_string()
   7100                 .as_str()
   7101             )
   7102             .unwrap_err()
   7103             .to_string()
   7104             .into_bytes()
   7105             .get(..err.len()),
   7106             Some(err.as_slice())
   7107         );
   7108         // `publicKey` mismatch.
   7109         let bad_pub_key = MlDsaVerKey::<MlDsa87>::decode(&[2; 2592].into());
   7110         err = Error::invalid_value(
   7111             Unexpected::Bytes([0; 32].as_slice()),
   7112             &format!(
   7113                 "DER-encoded public key to match the public key within the attestation object: MlDsa87(MlDsa87PubKey({:?}))",
   7114                 &[1u8; 2592]
   7115             )
   7116             .as_str(),
   7117         )
   7118         .to_string().into_bytes();
   7119         assert_eq!(serde_json::from_str::<Registration>(
   7120             serde_json::json!({
   7121                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7122                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7123                 "response": {
   7124                     "clientDataJSON": b64_cdata_json,
   7125                     "authenticatorData": b64_adata,
   7126                     "transports": [],
   7127                     "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
   7128                     "publicKeyAlgorithm": -50i8,
   7129                     "attestationObject": b64_aobj,
   7130                 },
   7131                 "clientExtensionResults": {},
   7132                 "type": "public-key"
   7133             })
   7134             .to_string()
   7135             .as_str()
   7136             )
   7137             .unwrap_err().to_string().into_bytes().get(..err.len()),
   7138             Some(err.as_slice())
   7139         );
   7140         // Missing `publicKey` is allowed when not using EdDSA, ES256, or RS256.
   7141         assert!(
   7142             serde_json::from_str::<Registration>(
   7143                 serde_json::json!({
   7144                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7145                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7146                     "response": {
   7147                         "clientDataJSON": b64_cdata_json,
   7148                         "authenticatorData": b64_adata,
   7149                         "transports": [],
   7150                         "publicKeyAlgorithm": -50i8,
   7151                         "attestationObject": b64_aobj,
   7152                     },
   7153                     "clientExtensionResults": {},
   7154                     "type": "public-key"
   7155                 })
   7156                 .to_string()
   7157                 .as_str()
   7158             )
   7159             .is_ok()
   7160         );
   7161         // `publicKeyAlgorithm` mismatch when `publicKey` does not exist.
   7162         err = Error::invalid_value(
   7163             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   7164             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa87).as_str()
   7165         )
   7166         .to_string().into_bytes();
   7167         assert_eq!(
   7168             serde_json::from_str::<Registration>(
   7169                 serde_json::json!({
   7170                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7171                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7172                     "response": {
   7173                         "clientDataJSON": b64_cdata_json,
   7174                         "authenticatorData": b64_adata,
   7175                         "transports": [],
   7176                         "publicKeyAlgorithm": -7i8,
   7177                         "attestationObject": b64_aobj,
   7178                     },
   7179                     "clientExtensionResults": {},
   7180                     "type": "public-key"
   7181                 })
   7182                 .to_string()
   7183                 .as_str()
   7184             )
   7185             .unwrap_err()
   7186             .to_string()
   7187             .into_bytes()
   7188             .get(..err.len()),
   7189             Some(err.as_slice())
   7190         );
   7191         // `null` `publicKey` is allowed when not using EdDSA, ES256, or RS256.
   7192         assert!(
   7193             serde_json::from_str::<Registration>(
   7194                 serde_json::json!({
   7195                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7196                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7197                     "response": {
   7198                         "clientDataJSON": b64_cdata_json,
   7199                         "authenticatorData": b64_adata,
   7200                         "transports": [],
   7201                         "publicKey": null,
   7202                         "publicKeyAlgorithm": -50i8,
   7203                         "attestationObject": b64_aobj,
   7204                     },
   7205                     "clientExtensionResults": {},
   7206                     "type": "public-key"
   7207                 })
   7208                 .to_string()
   7209                 .as_str()
   7210             )
   7211             .is_ok()
   7212         );
   7213         // `publicKeyAlgorithm` mismatch when `publicKey` is null.
   7214         err = Error::invalid_value(
   7215             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   7216             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa87).as_str()
   7217         )
   7218         .to_string().into_bytes();
   7219         assert_eq!(
   7220             serde_json::from_str::<Registration>(
   7221                 serde_json::json!({
   7222                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7223                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7224                     "response": {
   7225                         "clientDataJSON": b64_cdata_json,
   7226                         "authenticatorData": b64_adata,
   7227                         "transports": [],
   7228                         "publicKey": null,
   7229                         "publicKeyAlgorithm": -7i8,
   7230                         "attestationObject": b64_aobj,
   7231                     },
   7232                     "clientExtensionResults": {},
   7233                     "type": "public-key"
   7234                 })
   7235                 .to_string()
   7236                 .as_str()
   7237             )
   7238             .unwrap_err()
   7239             .to_string()
   7240             .into_bytes()
   7241             .get(..err.len()),
   7242             Some(err.as_slice())
   7243         );
   7244     }
   7245     #[expect(
   7246         clippy::assertions_on_result_states,
   7247         clippy::unwrap_used,
   7248         reason = "OK in tests"
   7249     )]
   7250     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
   7251     #[expect(clippy::too_many_lines, reason = "a lot to test")]
   7252     #[test]
   7253     fn mldsa65_registration_deserialize_data_mismatch() {
   7254         let c_data_json = serde_json::json!({}).to_string();
   7255         let att_obj: [u8; 2064] = [
   7256             cbor::MAP_3,
   7257             cbor::TEXT_3,
   7258             b'f',
   7259             b'm',
   7260             b't',
   7261             cbor::TEXT_4,
   7262             b'n',
   7263             b'o',
   7264             b'n',
   7265             b'e',
   7266             cbor::TEXT_7,
   7267             b'a',
   7268             b't',
   7269             b't',
   7270             b'S',
   7271             b't',
   7272             b'm',
   7273             b't',
   7274             cbor::MAP_0,
   7275             cbor::TEXT_8,
   7276             b'a',
   7277             b'u',
   7278             b't',
   7279             b'h',
   7280             b'D',
   7281             b'a',
   7282             b't',
   7283             b'a',
   7284             cbor::BYTES_INFO_25,
   7285             7,
   7286             241,
   7287             // `rpIdHash`.
   7288             0,
   7289             0,
   7290             0,
   7291             0,
   7292             0,
   7293             0,
   7294             0,
   7295             0,
   7296             0,
   7297             0,
   7298             0,
   7299             0,
   7300             0,
   7301             0,
   7302             0,
   7303             0,
   7304             0,
   7305             0,
   7306             0,
   7307             0,
   7308             0,
   7309             0,
   7310             0,
   7311             0,
   7312             0,
   7313             0,
   7314             0,
   7315             0,
   7316             0,
   7317             0,
   7318             0,
   7319             0,
   7320             // `flags`.
   7321             0b0100_0101,
   7322             // `signCount`.
   7323             0,
   7324             0,
   7325             0,
   7326             0,
   7327             // `aaguid`.
   7328             0,
   7329             0,
   7330             0,
   7331             0,
   7332             0,
   7333             0,
   7334             0,
   7335             0,
   7336             0,
   7337             0,
   7338             0,
   7339             0,
   7340             0,
   7341             0,
   7342             0,
   7343             0,
   7344             // `credentialIdLength`.
   7345             0,
   7346             16,
   7347             // `credentialId`.
   7348             0,
   7349             0,
   7350             0,
   7351             0,
   7352             0,
   7353             0,
   7354             0,
   7355             0,
   7356             0,
   7357             0,
   7358             0,
   7359             0,
   7360             0,
   7361             0,
   7362             0,
   7363             0,
   7364             // ML-DSA-65 COSE key.
   7365             cbor::MAP_3,
   7366             KTY,
   7367             AKP,
   7368             ALG,
   7369             cbor::NEG_INFO_24,
   7370             MLDSA65,
   7371             // `pub`.
   7372             cbor::NEG_ONE,
   7373             cbor::BYTES_INFO_25,
   7374             7,
   7375             160,
   7376             // Encoded key.
   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             1,
   8200             1,
   8201             1,
   8202             1,
   8203             1,
   8204             1,
   8205             1,
   8206             1,
   8207             1,
   8208             1,
   8209             1,
   8210             1,
   8211             1,
   8212             1,
   8213             1,
   8214             1,
   8215             1,
   8216             1,
   8217             1,
   8218             1,
   8219             1,
   8220             1,
   8221             1,
   8222             1,
   8223             1,
   8224             1,
   8225             1,
   8226             1,
   8227             1,
   8228             1,
   8229             1,
   8230             1,
   8231             1,
   8232             1,
   8233             1,
   8234             1,
   8235             1,
   8236             1,
   8237             1,
   8238             1,
   8239             1,
   8240             1,
   8241             1,
   8242             1,
   8243             1,
   8244             1,
   8245             1,
   8246             1,
   8247             1,
   8248             1,
   8249             1,
   8250             1,
   8251             1,
   8252             1,
   8253             1,
   8254             1,
   8255             1,
   8256             1,
   8257             1,
   8258             1,
   8259             1,
   8260             1,
   8261             1,
   8262             1,
   8263             1,
   8264             1,
   8265             1,
   8266             1,
   8267             1,
   8268             1,
   8269             1,
   8270             1,
   8271             1,
   8272             1,
   8273             1,
   8274             1,
   8275             1,
   8276             1,
   8277             1,
   8278             1,
   8279             1,
   8280             1,
   8281             1,
   8282             1,
   8283             1,
   8284             1,
   8285             1,
   8286             1,
   8287             1,
   8288             1,
   8289             1,
   8290             1,
   8291             1,
   8292             1,
   8293             1,
   8294             1,
   8295             1,
   8296             1,
   8297             1,
   8298             1,
   8299             1,
   8300             1,
   8301             1,
   8302             1,
   8303             1,
   8304             1,
   8305             1,
   8306             1,
   8307             1,
   8308             1,
   8309             1,
   8310             1,
   8311             1,
   8312             1,
   8313             1,
   8314             1,
   8315             1,
   8316             1,
   8317             1,
   8318             1,
   8319             1,
   8320             1,
   8321             1,
   8322             1,
   8323             1,
   8324             1,
   8325             1,
   8326             1,
   8327             1,
   8328             1,
   8329             1,
   8330             1,
   8331             1,
   8332             1,
   8333             1,
   8334             1,
   8335             1,
   8336             1,
   8337             1,
   8338             1,
   8339             1,
   8340             1,
   8341             1,
   8342             1,
   8343             1,
   8344             1,
   8345             1,
   8346             1,
   8347             1,
   8348             1,
   8349             1,
   8350             1,
   8351             1,
   8352             1,
   8353             1,
   8354             1,
   8355             1,
   8356             1,
   8357             1,
   8358             1,
   8359             1,
   8360             1,
   8361             1,
   8362             1,
   8363             1,
   8364             1,
   8365             1,
   8366             1,
   8367             1,
   8368             1,
   8369             1,
   8370             1,
   8371             1,
   8372             1,
   8373             1,
   8374             1,
   8375             1,
   8376             1,
   8377             1,
   8378             1,
   8379             1,
   8380             1,
   8381             1,
   8382             1,
   8383             1,
   8384             1,
   8385             1,
   8386             1,
   8387             1,
   8388             1,
   8389             1,
   8390             1,
   8391             1,
   8392             1,
   8393             1,
   8394             1,
   8395             1,
   8396             1,
   8397             1,
   8398             1,
   8399             1,
   8400             1,
   8401             1,
   8402             1,
   8403             1,
   8404             1,
   8405             1,
   8406             1,
   8407             1,
   8408             1,
   8409             1,
   8410             1,
   8411             1,
   8412             1,
   8413             1,
   8414             1,
   8415             1,
   8416             1,
   8417             1,
   8418             1,
   8419             1,
   8420             1,
   8421             1,
   8422             1,
   8423             1,
   8424             1,
   8425             1,
   8426             1,
   8427             1,
   8428             1,
   8429             1,
   8430             1,
   8431             1,
   8432             1,
   8433             1,
   8434             1,
   8435             1,
   8436             1,
   8437             1,
   8438             1,
   8439             1,
   8440             1,
   8441             1,
   8442             1,
   8443             1,
   8444             1,
   8445             1,
   8446             1,
   8447             1,
   8448             1,
   8449             1,
   8450             1,
   8451             1,
   8452             1,
   8453             1,
   8454             1,
   8455             1,
   8456             1,
   8457             1,
   8458             1,
   8459             1,
   8460             1,
   8461             1,
   8462             1,
   8463             1,
   8464             1,
   8465             1,
   8466             1,
   8467             1,
   8468             1,
   8469             1,
   8470             1,
   8471             1,
   8472             1,
   8473             1,
   8474             1,
   8475             1,
   8476             1,
   8477             1,
   8478             1,
   8479             1,
   8480             1,
   8481             1,
   8482             1,
   8483             1,
   8484             1,
   8485             1,
   8486             1,
   8487             1,
   8488             1,
   8489             1,
   8490             1,
   8491             1,
   8492             1,
   8493             1,
   8494             1,
   8495             1,
   8496             1,
   8497             1,
   8498             1,
   8499             1,
   8500             1,
   8501             1,
   8502             1,
   8503             1,
   8504             1,
   8505             1,
   8506             1,
   8507             1,
   8508             1,
   8509             1,
   8510             1,
   8511             1,
   8512             1,
   8513             1,
   8514             1,
   8515             1,
   8516             1,
   8517             1,
   8518             1,
   8519             1,
   8520             1,
   8521             1,
   8522             1,
   8523             1,
   8524             1,
   8525             1,
   8526             1,
   8527             1,
   8528             1,
   8529             1,
   8530             1,
   8531             1,
   8532             1,
   8533             1,
   8534             1,
   8535             1,
   8536             1,
   8537             1,
   8538             1,
   8539             1,
   8540             1,
   8541             1,
   8542             1,
   8543             1,
   8544             1,
   8545             1,
   8546             1,
   8547             1,
   8548             1,
   8549             1,
   8550             1,
   8551             1,
   8552             1,
   8553             1,
   8554             1,
   8555             1,
   8556             1,
   8557             1,
   8558             1,
   8559             1,
   8560             1,
   8561             1,
   8562             1,
   8563             1,
   8564             1,
   8565             1,
   8566             1,
   8567             1,
   8568             1,
   8569             1,
   8570             1,
   8571             1,
   8572             1,
   8573             1,
   8574             1,
   8575             1,
   8576             1,
   8577             1,
   8578             1,
   8579             1,
   8580             1,
   8581             1,
   8582             1,
   8583             1,
   8584             1,
   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         ];
   9330         let pub_key = MlDsaVerKey::<MlDsa65>::decode(&[1u8; 1952].into())
   9331             .to_public_key_der()
   9332             .unwrap();
   9333         let att_obj_len = att_obj.len();
   9334         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
   9335         let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 2033..]);
   9336         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
   9337         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
   9338         // Base case is valid.
   9339         assert!(
   9340             serde_json::from_str::<Registration>(
   9341                 serde_json::json!({
   9342                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9343                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9344                     "response": {
   9345                         "clientDataJSON": b64_cdata_json,
   9346                         "authenticatorData": b64_adata,
   9347                         "transports": [],
   9348                         "publicKey": b64_key,
   9349                         "publicKeyAlgorithm": -49i8,
   9350                         "attestationObject": b64_aobj,
   9351                     },
   9352                     "clientExtensionResults": {},
   9353                     "type": "public-key"
   9354                 })
   9355                 .to_string()
   9356                 .as_str()
   9357             )
   9358             .is_ok_and(
   9359                 |reg| reg.response.client_data_json == c_data_json.as_bytes()
   9360                     && reg.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
   9361                     && reg.response.attestation_object_and_c_data_hash[att_obj_len..]
   9362                         == *Sha256::digest(c_data_json.as_bytes())
   9363                     && reg.response.transports.is_empty()
   9364                     && matches!(reg.authenticator_attachment, AuthenticatorAttachment::None)
   9365                     && reg.client_extension_results.cred_props.is_none()
   9366                     && reg.client_extension_results.prf.is_none()
   9367             )
   9368         );
   9369         // `publicKeyAlgorithm` mismatch.
   9370         let mut err = Error::invalid_value(
   9371             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
   9372             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa65).as_str()
   9373         )
   9374         .to_string().into_bytes();
   9375         assert_eq!(
   9376             serde_json::from_str::<Registration>(
   9377                 serde_json::json!({
   9378                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9379                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9380                     "response": {
   9381                         "clientDataJSON": b64_cdata_json,
   9382                         "authenticatorData": b64_adata,
   9383                         "transports": [],
   9384                         "publicKey": b64_key,
   9385                         "publicKeyAlgorithm": -8i8,
   9386                         "attestationObject": b64_aobj,
   9387                     },
   9388                     "clientExtensionResults": {},
   9389                     "type": "public-key"
   9390                 })
   9391                 .to_string()
   9392                 .as_str()
   9393             )
   9394             .unwrap_err()
   9395             .to_string()
   9396             .into_bytes()
   9397             .get(..err.len()),
   9398             Some(err.as_slice())
   9399         );
   9400         // Missing `publicKeyAlgorithm`.
   9401         err = Error::missing_field("publicKeyAlgorithm")
   9402             .to_string()
   9403             .into_bytes();
   9404         assert_eq!(
   9405             serde_json::from_str::<Registration>(
   9406                 serde_json::json!({
   9407                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9408                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9409                     "response": {
   9410                         "clientDataJSON": b64_cdata_json,
   9411                         "authenticatorData": b64_adata,
   9412                         "transports": [],
   9413                         "publicKey": b64_key,
   9414                         "attestationObject": b64_aobj,
   9415                     },
   9416                     "clientExtensionResults": {},
   9417                     "type": "public-key"
   9418                 })
   9419                 .to_string()
   9420                 .as_str()
   9421             )
   9422             .unwrap_err()
   9423             .to_string()
   9424             .into_bytes()
   9425             .get(..err.len()),
   9426             Some(err.as_slice())
   9427         );
   9428         // `null` `publicKeyAlgorithm`.
   9429         err = Error::invalid_type(Unexpected::Other("null"), &"publicKeyAlgorithm")
   9430             .to_string()
   9431             .into_bytes();
   9432         assert_eq!(
   9433             serde_json::from_str::<Registration>(
   9434                 serde_json::json!({
   9435                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9436                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9437                     "response": {
   9438                         "clientDataJSON": b64_cdata_json,
   9439                         "authenticatorData": b64_adata,
   9440                         "transports": [],
   9441                         "publicKey": b64_key,
   9442                         "publicKeyAlgorithm": null,
   9443                         "attestationObject": b64_aobj,
   9444                     },
   9445                     "clientExtensionResults": {},
   9446                     "type": "public-key"
   9447                 })
   9448                 .to_string()
   9449                 .as_str()
   9450             )
   9451             .unwrap_err()
   9452             .to_string()
   9453             .into_bytes()
   9454             .get(..err.len()),
   9455             Some(err.as_slice())
   9456         );
   9457         // `publicKey` mismatch.
   9458         let bad_pub_key = MlDsaVerKey::<MlDsa65>::decode(&[2; 1952].into());
   9459         err = Error::invalid_value(
   9460             Unexpected::Bytes([0; 32].as_slice()),
   9461             &format!(
   9462                 "DER-encoded public key to match the public key within the attestation object: MlDsa65(MlDsa65PubKey({:?}))",
   9463                 &[1u8; 1952]
   9464             )
   9465             .as_str(),
   9466         )
   9467         .to_string().into_bytes();
   9468         assert_eq!(serde_json::from_str::<Registration>(
   9469             serde_json::json!({
   9470                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9471                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9472                 "response": {
   9473                     "clientDataJSON": b64_cdata_json,
   9474                     "authenticatorData": b64_adata,
   9475                     "transports": [],
   9476                     "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
   9477                     "publicKeyAlgorithm": -49i8,
   9478                     "attestationObject": b64_aobj,
   9479                 },
   9480                 "clientExtensionResults": {},
   9481                 "type": "public-key"
   9482             })
   9483             .to_string()
   9484             .as_str()
   9485             )
   9486             .unwrap_err().to_string().into_bytes().get(..err.len()),
   9487             Some(err.as_slice())
   9488         );
   9489         // Missing `publicKey` is allowed when not using EdDSA, ES256, or RS256.
   9490         assert!(
   9491             serde_json::from_str::<Registration>(
   9492                 serde_json::json!({
   9493                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9494                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9495                     "response": {
   9496                         "clientDataJSON": b64_cdata_json,
   9497                         "authenticatorData": b64_adata,
   9498                         "transports": [],
   9499                         "publicKeyAlgorithm": -49i8,
   9500                         "attestationObject": b64_aobj,
   9501                     },
   9502                     "clientExtensionResults": {},
   9503                     "type": "public-key"
   9504                 })
   9505                 .to_string()
   9506                 .as_str()
   9507             )
   9508             .is_ok()
   9509         );
   9510         // `publicKeyAlgorithm` mismatch when `publicKey` does not exist.
   9511         err = Error::invalid_value(
   9512             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   9513             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa65).as_str()
   9514         )
   9515         .to_string().into_bytes();
   9516         assert_eq!(
   9517             serde_json::from_str::<Registration>(
   9518                 serde_json::json!({
   9519                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9520                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9521                     "response": {
   9522                         "clientDataJSON": b64_cdata_json,
   9523                         "authenticatorData": b64_adata,
   9524                         "transports": [],
   9525                         "publicKeyAlgorithm": -7i8,
   9526                         "attestationObject": b64_aobj,
   9527                     },
   9528                     "clientExtensionResults": {},
   9529                     "type": "public-key"
   9530                 })
   9531                 .to_string()
   9532                 .as_str()
   9533             )
   9534             .unwrap_err()
   9535             .to_string()
   9536             .into_bytes()
   9537             .get(..err.len()),
   9538             Some(err.as_slice())
   9539         );
   9540         // `null` `publicKey` is allowed when not using EdDSA, ES256, or RS256.
   9541         assert!(
   9542             serde_json::from_str::<Registration>(
   9543                 serde_json::json!({
   9544                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9545                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9546                     "response": {
   9547                         "clientDataJSON": b64_cdata_json,
   9548                         "authenticatorData": b64_adata,
   9549                         "transports": [],
   9550                         "publicKey": null,
   9551                         "publicKeyAlgorithm": -49i8,
   9552                         "attestationObject": b64_aobj,
   9553                     },
   9554                     "clientExtensionResults": {},
   9555                     "type": "public-key"
   9556                 })
   9557                 .to_string()
   9558                 .as_str()
   9559             )
   9560             .is_ok()
   9561         );
   9562         // `publicKeyAlgorithm` mismatch when `publicKey` is null.
   9563         err = Error::invalid_value(
   9564             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   9565             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa65).as_str()
   9566         )
   9567         .to_string().into_bytes();
   9568         assert_eq!(
   9569             serde_json::from_str::<Registration>(
   9570                 serde_json::json!({
   9571                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9572                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9573                     "response": {
   9574                         "clientDataJSON": b64_cdata_json,
   9575                         "authenticatorData": b64_adata,
   9576                         "transports": [],
   9577                         "publicKey": null,
   9578                         "publicKeyAlgorithm": -7i8,
   9579                         "attestationObject": b64_aobj,
   9580                     },
   9581                     "clientExtensionResults": {},
   9582                     "type": "public-key"
   9583                 })
   9584                 .to_string()
   9585                 .as_str()
   9586             )
   9587             .unwrap_err()
   9588             .to_string()
   9589             .into_bytes()
   9590             .get(..err.len()),
   9591             Some(err.as_slice())
   9592         );
   9593     }
   9594     #[expect(
   9595         clippy::assertions_on_result_states,
   9596         clippy::unwrap_used,
   9597         reason = "OK in tests"
   9598     )]
   9599     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
   9600     #[expect(clippy::too_many_lines, reason = "a lot to test")]
   9601     #[test]
   9602     fn mldsa44_registration_deserialize_data_mismatch() {
   9603         let c_data_json = serde_json::json!({}).to_string();
   9604         let att_obj: [u8; 1424] = [
   9605             cbor::MAP_3,
   9606             cbor::TEXT_3,
   9607             b'f',
   9608             b'm',
   9609             b't',
   9610             cbor::TEXT_4,
   9611             b'n',
   9612             b'o',
   9613             b'n',
   9614             b'e',
   9615             cbor::TEXT_7,
   9616             b'a',
   9617             b't',
   9618             b't',
   9619             b'S',
   9620             b't',
   9621             b'm',
   9622             b't',
   9623             cbor::MAP_0,
   9624             cbor::TEXT_8,
   9625             b'a',
   9626             b'u',
   9627             b't',
   9628             b'h',
   9629             b'D',
   9630             b'a',
   9631             b't',
   9632             b'a',
   9633             cbor::BYTES_INFO_25,
   9634             5,
   9635             113,
   9636             // `rpIdHash`.
   9637             0,
   9638             0,
   9639             0,
   9640             0,
   9641             0,
   9642             0,
   9643             0,
   9644             0,
   9645             0,
   9646             0,
   9647             0,
   9648             0,
   9649             0,
   9650             0,
   9651             0,
   9652             0,
   9653             0,
   9654             0,
   9655             0,
   9656             0,
   9657             0,
   9658             0,
   9659             0,
   9660             0,
   9661             0,
   9662             0,
   9663             0,
   9664             0,
   9665             0,
   9666             0,
   9667             0,
   9668             0,
   9669             // `flags`.
   9670             0b0100_0101,
   9671             // `signCount`.
   9672             0,
   9673             0,
   9674             0,
   9675             0,
   9676             // `aaguid`.
   9677             0,
   9678             0,
   9679             0,
   9680             0,
   9681             0,
   9682             0,
   9683             0,
   9684             0,
   9685             0,
   9686             0,
   9687             0,
   9688             0,
   9689             0,
   9690             0,
   9691             0,
   9692             0,
   9693             // `credentialIdLength`.
   9694             0,
   9695             16,
   9696             // `credentialId`.
   9697             0,
   9698             0,
   9699             0,
   9700             0,
   9701             0,
   9702             0,
   9703             0,
   9704             0,
   9705             0,
   9706             0,
   9707             0,
   9708             0,
   9709             0,
   9710             0,
   9711             0,
   9712             0,
   9713             // ML-DSA-44 COSE key.
   9714             cbor::MAP_3,
   9715             KTY,
   9716             AKP,
   9717             ALG,
   9718             cbor::NEG_INFO_24,
   9719             MLDSA44,
   9720             // `pub`.
   9721             cbor::NEG_ONE,
   9722             cbor::BYTES_INFO_25,
   9723             5,
   9724             32,
   9725             // Encoded key.
   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             1,
   9898             1,
   9899             1,
   9900             1,
   9901             1,
   9902             1,
   9903             1,
   9904             1,
   9905             1,
   9906             1,
   9907             1,
   9908             1,
   9909             1,
   9910             1,
   9911             1,
   9912             1,
   9913             1,
   9914             1,
   9915             1,
   9916             1,
   9917             1,
   9918             1,
   9919             1,
   9920             1,
   9921             1,
   9922             1,
   9923             1,
   9924             1,
   9925             1,
   9926             1,
   9927             1,
   9928             1,
   9929             1,
   9930             1,
   9931             1,
   9932             1,
   9933             1,
   9934             1,
   9935             1,
   9936             1,
   9937             1,
   9938             1,
   9939             1,
   9940             1,
   9941             1,
   9942             1,
   9943             1,
   9944             1,
   9945             1,
   9946             1,
   9947             1,
   9948             1,
   9949             1,
   9950             1,
   9951             1,
   9952             1,
   9953             1,
   9954             1,
   9955             1,
   9956             1,
   9957             1,
   9958             1,
   9959             1,
   9960             1,
   9961             1,
   9962             1,
   9963             1,
   9964             1,
   9965             1,
   9966             1,
   9967             1,
   9968             1,
   9969             1,
   9970             1,
   9971             1,
   9972             1,
   9973             1,
   9974             1,
   9975             1,
   9976             1,
   9977             1,
   9978             1,
   9979             1,
   9980             1,
   9981             1,
   9982             1,
   9983             1,
   9984             1,
   9985             1,
   9986             1,
   9987             1,
   9988             1,
   9989             1,
   9990             1,
   9991             1,
   9992             1,
   9993             1,
   9994             1,
   9995             1,
   9996             1,
   9997             1,
   9998             1,
   9999             1,
  10000             1,
  10001             1,
  10002             1,
  10003             1,
  10004             1,
  10005             1,
  10006             1,
  10007             1,
  10008             1,
  10009             1,
  10010             1,
  10011             1,
  10012             1,
  10013             1,
  10014             1,
  10015             1,
  10016             1,
  10017             1,
  10018             1,
  10019             1,
  10020             1,
  10021             1,
  10022             1,
  10023             1,
  10024             1,
  10025             1,
  10026             1,
  10027             1,
  10028             1,
  10029             1,
  10030             1,
  10031             1,
  10032             1,
  10033             1,
  10034             1,
  10035             1,
  10036             1,
  10037             1,
  10038             1,
  10039             1,
  10040             1,
  10041             1,
  10042             1,
  10043             1,
  10044             1,
  10045             1,
  10046             1,
  10047             1,
  10048             1,
  10049             1,
  10050             1,
  10051             1,
  10052             1,
  10053             1,
  10054             1,
  10055             1,
  10056             1,
  10057             1,
  10058             1,
  10059             1,
  10060             1,
  10061             1,
  10062             1,
  10063             1,
  10064             1,
  10065             1,
  10066             1,
  10067             1,
  10068             1,
  10069             1,
  10070             1,
  10071             1,
  10072             1,
  10073             1,
  10074             1,
  10075             1,
  10076             1,
  10077             1,
  10078             1,
  10079             1,
  10080             1,
  10081             1,
  10082             1,
  10083             1,
  10084             1,
  10085             1,
  10086             1,
  10087             1,
  10088             1,
  10089             1,
  10090             1,
  10091             1,
  10092             1,
  10093             1,
  10094             1,
  10095             1,
  10096             1,
  10097             1,
  10098             1,
  10099             1,
  10100             1,
  10101             1,
  10102             1,
  10103             1,
  10104             1,
  10105             1,
  10106             1,
  10107             1,
  10108             1,
  10109             1,
  10110             1,
  10111             1,
  10112             1,
  10113             1,
  10114             1,
  10115             1,
  10116             1,
  10117             1,
  10118             1,
  10119             1,
  10120             1,
  10121             1,
  10122             1,
  10123             1,
  10124             1,
  10125             1,
  10126             1,
  10127             1,
  10128             1,
  10129             1,
  10130             1,
  10131             1,
  10132             1,
  10133             1,
  10134             1,
  10135             1,
  10136             1,
  10137             1,
  10138             1,
  10139             1,
  10140             1,
  10141             1,
  10142             1,
  10143             1,
  10144             1,
  10145             1,
  10146             1,
  10147             1,
  10148             1,
  10149             1,
  10150             1,
  10151             1,
  10152             1,
  10153             1,
  10154             1,
  10155             1,
  10156             1,
  10157             1,
  10158             1,
  10159             1,
  10160             1,
  10161             1,
  10162             1,
  10163             1,
  10164             1,
  10165             1,
  10166             1,
  10167             1,
  10168             1,
  10169             1,
  10170             1,
  10171             1,
  10172             1,
  10173             1,
  10174             1,
  10175             1,
  10176             1,
  10177             1,
  10178             1,
  10179             1,
  10180             1,
  10181             1,
  10182             1,
  10183             1,
  10184             1,
  10185             1,
  10186             1,
  10187             1,
  10188             1,
  10189             1,
  10190             1,
  10191             1,
  10192             1,
  10193             1,
  10194             1,
  10195             1,
  10196             1,
  10197             1,
  10198             1,
  10199             1,
  10200             1,
  10201             1,
  10202             1,
  10203             1,
  10204             1,
  10205             1,
  10206             1,
  10207             1,
  10208             1,
  10209             1,
  10210             1,
  10211             1,
  10212             1,
  10213             1,
  10214             1,
  10215             1,
  10216             1,
  10217             1,
  10218             1,
  10219             1,
  10220             1,
  10221             1,
  10222             1,
  10223             1,
  10224             1,
  10225             1,
  10226             1,
  10227             1,
  10228             1,
  10229             1,
  10230             1,
  10231             1,
  10232             1,
  10233             1,
  10234             1,
  10235             1,
  10236             1,
  10237             1,
  10238             1,
  10239             1,
  10240             1,
  10241             1,
  10242             1,
  10243             1,
  10244             1,
  10245             1,
  10246             1,
  10247             1,
  10248             1,
  10249             1,
  10250             1,
  10251             1,
  10252             1,
  10253             1,
  10254             1,
  10255             1,
  10256             1,
  10257             1,
  10258             1,
  10259             1,
  10260             1,
  10261             1,
  10262             1,
  10263             1,
  10264             1,
  10265             1,
  10266             1,
  10267             1,
  10268             1,
  10269             1,
  10270             1,
  10271             1,
  10272             1,
  10273             1,
  10274             1,
  10275             1,
  10276             1,
  10277             1,
  10278             1,
  10279             1,
  10280             1,
  10281             1,
  10282             1,
  10283             1,
  10284             1,
  10285             1,
  10286             1,
  10287             1,
  10288             1,
  10289             1,
  10290             1,
  10291             1,
  10292             1,
  10293             1,
  10294             1,
  10295             1,
  10296             1,
  10297             1,
  10298             1,
  10299             1,
  10300             1,
  10301             1,
  10302             1,
  10303             1,
  10304             1,
  10305             1,
  10306             1,
  10307             1,
  10308             1,
  10309             1,
  10310             1,
  10311             1,
  10312             1,
  10313             1,
  10314             1,
  10315             1,
  10316             1,
  10317             1,
  10318             1,
  10319             1,
  10320             1,
  10321             1,
  10322             1,
  10323             1,
  10324             1,
  10325             1,
  10326             1,
  10327             1,
  10328             1,
  10329             1,
  10330             1,
  10331             1,
  10332             1,
  10333             1,
  10334             1,
  10335             1,
  10336             1,
  10337             1,
  10338             1,
  10339             1,
  10340             1,
  10341             1,
  10342             1,
  10343             1,
  10344             1,
  10345             1,
  10346             1,
  10347             1,
  10348             1,
  10349             1,
  10350             1,
  10351             1,
  10352             1,
  10353             1,
  10354             1,
  10355             1,
  10356             1,
  10357             1,
  10358             1,
  10359             1,
  10360             1,
  10361             1,
  10362             1,
  10363             1,
  10364             1,
  10365             1,
  10366             1,
  10367             1,
  10368             1,
  10369             1,
  10370             1,
  10371             1,
  10372             1,
  10373             1,
  10374             1,
  10375             1,
  10376             1,
  10377             1,
  10378             1,
  10379             1,
  10380             1,
  10381             1,
  10382             1,
  10383             1,
  10384             1,
  10385             1,
  10386             1,
  10387             1,
  10388             1,
  10389             1,
  10390             1,
  10391             1,
  10392             1,
  10393             1,
  10394             1,
  10395             1,
  10396             1,
  10397             1,
  10398             1,
  10399             1,
  10400             1,
  10401             1,
  10402             1,
  10403             1,
  10404             1,
  10405             1,
  10406             1,
  10407             1,
  10408             1,
  10409             1,
  10410             1,
  10411             1,
  10412             1,
  10413             1,
  10414             1,
  10415             1,
  10416             1,
  10417             1,
  10418             1,
  10419             1,
  10420             1,
  10421             1,
  10422             1,
  10423             1,
  10424             1,
  10425             1,
  10426             1,
  10427             1,
  10428             1,
  10429             1,
  10430             1,
  10431             1,
  10432             1,
  10433             1,
  10434             1,
  10435             1,
  10436             1,
  10437             1,
  10438             1,
  10439             1,
  10440             1,
  10441             1,
  10442             1,
  10443             1,
  10444             1,
  10445             1,
  10446             1,
  10447             1,
  10448             1,
  10449             1,
  10450             1,
  10451             1,
  10452             1,
  10453             1,
  10454             1,
  10455             1,
  10456             1,
  10457             1,
  10458             1,
  10459             1,
  10460             1,
  10461             1,
  10462             1,
  10463             1,
  10464             1,
  10465             1,
  10466             1,
  10467             1,
  10468             1,
  10469             1,
  10470             1,
  10471             1,
  10472             1,
  10473             1,
  10474             1,
  10475             1,
  10476             1,
  10477             1,
  10478             1,
  10479             1,
  10480             1,
  10481             1,
  10482             1,
  10483             1,
  10484             1,
  10485             1,
  10486             1,
  10487             1,
  10488             1,
  10489             1,
  10490             1,
  10491             1,
  10492             1,
  10493             1,
  10494             1,
  10495             1,
  10496             1,
  10497             1,
  10498             1,
  10499             1,
  10500             1,
  10501             1,
  10502             1,
  10503             1,
  10504             1,
  10505             1,
  10506             1,
  10507             1,
  10508             1,
  10509             1,
  10510             1,
  10511             1,
  10512             1,
  10513             1,
  10514             1,
  10515             1,
  10516             1,
  10517             1,
  10518             1,
  10519             1,
  10520             1,
  10521             1,
  10522             1,
  10523             1,
  10524             1,
  10525             1,
  10526             1,
  10527             1,
  10528             1,
  10529             1,
  10530             1,
  10531             1,
  10532             1,
  10533             1,
  10534             1,
  10535             1,
  10536             1,
  10537             1,
  10538             1,
  10539             1,
  10540             1,
  10541             1,
  10542             1,
  10543             1,
  10544             1,
  10545             1,
  10546             1,
  10547             1,
  10548             1,
  10549             1,
  10550             1,
  10551             1,
  10552             1,
  10553             1,
  10554             1,
  10555             1,
  10556             1,
  10557             1,
  10558             1,
  10559             1,
  10560             1,
  10561             1,
  10562             1,
  10563             1,
  10564             1,
  10565             1,
  10566             1,
  10567             1,
  10568             1,
  10569             1,
  10570             1,
  10571             1,
  10572             1,
  10573             1,
  10574             1,
  10575             1,
  10576             1,
  10577             1,
  10578             1,
  10579             1,
  10580             1,
  10581             1,
  10582             1,
  10583             1,
  10584             1,
  10585             1,
  10586             1,
  10587             1,
  10588             1,
  10589             1,
  10590             1,
  10591             1,
  10592             1,
  10593             1,
  10594             1,
  10595             1,
  10596             1,
  10597             1,
  10598             1,
  10599             1,
  10600             1,
  10601             1,
  10602             1,
  10603             1,
  10604             1,
  10605             1,
  10606             1,
  10607             1,
  10608             1,
  10609             1,
  10610             1,
  10611             1,
  10612             1,
  10613             1,
  10614             1,
  10615             1,
  10616             1,
  10617             1,
  10618             1,
  10619             1,
  10620             1,
  10621             1,
  10622             1,
  10623             1,
  10624             1,
  10625             1,
  10626             1,
  10627             1,
  10628             1,
  10629             1,
  10630             1,
  10631             1,
  10632             1,
  10633             1,
  10634             1,
  10635             1,
  10636             1,
  10637             1,
  10638             1,
  10639             1,
  10640             1,
  10641             1,
  10642             1,
  10643             1,
  10644             1,
  10645             1,
  10646             1,
  10647             1,
  10648             1,
  10649             1,
  10650             1,
  10651             1,
  10652             1,
  10653             1,
  10654             1,
  10655             1,
  10656             1,
  10657             1,
  10658             1,
  10659             1,
  10660             1,
  10661             1,
  10662             1,
  10663             1,
  10664             1,
  10665             1,
  10666             1,
  10667             1,
  10668             1,
  10669             1,
  10670             1,
  10671             1,
  10672             1,
  10673             1,
  10674             1,
  10675             1,
  10676             1,
  10677             1,
  10678             1,
  10679             1,
  10680             1,
  10681             1,
  10682             1,
  10683             1,
  10684             1,
  10685             1,
  10686             1,
  10687             1,
  10688             1,
  10689             1,
  10690             1,
  10691             1,
  10692             1,
  10693             1,
  10694             1,
  10695             1,
  10696             1,
  10697             1,
  10698             1,
  10699             1,
  10700             1,
  10701             1,
  10702             1,
  10703             1,
  10704             1,
  10705             1,
  10706             1,
  10707             1,
  10708             1,
  10709             1,
  10710             1,
  10711             1,
  10712             1,
  10713             1,
  10714             1,
  10715             1,
  10716             1,
  10717             1,
  10718             1,
  10719             1,
  10720             1,
  10721             1,
  10722             1,
  10723             1,
  10724             1,
  10725             1,
  10726             1,
  10727             1,
  10728             1,
  10729             1,
  10730             1,
  10731             1,
  10732             1,
  10733             1,
  10734             1,
  10735             1,
  10736             1,
  10737             1,
  10738             1,
  10739             1,
  10740             1,
  10741             1,
  10742             1,
  10743             1,
  10744             1,
  10745             1,
  10746             1,
  10747             1,
  10748             1,
  10749             1,
  10750             1,
  10751             1,
  10752             1,
  10753             1,
  10754             1,
  10755             1,
  10756             1,
  10757             1,
  10758             1,
  10759             1,
  10760             1,
  10761             1,
  10762             1,
  10763             1,
  10764             1,
  10765             1,
  10766             1,
  10767             1,
  10768             1,
  10769             1,
  10770             1,
  10771             1,
  10772             1,
  10773             1,
  10774             1,
  10775             1,
  10776             1,
  10777             1,
  10778             1,
  10779             1,
  10780             1,
  10781             1,
  10782             1,
  10783             1,
  10784             1,
  10785             1,
  10786             1,
  10787             1,
  10788             1,
  10789             1,
  10790             1,
  10791             1,
  10792             1,
  10793             1,
  10794             1,
  10795             1,
  10796             1,
  10797             1,
  10798             1,
  10799             1,
  10800             1,
  10801             1,
  10802             1,
  10803             1,
  10804             1,
  10805             1,
  10806             1,
  10807             1,
  10808             1,
  10809             1,
  10810             1,
  10811             1,
  10812             1,
  10813             1,
  10814             1,
  10815             1,
  10816             1,
  10817             1,
  10818             1,
  10819             1,
  10820             1,
  10821             1,
  10822             1,
  10823             1,
  10824             1,
  10825             1,
  10826             1,
  10827             1,
  10828             1,
  10829             1,
  10830             1,
  10831             1,
  10832             1,
  10833             1,
  10834             1,
  10835             1,
  10836             1,
  10837             1,
  10838             1,
  10839             1,
  10840             1,
  10841             1,
  10842             1,
  10843             1,
  10844             1,
  10845             1,
  10846             1,
  10847             1,
  10848             1,
  10849             1,
  10850             1,
  10851             1,
  10852             1,
  10853             1,
  10854             1,
  10855             1,
  10856             1,
  10857             1,
  10858             1,
  10859             1,
  10860             1,
  10861             1,
  10862             1,
  10863             1,
  10864             1,
  10865             1,
  10866             1,
  10867             1,
  10868             1,
  10869             1,
  10870             1,
  10871             1,
  10872             1,
  10873             1,
  10874             1,
  10875             1,
  10876             1,
  10877             1,
  10878             1,
  10879             1,
  10880             1,
  10881             1,
  10882             1,
  10883             1,
  10884             1,
  10885             1,
  10886             1,
  10887             1,
  10888             1,
  10889             1,
  10890             1,
  10891             1,
  10892             1,
  10893             1,
  10894             1,
  10895             1,
  10896             1,
  10897             1,
  10898             1,
  10899             1,
  10900             1,
  10901             1,
  10902             1,
  10903             1,
  10904             1,
  10905             1,
  10906             1,
  10907             1,
  10908             1,
  10909             1,
  10910             1,
  10911             1,
  10912             1,
  10913             1,
  10914             1,
  10915             1,
  10916             1,
  10917             1,
  10918             1,
  10919             1,
  10920             1,
  10921             1,
  10922             1,
  10923             1,
  10924             1,
  10925             1,
  10926             1,
  10927             1,
  10928             1,
  10929             1,
  10930             1,
  10931             1,
  10932             1,
  10933             1,
  10934             1,
  10935             1,
  10936             1,
  10937             1,
  10938             1,
  10939             1,
  10940             1,
  10941             1,
  10942             1,
  10943             1,
  10944             1,
  10945             1,
  10946             1,
  10947             1,
  10948             1,
  10949             1,
  10950             1,
  10951             1,
  10952             1,
  10953             1,
  10954             1,
  10955             1,
  10956             1,
  10957             1,
  10958             1,
  10959             1,
  10960             1,
  10961             1,
  10962             1,
  10963             1,
  10964             1,
  10965             1,
  10966             1,
  10967             1,
  10968             1,
  10969             1,
  10970             1,
  10971             1,
  10972             1,
  10973             1,
  10974             1,
  10975             1,
  10976             1,
  10977             1,
  10978             1,
  10979             1,
  10980             1,
  10981             1,
  10982             1,
  10983             1,
  10984             1,
  10985             1,
  10986             1,
  10987             1,
  10988             1,
  10989             1,
  10990             1,
  10991             1,
  10992             1,
  10993             1,
  10994             1,
  10995             1,
  10996             1,
  10997             1,
  10998             1,
  10999             1,
  11000             1,
  11001             1,
  11002             1,
  11003             1,
  11004             1,
  11005             1,
  11006             1,
  11007             1,
  11008             1,
  11009             1,
  11010             1,
  11011             1,
  11012             1,
  11013             1,
  11014             1,
  11015             1,
  11016             1,
  11017             1,
  11018             1,
  11019             1,
  11020             1,
  11021             1,
  11022             1,
  11023             1,
  11024             1,
  11025             1,
  11026             1,
  11027             1,
  11028             1,
  11029             1,
  11030             1,
  11031             1,
  11032             1,
  11033             1,
  11034             1,
  11035             1,
  11036             1,
  11037             1,
  11038         ];
  11039         let pub_key = MlDsaVerKey::<MlDsa44>::decode(&[1u8; 1312].into())
  11040             .to_public_key_der()
  11041             .unwrap();
  11042         let att_obj_len = att_obj.len();
  11043         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
  11044         let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 1393..]);
  11045         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
  11046         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
  11047         // Base case is valid.
  11048         assert!(
  11049             serde_json::from_str::<Registration>(
  11050                 serde_json::json!({
  11051                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11052                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11053                     "response": {
  11054                         "clientDataJSON": b64_cdata_json,
  11055                         "authenticatorData": b64_adata,
  11056                         "transports": [],
  11057                         "publicKey": b64_key,
  11058                         "publicKeyAlgorithm": -48i8,
  11059                         "attestationObject": b64_aobj,
  11060                     },
  11061                     "clientExtensionResults": {},
  11062                     "type": "public-key"
  11063                 })
  11064                 .to_string()
  11065                 .as_str()
  11066             )
  11067             .is_ok_and(
  11068                 |reg| reg.response.client_data_json == c_data_json.as_bytes()
  11069                     && reg.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
  11070                     && reg.response.attestation_object_and_c_data_hash[att_obj_len..]
  11071                         == *Sha256::digest(c_data_json.as_bytes())
  11072                     && reg.response.transports.is_empty()
  11073                     && matches!(reg.authenticator_attachment, AuthenticatorAttachment::None)
  11074                     && reg.client_extension_results.cred_props.is_none()
  11075                     && reg.client_extension_results.prf.is_none()
  11076             )
  11077         );
  11078         // `publicKeyAlgorithm` mismatch.
  11079         let mut err = Error::invalid_value(
  11080             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
  11081             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa44).as_str()
  11082         )
  11083         .to_string().into_bytes();
  11084         assert_eq!(
  11085             serde_json::from_str::<Registration>(
  11086                 serde_json::json!({
  11087                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11088                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11089                     "response": {
  11090                         "clientDataJSON": b64_cdata_json,
  11091                         "authenticatorData": b64_adata,
  11092                         "transports": [],
  11093                         "publicKey": b64_key,
  11094                         "publicKeyAlgorithm": -8i8,
  11095                         "attestationObject": b64_aobj,
  11096                     },
  11097                     "clientExtensionResults": {},
  11098                     "type": "public-key"
  11099                 })
  11100                 .to_string()
  11101                 .as_str()
  11102             )
  11103             .unwrap_err()
  11104             .to_string()
  11105             .into_bytes()
  11106             .get(..err.len()),
  11107             Some(err.as_slice())
  11108         );
  11109         // Missing `publicKeyAlgorithm`.
  11110         err = Error::missing_field("publicKeyAlgorithm")
  11111             .to_string()
  11112             .into_bytes();
  11113         assert_eq!(
  11114             serde_json::from_str::<Registration>(
  11115                 serde_json::json!({
  11116                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11117                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11118                     "response": {
  11119                         "clientDataJSON": b64_cdata_json,
  11120                         "authenticatorData": b64_adata,
  11121                         "transports": [],
  11122                         "publicKey": b64_key,
  11123                         "attestationObject": b64_aobj,
  11124                     },
  11125                     "clientExtensionResults": {},
  11126                     "type": "public-key"
  11127                 })
  11128                 .to_string()
  11129                 .as_str()
  11130             )
  11131             .unwrap_err()
  11132             .to_string()
  11133             .into_bytes()
  11134             .get(..err.len()),
  11135             Some(err.as_slice())
  11136         );
  11137         // `null` `publicKeyAlgorithm`.
  11138         err = Error::invalid_type(Unexpected::Other("null"), &"publicKeyAlgorithm")
  11139             .to_string()
  11140             .into_bytes();
  11141         assert_eq!(
  11142             serde_json::from_str::<Registration>(
  11143                 serde_json::json!({
  11144                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11145                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11146                     "response": {
  11147                         "clientDataJSON": b64_cdata_json,
  11148                         "authenticatorData": b64_adata,
  11149                         "transports": [],
  11150                         "publicKey": b64_key,
  11151                         "publicKeyAlgorithm": null,
  11152                         "attestationObject": b64_aobj,
  11153                     },
  11154                     "clientExtensionResults": {},
  11155                     "type": "public-key"
  11156                 })
  11157                 .to_string()
  11158                 .as_str()
  11159             )
  11160             .unwrap_err()
  11161             .to_string()
  11162             .into_bytes()
  11163             .get(..err.len()),
  11164             Some(err.as_slice())
  11165         );
  11166         // `publicKey` mismatch.
  11167         let bad_pub_key = MlDsaVerKey::<MlDsa44>::decode(&[2; 1312].into());
  11168         err = Error::invalid_value(
  11169             Unexpected::Bytes([0; 32].as_slice()),
  11170             &format!(
  11171                 "DER-encoded public key to match the public key within the attestation object: MlDsa44(MlDsa44PubKey({:?}))",
  11172                 &[1u8; 1312]
  11173             )
  11174             .as_str(),
  11175         )
  11176         .to_string().into_bytes();
  11177         assert_eq!(serde_json::from_str::<Registration>(
  11178             serde_json::json!({
  11179                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11180                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11181                 "response": {
  11182                     "clientDataJSON": b64_cdata_json,
  11183                     "authenticatorData": b64_adata,
  11184                     "transports": [],
  11185                     "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
  11186                     "publicKeyAlgorithm": -48i8,
  11187                     "attestationObject": b64_aobj,
  11188                 },
  11189                 "clientExtensionResults": {},
  11190                 "type": "public-key"
  11191             })
  11192             .to_string()
  11193             .as_str()
  11194             )
  11195             .unwrap_err().to_string().into_bytes().get(..err.len()),
  11196             Some(err.as_slice())
  11197         );
  11198         // Missing `publicKey` is allowed when not using EdDSA, ES256, or RS256.
  11199         assert!(
  11200             serde_json::from_str::<Registration>(
  11201                 serde_json::json!({
  11202                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11203                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11204                     "response": {
  11205                         "clientDataJSON": b64_cdata_json,
  11206                         "authenticatorData": b64_adata,
  11207                         "transports": [],
  11208                         "publicKeyAlgorithm": -48i8,
  11209                         "attestationObject": b64_aobj,
  11210                     },
  11211                     "clientExtensionResults": {},
  11212                     "type": "public-key"
  11213                 })
  11214                 .to_string()
  11215                 .as_str()
  11216             )
  11217             .is_ok()
  11218         );
  11219         // `publicKeyAlgorithm` mismatch when `publicKey` does not exist.
  11220         err = Error::invalid_value(
  11221             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
  11222             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa44).as_str()
  11223         )
  11224         .to_string().into_bytes();
  11225         assert_eq!(
  11226             serde_json::from_str::<Registration>(
  11227                 serde_json::json!({
  11228                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11229                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11230                     "response": {
  11231                         "clientDataJSON": b64_cdata_json,
  11232                         "authenticatorData": b64_adata,
  11233                         "transports": [],
  11234                         "publicKeyAlgorithm": -7i8,
  11235                         "attestationObject": b64_aobj,
  11236                     },
  11237                     "clientExtensionResults": {},
  11238                     "type": "public-key"
  11239                 })
  11240                 .to_string()
  11241                 .as_str()
  11242             )
  11243             .unwrap_err()
  11244             .to_string()
  11245             .into_bytes()
  11246             .get(..err.len()),
  11247             Some(err.as_slice())
  11248         );
  11249         // `null` `publicKey` is allowed when not using EdDSA, ES256, or RS256.
  11250         assert!(
  11251             serde_json::from_str::<Registration>(
  11252                 serde_json::json!({
  11253                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11254                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11255                     "response": {
  11256                         "clientDataJSON": b64_cdata_json,
  11257                         "authenticatorData": b64_adata,
  11258                         "transports": [],
  11259                         "publicKey": null,
  11260                         "publicKeyAlgorithm": -48i8,
  11261                         "attestationObject": b64_aobj,
  11262                     },
  11263                     "clientExtensionResults": {},
  11264                     "type": "public-key"
  11265                 })
  11266                 .to_string()
  11267                 .as_str()
  11268             )
  11269             .is_ok()
  11270         );
  11271         // `publicKeyAlgorithm` mismatch when `publicKey` is null.
  11272         err = Error::invalid_value(
  11273             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
  11274             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa44).as_str()
  11275         )
  11276         .to_string().into_bytes();
  11277         assert_eq!(
  11278             serde_json::from_str::<Registration>(
  11279                 serde_json::json!({
  11280                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11281                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11282                     "response": {
  11283                         "clientDataJSON": b64_cdata_json,
  11284                         "authenticatorData": b64_adata,
  11285                         "transports": [],
  11286                         "publicKey": null,
  11287                         "publicKeyAlgorithm": -7i8,
  11288                         "attestationObject": b64_aobj,
  11289                     },
  11290                     "clientExtensionResults": {},
  11291                     "type": "public-key"
  11292                 })
  11293                 .to_string()
  11294                 .as_str()
  11295             )
  11296             .unwrap_err()
  11297             .to_string()
  11298             .into_bytes()
  11299             .get(..err.len()),
  11300             Some(err.as_slice())
  11301         );
  11302     }
  11303     #[expect(clippy::unwrap_used, reason = "OK in tests")]
  11304     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
  11305     #[expect(clippy::too_many_lines, reason = "a lot to test")]
  11306     #[test]
  11307     fn es256_registration_deserialize_data_mismatch() {
  11308         let c_data_json = serde_json::json!({}).to_string();
  11309         let mut att_obj: [u8; 178] = [
  11310             cbor::MAP_3,
  11311             cbor::TEXT_3,
  11312             b'f',
  11313             b'm',
  11314             b't',
  11315             cbor::TEXT_4,
  11316             b'n',
  11317             b'o',
  11318             b'n',
  11319             b'e',
  11320             cbor::TEXT_7,
  11321             b'a',
  11322             b't',
  11323             b't',
  11324             b'S',
  11325             b't',
  11326             b'm',
  11327             b't',
  11328             cbor::MAP_0,
  11329             cbor::TEXT_8,
  11330             b'a',
  11331             b'u',
  11332             b't',
  11333             b'h',
  11334             b'D',
  11335             b'a',
  11336             b't',
  11337             b'a',
  11338             cbor::BYTES_INFO_24,
  11339             148,
  11340             // `rpIdHash`.
  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             // `flags`.
  11374             0b0100_0101,
  11375             // `signCount`.
  11376             0,
  11377             0,
  11378             0,
  11379             0,
  11380             // `aaguid`.
  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             // `credentialIdLength`.
  11398             0,
  11399             16,
  11400             // `credentialId`.
  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             // P-256 COSE key.
  11418             cbor::MAP_5,
  11419             KTY,
  11420             EC2,
  11421             ALG,
  11422             ES256,
  11423             // `crv`.
  11424             cbor::NEG_ONE,
  11425             // `P-256`.
  11426             cbor::ONE,
  11427             // `x`.
  11428             cbor::NEG_TWO,
  11429             cbor::BYTES_INFO_24,
  11430             32,
  11431             // x-coordinate. This will be overwritten later.
  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             // `y`.
  11465             cbor::NEG_THREE,
  11466             cbor::BYTES_INFO_24,
  11467             32,
  11468             // y-coordinate. This will be overwritten later.
  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         ];
  11502         let key = P256Key::from_bytes(
  11503             &[
  11504                 137, 133, 36, 206, 163, 47, 255, 5, 76, 144, 163, 141, 40, 109, 108, 240, 246, 115,
  11505                 178, 237, 169, 68, 6, 129, 92, 21, 238, 127, 55, 158, 207, 95,
  11506             ]
  11507             .into(),
  11508         )
  11509         .unwrap()
  11510         .public_key();
  11511         let enc_key = key.to_sec1_point(false);
  11512         let pub_key = key.to_public_key_der().unwrap();
  11513         let att_obj_len = att_obj.len();
  11514         let x_start = att_obj_len - 67;
  11515         let y_meta_start = x_start + 32;
  11516         let y_start = y_meta_start + 3;
  11517         att_obj[x_start..y_meta_start].copy_from_slice(enc_key.x().unwrap());
  11518         att_obj[y_start..].copy_from_slice(enc_key.y().unwrap());
  11519         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
  11520         let b64_adata = base64url_nopad::encode(&att_obj[att_obj.len() - 148..]);
  11521         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
  11522         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
  11523         // Base case is valid.
  11524         assert!(
  11525             serde_json::from_str::<Registration>(
  11526                 serde_json::json!({
  11527                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11528                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11529                     "response": {
  11530                         "clientDataJSON": b64_cdata_json,
  11531                         "authenticatorData": b64_adata,
  11532                         "transports": [],
  11533                         "publicKey": b64_key,
  11534                         "publicKeyAlgorithm": -7i8,
  11535                         "attestationObject": b64_aobj,
  11536                     },
  11537                     "clientExtensionResults": {},
  11538                     "type": "public-key"
  11539                 })
  11540                 .to_string()
  11541                 .as_str()
  11542             )
  11543             .is_ok_and(
  11544                 |reg| reg.response.client_data_json == c_data_json.as_bytes()
  11545                     && reg.response.attestation_object_and_c_data_hash[..att_obj.len()] == att_obj
  11546                     && reg.response.attestation_object_and_c_data_hash[att_obj.len()..]
  11547                         == *Sha256::digest(c_data_json.as_bytes())
  11548                     && reg.response.transports.is_empty()
  11549                     && matches!(reg.authenticator_attachment, AuthenticatorAttachment::None)
  11550                     && reg.client_extension_results.cred_props.is_none()
  11551                     && reg.client_extension_results.prf.is_none()
  11552             )
  11553         );
  11554         // `publicKeyAlgorithm` mismatch.
  11555         let mut err = Error::invalid_value(
  11556             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
  11557             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Es256).as_str()
  11558         )
  11559         .to_string().into_bytes();
  11560         assert_eq!(
  11561             serde_json::from_str::<Registration>(
  11562                 serde_json::json!({
  11563                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11564                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11565                     "response": {
  11566                         "clientDataJSON": b64_cdata_json,
  11567                         "authenticatorData": b64_adata,
  11568                         "transports": [],
  11569                         "publicKey": b64_key,
  11570                         "publicKeyAlgorithm": -8i8,
  11571                         "attestationObject": b64_aobj,
  11572                     },
  11573                     "clientExtensionResults": {},
  11574                     "type": "public-key"
  11575                 })
  11576                 .to_string()
  11577                 .as_str()
  11578             )
  11579             .unwrap_err()
  11580             .to_string()
  11581             .into_bytes()
  11582             .get(..err.len()),
  11583             Some(err.as_slice())
  11584         );
  11585         // Missing `publicKeyAlgorithm`.
  11586         err = Error::missing_field("publicKeyAlgorithm")
  11587             .to_string()
  11588             .into_bytes();
  11589         assert_eq!(
  11590             serde_json::from_str::<Registration>(
  11591                 serde_json::json!({
  11592                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11593                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11594                     "response": {
  11595                         "clientDataJSON": b64_cdata_json,
  11596                         "authenticatorData": b64_adata,
  11597                         "transports": [],
  11598                         "publicKey": b64_key,
  11599                         "attestationObject": b64_aobj,
  11600                     },
  11601                     "clientExtensionResults": {},
  11602                     "type": "public-key"
  11603                 })
  11604                 .to_string()
  11605                 .as_str()
  11606             )
  11607             .unwrap_err()
  11608             .to_string()
  11609             .into_bytes()
  11610             .get(..err.len()),
  11611             Some(err.as_slice())
  11612         );
  11613         // `null` `publicKeyAlgorithm`.
  11614         err = Error::invalid_type(Unexpected::Other("null"), &"publicKeyAlgorithm")
  11615             .to_string()
  11616             .into_bytes();
  11617         assert_eq!(
  11618             serde_json::from_str::<Registration>(
  11619                 serde_json::json!({
  11620                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11621                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11622                     "response": {
  11623                         "clientDataJSON": b64_cdata_json,
  11624                         "authenticatorData": b64_adata,
  11625                         "transports": [],
  11626                         "publicKey": b64_key,
  11627                         "publicKeyAlgorithm": null,
  11628                         "attestationObject": b64_aobj,
  11629                     },
  11630                     "clientExtensionResults": {},
  11631                     "type": "public-key"
  11632                 })
  11633                 .to_string()
  11634                 .as_str()
  11635             )
  11636             .unwrap_err()
  11637             .to_string()
  11638             .into_bytes()
  11639             .get(..err.len()),
  11640             Some(err.as_slice())
  11641         );
  11642         // `publicKey` mismatch.
  11643         let bad_pub_key = P256PubKey::from_sec1_point(&P256Pt::from_affine_coordinates(
  11644             &[
  11645                 66, 71, 188, 41, 125, 2, 226, 44, 148, 62, 63, 190, 172, 64, 33, 214, 6, 37, 148,
  11646                 23, 240, 235, 203, 84, 112, 219, 232, 197, 54, 182, 17, 235,
  11647             ]
  11648             .into(),
  11649             &[
  11650                 22, 172, 123, 13, 170, 242, 217, 248, 193, 209, 206, 163, 92, 4, 162, 168, 113, 63,
  11651                 2, 117, 16, 223, 239, 196, 109, 179, 10, 130, 43, 213, 205, 92,
  11652             ]
  11653             .into(),
  11654             false,
  11655         ))
  11656         .unwrap();
  11657         err = Error::invalid_value(
  11658             Unexpected::Bytes([0; 32].as_slice()),
  11659             &format!(
  11660                 "DER-encoded public key to match the public key within the attestation object: P256(UncompressedP256PubKey({:?}, {:?}))",
  11661                 &att_obj[x_start..y_meta_start],
  11662                 &att_obj[y_start..],
  11663             )
  11664             .as_str(),
  11665         )
  11666         .to_string().into_bytes();
  11667         assert_eq!(serde_json::from_str::<Registration>(
  11668             serde_json::json!({
  11669                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11670                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11671                 "response": {
  11672                     "clientDataJSON": b64_cdata_json,
  11673                     "authenticatorData": b64_adata,
  11674                     "transports": [],
  11675                     "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
  11676                     "publicKeyAlgorithm": -7i8,
  11677                     "attestationObject": b64_aobj,
  11678                 },
  11679                 "clientExtensionResults": {},
  11680                 "type": "public-key"
  11681             })
  11682             .to_string()
  11683             .as_str()
  11684             )
  11685             .unwrap_err().to_string().into_bytes().get(..err.len()),
  11686             Some(err.as_slice())
  11687         );
  11688         // Missing `publicKey` when using EdDSA, ES256, or RS256.
  11689         err = Error::missing_field("publicKey").to_string().into_bytes();
  11690         assert_eq!(
  11691             serde_json::from_str::<Registration>(
  11692                 serde_json::json!({
  11693                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11694                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11695                     "response": {
  11696                         "clientDataJSON": b64_cdata_json,
  11697                         "authenticatorData": b64_adata,
  11698                         "transports": [],
  11699                         "publicKeyAlgorithm": -7i8,
  11700                         "attestationObject": b64_aobj,
  11701                     },
  11702                     "clientExtensionResults": {},
  11703                     "type": "public-key"
  11704                 })
  11705                 .to_string()
  11706                 .as_str()
  11707             )
  11708             .unwrap_err()
  11709             .to_string()
  11710             .into_bytes()
  11711             .get(..err.len()),
  11712             Some(err.as_slice())
  11713         );
  11714         // `null` `publicKey` when using EdDSA, ES256, or RS256.
  11715         err = Error::invalid_type(Unexpected::Other("null"), &"publicKey")
  11716             .to_string()
  11717             .into_bytes();
  11718         assert_eq!(
  11719             serde_json::from_str::<Registration>(
  11720                 serde_json::json!({
  11721                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11722                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11723                     "response": {
  11724                         "clientDataJSON": b64_cdata_json,
  11725                         "authenticatorData": b64_adata,
  11726                         "transports": [],
  11727                         "publicKey": null,
  11728                         "publicKeyAlgorithm": -7i8,
  11729                         "attestationObject": b64_aobj,
  11730                     },
  11731                     "clientExtensionResults": {},
  11732                     "type": "public-key"
  11733                 })
  11734                 .to_string()
  11735                 .as_str()
  11736             )
  11737             .unwrap_err()
  11738             .to_string()
  11739             .into_bytes()
  11740             .get(..err.len()),
  11741             Some(err.as_slice())
  11742         );
  11743     }
  11744     #[expect(
  11745         clippy::assertions_on_result_states,
  11746         clippy::unwrap_used,
  11747         reason = "OK in tests"
  11748     )]
  11749     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
  11750     #[expect(clippy::too_many_lines, reason = "a lot to test")]
  11751     #[test]
  11752     fn es384_registration_deserialize_data_mismatch() {
  11753         let c_data_json = serde_json::json!({}).to_string();
  11754         let mut att_obj: [u8; 211] = [
  11755             cbor::MAP_3,
  11756             cbor::TEXT_3,
  11757             b'f',
  11758             b'm',
  11759             b't',
  11760             cbor::TEXT_4,
  11761             b'n',
  11762             b'o',
  11763             b'n',
  11764             b'e',
  11765             cbor::TEXT_7,
  11766             b'a',
  11767             b't',
  11768             b't',
  11769             b'S',
  11770             b't',
  11771             b'm',
  11772             b't',
  11773             cbor::MAP_0,
  11774             cbor::TEXT_8,
  11775             b'a',
  11776             b'u',
  11777             b't',
  11778             b'h',
  11779             b'D',
  11780             b'a',
  11781             b't',
  11782             b'a',
  11783             cbor::BYTES_INFO_24,
  11784             181,
  11785             // `rpIdHash`.
  11786             0,
  11787             0,
  11788             0,
  11789             0,
  11790             0,
  11791             0,
  11792             0,
  11793             0,
  11794             0,
  11795             0,
  11796             0,
  11797             0,
  11798             0,
  11799             0,
  11800             0,
  11801             0,
  11802             0,
  11803             0,
  11804             0,
  11805             0,
  11806             0,
  11807             0,
  11808             0,
  11809             0,
  11810             0,
  11811             0,
  11812             0,
  11813             0,
  11814             0,
  11815             0,
  11816             0,
  11817             0,
  11818             // `flags`.
  11819             0b0100_0101,
  11820             // `signCount`.
  11821             0,
  11822             0,
  11823             0,
  11824             0,
  11825             // `aaguid`.
  11826             0,
  11827             0,
  11828             0,
  11829             0,
  11830             0,
  11831             0,
  11832             0,
  11833             0,
  11834             0,
  11835             0,
  11836             0,
  11837             0,
  11838             0,
  11839             0,
  11840             0,
  11841             0,
  11842             // `credentialIdLength`.
  11843             0,
  11844             16,
  11845             // `credentialId`.
  11846             0,
  11847             0,
  11848             0,
  11849             0,
  11850             0,
  11851             0,
  11852             0,
  11853             0,
  11854             0,
  11855             0,
  11856             0,
  11857             0,
  11858             0,
  11859             0,
  11860             0,
  11861             0,
  11862             // P-384 COSE key.
  11863             cbor::MAP_5,
  11864             KTY,
  11865             EC2,
  11866             ALG,
  11867             cbor::NEG_INFO_24,
  11868             ES384,
  11869             // `crv`.
  11870             cbor::NEG_ONE,
  11871             // `P-384`.
  11872             cbor::TWO,
  11873             // `x`.
  11874             cbor::NEG_TWO,
  11875             cbor::BYTES_INFO_24,
  11876             48,
  11877             // x-coordinate. This will be overwritten later.
  11878             0,
  11879             0,
  11880             0,
  11881             0,
  11882             0,
  11883             0,
  11884             0,
  11885             0,
  11886             0,
  11887             0,
  11888             0,
  11889             0,
  11890             0,
  11891             0,
  11892             0,
  11893             0,
  11894             0,
  11895             0,
  11896             0,
  11897             0,
  11898             0,
  11899             0,
  11900             0,
  11901             0,
  11902             0,
  11903             0,
  11904             0,
  11905             0,
  11906             0,
  11907             0,
  11908             0,
  11909             0,
  11910             0,
  11911             0,
  11912             0,
  11913             0,
  11914             0,
  11915             0,
  11916             0,
  11917             0,
  11918             0,
  11919             0,
  11920             0,
  11921             0,
  11922             0,
  11923             0,
  11924             0,
  11925             0,
  11926             // `y`.
  11927             cbor::NEG_THREE,
  11928             cbor::BYTES_INFO_24,
  11929             48,
  11930             // y-coordinate. This will be overwritten later.
  11931             0,
  11932             0,
  11933             0,
  11934             0,
  11935             0,
  11936             0,
  11937             0,
  11938             0,
  11939             0,
  11940             0,
  11941             0,
  11942             0,
  11943             0,
  11944             0,
  11945             0,
  11946             0,
  11947             0,
  11948             0,
  11949             0,
  11950             0,
  11951             0,
  11952             0,
  11953             0,
  11954             0,
  11955             0,
  11956             0,
  11957             0,
  11958             0,
  11959             0,
  11960             0,
  11961             0,
  11962             0,
  11963             0,
  11964             0,
  11965             0,
  11966             0,
  11967             0,
  11968             0,
  11969             0,
  11970             0,
  11971             0,
  11972             0,
  11973             0,
  11974             0,
  11975             0,
  11976             0,
  11977             0,
  11978             0,
  11979         ];
  11980         let key = P384Key::from_bytes(
  11981             &[
  11982                 158, 99, 156, 49, 190, 211, 85, 167, 28, 2, 80, 57, 31, 22, 17, 38, 85, 78, 232,
  11983                 42, 45, 199, 154, 243, 136, 251, 84, 34, 5, 120, 208, 91, 61, 248, 64, 144, 87, 1,
  11984                 32, 86, 220, 68, 182, 11, 105, 223, 75, 70,
  11985             ]
  11986             .into(),
  11987         )
  11988         .unwrap()
  11989         .public_key();
  11990         let enc_key = key.to_sec1_point(false);
  11991         let pub_key = key.to_public_key_der().unwrap();
  11992         let att_obj_len = att_obj.len();
  11993         let x_start = att_obj_len - 99;
  11994         let y_meta_start = x_start + 48;
  11995         let y_start = y_meta_start + 3;
  11996         att_obj[x_start..y_meta_start].copy_from_slice(enc_key.x().unwrap());
  11997         att_obj[y_start..].copy_from_slice(enc_key.y().unwrap());
  11998         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
  11999         let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 181..]);
  12000         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
  12001         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
  12002         // Base case is valid.
  12003         assert!(
  12004             serde_json::from_str::<Registration>(
  12005                 serde_json::json!({
  12006                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12007                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12008                     "response": {
  12009                         "clientDataJSON": b64_cdata_json,
  12010                         "authenticatorData": b64_adata,
  12011                         "transports": [],
  12012                         "publicKey": b64_key,
  12013                         "publicKeyAlgorithm": -35i8,
  12014                         "attestationObject": b64_aobj,
  12015                     },
  12016                     "clientExtensionResults": {},
  12017                     "type": "public-key"
  12018                 })
  12019                 .to_string()
  12020                 .as_str()
  12021             )
  12022             .is_ok_and(
  12023                 |reg| reg.response.client_data_json == c_data_json.as_bytes()
  12024                     && reg.response.attestation_object_and_c_data_hash[..att_obj.len()] == att_obj
  12025                     && reg.response.attestation_object_and_c_data_hash[att_obj.len()..]
  12026                         == *Sha256::digest(c_data_json.as_bytes())
  12027                     && reg.response.transports.is_empty()
  12028                     && matches!(reg.authenticator_attachment, AuthenticatorAttachment::None)
  12029                     && reg.client_extension_results.cred_props.is_none()
  12030                     && reg.client_extension_results.prf.is_none()
  12031             )
  12032         );
  12033         // `publicKeyAlgorithm` mismatch.
  12034         let mut err = Error::invalid_value(
  12035             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
  12036             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Es384).as_str()
  12037         )
  12038         .to_string().into_bytes();
  12039         assert_eq!(
  12040             serde_json::from_str::<Registration>(
  12041                 serde_json::json!({
  12042                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12043                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12044                     "response": {
  12045                         "clientDataJSON": b64_cdata_json,
  12046                         "authenticatorData": b64_adata,
  12047                         "transports": [],
  12048                         "publicKey": b64_key,
  12049                         "publicKeyAlgorithm": -7i8,
  12050                         "attestationObject": b64_aobj,
  12051                     },
  12052                     "clientExtensionResults": {},
  12053                     "type": "public-key"
  12054                 })
  12055                 .to_string()
  12056                 .as_str()
  12057             )
  12058             .unwrap_err()
  12059             .to_string()
  12060             .into_bytes()
  12061             .get(..err.len()),
  12062             Some(err.as_slice())
  12063         );
  12064         // Missing `publicKeyAlgorithm`.
  12065         err = Error::missing_field("publicKeyAlgorithm")
  12066             .to_string()
  12067             .into_bytes();
  12068         assert_eq!(
  12069             serde_json::from_str::<Registration>(
  12070                 serde_json::json!({
  12071                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12072                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12073                     "response": {
  12074                         "clientDataJSON": b64_cdata_json,
  12075                         "authenticatorData": b64_adata,
  12076                         "transports": [],
  12077                         "publicKey": b64_key,
  12078                         "attestationObject": b64_aobj,
  12079                     },
  12080                     "clientExtensionResults": {},
  12081                     "type": "public-key"
  12082                 })
  12083                 .to_string()
  12084                 .as_str()
  12085             )
  12086             .unwrap_err()
  12087             .to_string()
  12088             .into_bytes()
  12089             .get(..err.len()),
  12090             Some(err.as_slice())
  12091         );
  12092         // `null` `publicKeyAlgorithm`.
  12093         err = Error::invalid_type(Unexpected::Other("null"), &"publicKeyAlgorithm")
  12094             .to_string()
  12095             .into_bytes();
  12096         assert_eq!(
  12097             serde_json::from_str::<Registration>(
  12098                 serde_json::json!({
  12099                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12100                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12101                     "response": {
  12102                         "clientDataJSON": b64_cdata_json,
  12103                         "authenticatorData": b64_adata,
  12104                         "transports": [],
  12105                         "publicKey": b64_key,
  12106                         "publicKeyAlgorithm": null,
  12107                         "attestationObject": b64_aobj,
  12108                     },
  12109                     "clientExtensionResults": {},
  12110                     "type": "public-key"
  12111                 })
  12112                 .to_string()
  12113                 .as_str()
  12114             )
  12115             .unwrap_err()
  12116             .to_string()
  12117             .into_bytes()
  12118             .get(..err.len()),
  12119             Some(err.as_slice())
  12120         );
  12121         // `publicKey` mismatch.
  12122         let bad_pub_key = P384PubKey::from_sec1_point(&P384Pt::from_affine_coordinates(
  12123             &[
  12124                 192, 10, 27, 46, 66, 67, 80, 98, 33, 230, 156, 95, 1, 135, 150, 110, 64, 243, 22,
  12125                 118, 5, 255, 107, 44, 234, 111, 217, 105, 125, 114, 39, 7, 126, 2, 191, 111, 48,
  12126                 93, 234, 175, 18, 172, 59, 28, 97, 106, 178, 152,
  12127             ]
  12128             .into(),
  12129             &[
  12130                 57, 36, 196, 12, 109, 129, 253, 115, 88, 154, 6, 43, 195, 85, 169, 5, 230, 51, 28,
  12131                 205, 142, 28, 150, 35, 24, 222, 170, 253, 14, 248, 84, 151, 109, 191, 152, 111,
  12132                 222, 70, 134, 247, 109, 171, 211, 33, 214, 217, 200, 111,
  12133             ]
  12134             .into(),
  12135             false,
  12136         ))
  12137         .unwrap();
  12138         err = Error::invalid_value(
  12139             Unexpected::Bytes([0; 32].as_slice()),
  12140             &format!(
  12141                 "DER-encoded public key to match the public key within the attestation object: P384(UncompressedP384PubKey({:?}, {:?}))",
  12142                 &att_obj[x_start..y_meta_start],
  12143                 &att_obj[y_start..],
  12144             )
  12145             .as_str(),
  12146         )
  12147         .to_string().into_bytes();
  12148         assert_eq!(serde_json::from_str::<Registration>(
  12149             serde_json::json!({
  12150                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12151                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12152                 "response": {
  12153                     "clientDataJSON": b64_cdata_json,
  12154                     "authenticatorData": b64_adata,
  12155                     "transports": [],
  12156                     "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
  12157                     "publicKeyAlgorithm": -35i8,
  12158                     "attestationObject": b64_aobj,
  12159                 },
  12160                 "clientExtensionResults": {},
  12161                 "type": "public-key"
  12162             })
  12163             .to_string()
  12164             .as_str()
  12165             )
  12166             .unwrap_err().to_string().into_bytes().get(..err.len()),
  12167             Some(err.as_slice())
  12168         );
  12169         // Missing `publicKey` is allowed when not using EdDSA, ES256, or RS256.
  12170         assert!(
  12171             serde_json::from_str::<Registration>(
  12172                 serde_json::json!({
  12173                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12174                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12175                     "response": {
  12176                         "clientDataJSON": b64_cdata_json,
  12177                         "authenticatorData": b64_adata,
  12178                         "transports": [],
  12179                         "publicKeyAlgorithm": -35i8,
  12180                         "attestationObject": b64_aobj,
  12181                     },
  12182                     "clientExtensionResults": {},
  12183                     "type": "public-key"
  12184                 })
  12185                 .to_string()
  12186                 .as_str()
  12187             )
  12188             .is_ok()
  12189         );
  12190         // `publicKeyAlgorithm` mismatch when `publicKey` does not exist.
  12191         err = Error::invalid_value(
  12192             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
  12193             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Es384).as_str()
  12194         )
  12195         .to_string().into_bytes();
  12196         assert_eq!(
  12197             serde_json::from_str::<Registration>(
  12198                 serde_json::json!({
  12199                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12200                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12201                     "response": {
  12202                         "clientDataJSON": b64_cdata_json,
  12203                         "authenticatorData": b64_adata,
  12204                         "transports": [],
  12205                         "publicKeyAlgorithm": -7i8,
  12206                         "attestationObject": b64_aobj,
  12207                     },
  12208                     "clientExtensionResults": {},
  12209                     "type": "public-key"
  12210                 })
  12211                 .to_string()
  12212                 .as_str()
  12213             )
  12214             .unwrap_err()
  12215             .to_string()
  12216             .into_bytes()
  12217             .get(..err.len()),
  12218             Some(err.as_slice())
  12219         );
  12220         // `null` `publicKey` is allowed when not using EdDSA, ES256, or RS256.
  12221         assert!(
  12222             serde_json::from_str::<Registration>(
  12223                 serde_json::json!({
  12224                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12225                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12226                     "response": {
  12227                         "clientDataJSON": b64_cdata_json,
  12228                         "authenticatorData": b64_adata,
  12229                         "transports": [],
  12230                         "publicKey": null,
  12231                         "publicKeyAlgorithm": -35i8,
  12232                         "attestationObject": b64_aobj,
  12233                     },
  12234                     "clientExtensionResults": {},
  12235                     "type": "public-key"
  12236                 })
  12237                 .to_string()
  12238                 .as_str()
  12239             )
  12240             .is_ok()
  12241         );
  12242         // `publicKeyAlgorithm` mismatch when `publicKey` is null.
  12243         err = Error::invalid_value(
  12244             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
  12245             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Es384).as_str()
  12246         )
  12247         .to_string().into_bytes();
  12248         assert_eq!(
  12249             serde_json::from_str::<Registration>(
  12250                 serde_json::json!({
  12251                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12252                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12253                     "response": {
  12254                         "clientDataJSON": b64_cdata_json,
  12255                         "authenticatorData": b64_adata,
  12256                         "transports": [],
  12257                         "publicKey": null,
  12258                         "publicKeyAlgorithm": -7i8,
  12259                         "attestationObject": b64_aobj,
  12260                     },
  12261                     "clientExtensionResults": {},
  12262                     "type": "public-key"
  12263                 })
  12264                 .to_string()
  12265                 .as_str()
  12266             )
  12267             .unwrap_err()
  12268             .to_string()
  12269             .into_bytes()
  12270             .get(..err.len()),
  12271             Some(err.as_slice())
  12272         );
  12273     }
  12274     #[expect(clippy::unwrap_used, reason = "OK in tests")]
  12275     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
  12276     #[expect(clippy::too_many_lines, reason = "a lot to test")]
  12277     #[test]
  12278     fn rs256_registration_deserialize_data_mismatch() {
  12279         let c_data_json = serde_json::json!({}).to_string();
  12280         let mut att_obj: [u8; 374] = [
  12281             cbor::MAP_3,
  12282             cbor::TEXT_3,
  12283             b'f',
  12284             b'm',
  12285             b't',
  12286             cbor::TEXT_4,
  12287             b'n',
  12288             b'o',
  12289             b'n',
  12290             b'e',
  12291             cbor::TEXT_7,
  12292             b'a',
  12293             b't',
  12294             b't',
  12295             b'S',
  12296             b't',
  12297             b'm',
  12298             b't',
  12299             cbor::MAP_0,
  12300             cbor::TEXT_8,
  12301             b'a',
  12302             b'u',
  12303             b't',
  12304             b'h',
  12305             b'D',
  12306             b'a',
  12307             b't',
  12308             b'a',
  12309             cbor::BYTES_INFO_25,
  12310             1,
  12311             87,
  12312             // `rpIdHash`.
  12313             0,
  12314             0,
  12315             0,
  12316             0,
  12317             0,
  12318             0,
  12319             0,
  12320             0,
  12321             0,
  12322             0,
  12323             0,
  12324             0,
  12325             0,
  12326             0,
  12327             0,
  12328             0,
  12329             0,
  12330             0,
  12331             0,
  12332             0,
  12333             0,
  12334             0,
  12335             0,
  12336             0,
  12337             0,
  12338             0,
  12339             0,
  12340             0,
  12341             0,
  12342             0,
  12343             0,
  12344             0,
  12345             // `flags`.
  12346             0b0100_0101,
  12347             // `signCount`.
  12348             0,
  12349             0,
  12350             0,
  12351             0,
  12352             // `aaguid`.
  12353             0,
  12354             0,
  12355             0,
  12356             0,
  12357             0,
  12358             0,
  12359             0,
  12360             0,
  12361             0,
  12362             0,
  12363             0,
  12364             0,
  12365             0,
  12366             0,
  12367             0,
  12368             0,
  12369             // `credentialIdLength`.
  12370             0,
  12371             16,
  12372             // `credentialId`.
  12373             0,
  12374             0,
  12375             0,
  12376             0,
  12377             0,
  12378             0,
  12379             0,
  12380             0,
  12381             0,
  12382             0,
  12383             0,
  12384             0,
  12385             0,
  12386             0,
  12387             0,
  12388             0,
  12389             // RSA COSE key.
  12390             cbor::MAP_4,
  12391             KTY,
  12392             RSA,
  12393             ALG,
  12394             cbor::NEG_INFO_25,
  12395             // RS256.
  12396             1,
  12397             0,
  12398             // `n`.
  12399             cbor::NEG_ONE,
  12400             cbor::BYTES_INFO_25,
  12401             1,
  12402             0,
  12403             // n. This will be overwritten later.
  12404             0,
  12405             0,
  12406             0,
  12407             0,
  12408             0,
  12409             0,
  12410             0,
  12411             0,
  12412             0,
  12413             0,
  12414             0,
  12415             0,
  12416             0,
  12417             0,
  12418             0,
  12419             0,
  12420             0,
  12421             0,
  12422             0,
  12423             0,
  12424             0,
  12425             0,
  12426             0,
  12427             0,
  12428             0,
  12429             0,
  12430             0,
  12431             0,
  12432             0,
  12433             0,
  12434             0,
  12435             0,
  12436             0,
  12437             0,
  12438             0,
  12439             0,
  12440             0,
  12441             0,
  12442             0,
  12443             0,
  12444             0,
  12445             0,
  12446             0,
  12447             0,
  12448             0,
  12449             0,
  12450             0,
  12451             0,
  12452             0,
  12453             0,
  12454             0,
  12455             0,
  12456             0,
  12457             0,
  12458             0,
  12459             0,
  12460             0,
  12461             0,
  12462             0,
  12463             0,
  12464             0,
  12465             0,
  12466             0,
  12467             0,
  12468             0,
  12469             0,
  12470             0,
  12471             0,
  12472             0,
  12473             0,
  12474             0,
  12475             0,
  12476             0,
  12477             0,
  12478             0,
  12479             0,
  12480             0,
  12481             0,
  12482             0,
  12483             0,
  12484             0,
  12485             0,
  12486             0,
  12487             0,
  12488             0,
  12489             0,
  12490             0,
  12491             0,
  12492             0,
  12493             0,
  12494             0,
  12495             0,
  12496             0,
  12497             0,
  12498             0,
  12499             0,
  12500             0,
  12501             0,
  12502             0,
  12503             0,
  12504             0,
  12505             0,
  12506             0,
  12507             0,
  12508             0,
  12509             0,
  12510             0,
  12511             0,
  12512             0,
  12513             0,
  12514             0,
  12515             0,
  12516             0,
  12517             0,
  12518             0,
  12519             0,
  12520             0,
  12521             0,
  12522             0,
  12523             0,
  12524             0,
  12525             0,
  12526             0,
  12527             0,
  12528             0,
  12529             0,
  12530             0,
  12531             0,
  12532             0,
  12533             0,
  12534             0,
  12535             0,
  12536             0,
  12537             0,
  12538             0,
  12539             0,
  12540             0,
  12541             0,
  12542             0,
  12543             0,
  12544             0,
  12545             0,
  12546             0,
  12547             0,
  12548             0,
  12549             0,
  12550             0,
  12551             0,
  12552             0,
  12553             0,
  12554             0,
  12555             0,
  12556             0,
  12557             0,
  12558             0,
  12559             0,
  12560             0,
  12561             0,
  12562             0,
  12563             0,
  12564             0,
  12565             0,
  12566             0,
  12567             0,
  12568             0,
  12569             0,
  12570             0,
  12571             0,
  12572             0,
  12573             0,
  12574             0,
  12575             0,
  12576             0,
  12577             0,
  12578             0,
  12579             0,
  12580             0,
  12581             0,
  12582             0,
  12583             0,
  12584             0,
  12585             0,
  12586             0,
  12587             0,
  12588             0,
  12589             0,
  12590             0,
  12591             0,
  12592             0,
  12593             0,
  12594             0,
  12595             0,
  12596             0,
  12597             0,
  12598             0,
  12599             0,
  12600             0,
  12601             0,
  12602             0,
  12603             0,
  12604             0,
  12605             0,
  12606             0,
  12607             0,
  12608             0,
  12609             0,
  12610             0,
  12611             0,
  12612             0,
  12613             0,
  12614             0,
  12615             0,
  12616             0,
  12617             0,
  12618             0,
  12619             0,
  12620             0,
  12621             0,
  12622             0,
  12623             0,
  12624             0,
  12625             0,
  12626             0,
  12627             0,
  12628             0,
  12629             0,
  12630             0,
  12631             0,
  12632             0,
  12633             0,
  12634             0,
  12635             0,
  12636             0,
  12637             0,
  12638             0,
  12639             0,
  12640             0,
  12641             0,
  12642             0,
  12643             0,
  12644             0,
  12645             0,
  12646             0,
  12647             0,
  12648             0,
  12649             0,
  12650             0,
  12651             0,
  12652             0,
  12653             0,
  12654             0,
  12655             0,
  12656             0,
  12657             0,
  12658             0,
  12659             0,
  12660             // `e`.
  12661             cbor::NEG_TWO,
  12662             cbor::BYTES | 3,
  12663             // e.
  12664             1,
  12665             0,
  12666             1,
  12667         ];
  12668         let n = [
  12669             111, 183, 124, 133, 38, 167, 70, 148, 44, 50, 30, 60, 121, 14, 38, 37, 96, 114, 107,
  12670             195, 248, 64, 79, 36, 237, 140, 43, 27, 94, 74, 102, 152, 135, 102, 184, 150, 186, 206,
  12671             185, 19, 165, 209, 48, 98, 98, 9, 3, 205, 208, 82, 250, 105, 132, 201, 73, 62, 60, 165,
  12672             100, 128, 153, 9, 41, 118, 66, 95, 236, 214, 73, 135, 197, 68, 184, 10, 27, 116, 204,
  12673             145, 50, 174, 58, 42, 183, 181, 119, 232, 126, 252, 217, 96, 162, 190, 103, 122, 64,
  12674             87, 145, 45, 32, 207, 17, 239, 223, 3, 35, 14, 112, 119, 124, 141, 123, 208, 239, 105,
  12675             81, 217, 151, 162, 190, 17, 88, 182, 176, 158, 81, 200, 42, 166, 133, 48, 23, 236, 55,
  12676             117, 248, 233, 151, 203, 122, 155, 231, 46, 177, 20, 20, 151, 64, 222, 239, 226, 7, 21,
  12677             254, 81, 202, 64, 232, 161, 235, 22, 51, 246, 207, 213, 0, 229, 138, 46, 222, 205, 157,
  12678             108, 139, 253, 230, 80, 50, 2, 122, 212, 163, 100, 180, 114, 12, 113, 52, 56, 99, 188,
  12679             42, 198, 212, 23, 182, 222, 56, 221, 200, 79, 96, 239, 221, 135, 10, 17, 106, 183, 56,
  12680             104, 68, 94, 198, 196, 35, 200, 83, 204, 26, 185, 204, 212, 31, 183, 19, 111, 233, 13,
  12681             72, 93, 53, 65, 111, 59, 242, 122, 160, 244, 162, 126, 38, 235, 156, 47, 88, 39, 132,
  12682             153, 79, 0, 133, 78, 7, 218, 165, 241,
  12683         ];
  12684         let e = 0x0001_0001u32;
  12685         let d = [
  12686             145, 79, 21, 97, 233, 3, 192, 194, 177, 68, 181, 80, 120, 197, 23, 44, 185, 74, 144, 0,
  12687             132, 149, 139, 11, 16, 224, 4, 112, 236, 94, 238, 97, 121, 124, 213, 145, 24, 253, 168,
  12688             35, 190, 205, 132, 115, 33, 201, 38, 253, 246, 180, 66, 155, 165, 46, 3, 254, 68, 108,
  12689             154, 247, 246, 45, 187, 0, 204, 96, 185, 157, 249, 174, 158, 38, 62, 244, 183, 76, 102,
  12690             6, 219, 92, 212, 138, 59, 147, 163, 219, 111, 39, 105, 21, 236, 196, 38, 255, 114, 247,
  12691             82, 104, 113, 204, 29, 152, 209, 219, 48, 239, 74, 129, 19, 247, 33, 239, 119, 166,
  12692             216, 152, 94, 138, 238, 164, 242, 129, 50, 150, 57, 20, 53, 224, 56, 241, 138, 97, 111,
  12693             215, 107, 212, 195, 146, 108, 143, 0, 229, 181, 171, 73, 152, 105, 146, 25, 243, 242,
  12694             140, 252, 248, 162, 247, 63, 168, 180, 20, 153, 120, 10, 248, 211, 1, 71, 127, 212,
  12695             249, 237, 203, 202, 48, 26, 216, 226, 228, 186, 13, 204, 70, 255, 240, 89, 255, 59, 83,
  12696             31, 253, 55, 43, 158, 90, 248, 83, 32, 159, 105, 57, 134, 34, 96, 18, 255, 245, 153,
  12697             162, 60, 91, 99, 220, 51, 44, 85, 114, 67, 125, 202, 65, 217, 245, 40, 8, 81, 165, 142,
  12698             24, 245, 127, 122, 247, 152, 212, 75, 45, 59, 90, 184, 234, 31, 147, 36, 8, 212, 45,
  12699             50, 23, 3, 25, 253, 87, 227, 79, 119, 161,
  12700         ];
  12701         let p = BoxedUint::from_le_slice_vartime(
  12702             [
  12703                 215, 166, 5, 21, 11, 179, 41, 77, 198, 92, 165, 48, 77, 162, 42, 41, 206, 141, 60,
  12704                 69, 47, 164, 19, 92, 46, 72, 100, 238, 100, 53, 214, 197, 163, 185, 6, 140, 229,
  12705                 250, 195, 77, 8, 12, 5, 236, 178, 173, 86, 201, 43, 213, 165, 51, 108, 101, 161,
  12706                 99, 76, 240, 14, 234, 76, 197, 137, 53, 198, 168, 135, 205, 212, 198, 120, 29, 16,
  12707                 82, 98, 233, 236, 177, 12, 171, 141, 100, 107, 146, 33, 176, 125, 202, 172, 79,
  12708                 147, 179, 30, 62, 247, 206, 169, 19, 168, 114, 26, 73, 108, 178, 105, 84, 89, 191,
  12709                 168, 253, 228, 214, 54, 16, 212, 199, 111, 72, 3, 41, 247, 227, 165, 244, 32, 188,
  12710                 24, 247,
  12711             ]
  12712             .as_slice(),
  12713         );
  12714         let p_2 = BoxedUint::from_le_slice_vartime(
  12715             [
  12716                 41, 25, 198, 240, 134, 206, 121, 57, 11, 5, 134, 192, 212, 77, 229, 197, 14, 78,
  12717                 85, 212, 190, 114, 179, 188, 21, 171, 174, 12, 104, 74, 15, 164, 136, 173, 62, 177,
  12718                 141, 213, 93, 102, 147, 83, 59, 124, 146, 59, 175, 213, 55, 27, 25, 248, 154, 29,
  12719                 39, 85, 50, 235, 134, 60, 203, 106, 186, 195, 190, 185, 71, 169, 142, 236, 92, 11,
  12720                 250, 187, 198, 8, 201, 184, 120, 178, 227, 87, 63, 243, 89, 227, 234, 184, 28, 252,
  12721                 112, 211, 193, 69, 23, 92, 5, 72, 93, 53, 69, 159, 73, 160, 105, 244, 249, 94, 214,
  12722                 173, 9, 236, 4, 255, 129, 11, 224, 140, 252, 168, 57, 143, 176, 241, 60, 219, 90,
  12723                 250,
  12724             ]
  12725             .as_slice(),
  12726         );
  12727         let key = RsaPrivateKey::from_components(
  12728             BoxedUint::from_le_slice_vartime(n.as_slice()),
  12729             e.into(),
  12730             BoxedUint::from_le_slice_vartime(d.as_slice()),
  12731             vec![p, p_2],
  12732         )
  12733         .unwrap()
  12734         .to_public_key();
  12735         let pub_key = key.to_public_key_der().unwrap();
  12736         let att_obj_len = att_obj.len();
  12737         let n_start_idx = att_obj_len - 261;
  12738         let e_meta_start_idx = n_start_idx + 256;
  12739         // Correct and won't `panic`.
  12740         att_obj[n_start_idx..e_meta_start_idx]
  12741             .copy_from_slice(key.n().to_be_bytes_trimmed_vartime().as_ref());
  12742         let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
  12743         // Won't `panic`.
  12744         let b64_adata = base64url_nopad::encode(&att_obj[31..]);
  12745         let b64_key = base64url_nopad::encode(pub_key.as_bytes());
  12746         let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
  12747         // Base case is valid.
  12748         assert!(
  12749             serde_json::from_str::<Registration>(
  12750                 serde_json::json!({
  12751                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12752                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12753                     "response": {
  12754                         "clientDataJSON": b64_cdata_json,
  12755                         "authenticatorData": b64_adata,
  12756                         "transports": [],
  12757                         "publicKey": b64_key,
  12758                         "publicKeyAlgorithm": -257i16,
  12759                         "attestationObject": b64_aobj,
  12760                     },
  12761                     "clientExtensionResults": {},
  12762                     "type": "public-key"
  12763                 })
  12764                 .to_string()
  12765                 .as_str()
  12766             )
  12767             .is_ok_and(
  12768                 |reg| reg.response.client_data_json == c_data_json.as_bytes()
  12769                     && reg.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
  12770                     && reg.response.attestation_object_and_c_data_hash[att_obj_len..]
  12771                         == *Sha256::digest(c_data_json.as_bytes())
  12772                     && reg.response.transports.is_empty()
  12773                     && matches!(reg.authenticator_attachment, AuthenticatorAttachment::None)
  12774                     && reg.client_extension_results.cred_props.is_none()
  12775                     && reg.client_extension_results.prf.is_none()
  12776             )
  12777         );
  12778         // `publicKeyAlgorithm` mismatch.
  12779         let mut err = Error::invalid_value(
  12780             Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
  12781             &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Rs256).as_str()
  12782         )
  12783         .to_string().into_bytes();
  12784         assert_eq!(
  12785             serde_json::from_str::<Registration>(
  12786                 serde_json::json!({
  12787                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12788                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12789                     "response": {
  12790                         "clientDataJSON": b64_cdata_json,
  12791                         "authenticatorData": b64_adata,
  12792                         "transports": [],
  12793                         "publicKey": b64_key,
  12794                         "publicKeyAlgorithm": -8i8,
  12795                         "attestationObject": b64_aobj,
  12796                     },
  12797                     "clientExtensionResults": {},
  12798                     "type": "public-key"
  12799                 })
  12800                 .to_string()
  12801                 .as_str()
  12802             )
  12803             .unwrap_err()
  12804             .to_string()
  12805             .into_bytes()
  12806             .get(..err.len()),
  12807             Some(err.as_slice())
  12808         );
  12809         // Missing `publicKeyAlgorithm`.
  12810         err = Error::missing_field("publicKeyAlgorithm")
  12811             .to_string()
  12812             .into_bytes();
  12813         assert_eq!(
  12814             serde_json::from_str::<Registration>(
  12815                 serde_json::json!({
  12816                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12817                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12818                     "response": {
  12819                         "clientDataJSON": b64_cdata_json,
  12820                         "authenticatorData": b64_adata,
  12821                         "transports": [],
  12822                         "publicKey": b64_key,
  12823                         "attestationObject": b64_aobj,
  12824                     },
  12825                     "clientExtensionResults": {},
  12826                     "type": "public-key"
  12827                 })
  12828                 .to_string()
  12829                 .as_str()
  12830             )
  12831             .unwrap_err()
  12832             .to_string()
  12833             .into_bytes()
  12834             .get(..err.len()),
  12835             Some(err.as_slice())
  12836         );
  12837         // `null` `publicKeyAlgorithm`.
  12838         err = Error::invalid_type(Unexpected::Other("null"), &"publicKeyAlgorithm")
  12839             .to_string()
  12840             .into_bytes();
  12841         assert_eq!(
  12842             serde_json::from_str::<Registration>(
  12843                 serde_json::json!({
  12844                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12845                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12846                     "response": {
  12847                         "clientDataJSON": b64_cdata_json,
  12848                         "authenticatorData": b64_adata,
  12849                         "transports": [],
  12850                         "publicKey": b64_key,
  12851                         "publicKeyAlgorithm": null,
  12852                         "attestationObject": b64_aobj,
  12853                     },
  12854                     "clientExtensionResults": {},
  12855                     "type": "public-key"
  12856                 })
  12857                 .to_string()
  12858                 .as_str()
  12859             )
  12860             .unwrap_err()
  12861             .to_string()
  12862             .into_bytes()
  12863             .get(..err.len()),
  12864             Some(err.as_slice())
  12865         );
  12866         // `publicKey` mismatch.
  12867         let bad_pub_key = RsaPrivateKey::from_components(
  12868             BoxedUint::from_le_slice_vartime(
  12869                 [
  12870                     175, 161, 161, 75, 52, 244, 72, 168, 29, 119, 33, 120, 3, 222, 231, 152, 222,
  12871                     119, 112, 83, 221, 237, 74, 174, 79, 216, 147, 251, 245, 94, 234, 114, 254, 21,
  12872                     17, 254, 8, 115, 75, 127, 150, 87, 59, 109, 230, 116, 85, 90, 11, 160, 63, 217,
  12873                     9, 38, 187, 250, 226, 183, 38, 164, 182, 218, 22, 19, 58, 189, 83, 219, 11,
  12874                     144, 15, 99, 151, 166, 46, 57, 17, 111, 189, 131, 142, 113, 85, 122, 188, 238,
  12875                     52, 21, 116, 125, 102, 195, 182, 165, 29, 156, 213, 182, 125, 156, 88, 56, 221,
  12876                     2, 98, 43, 210, 115, 32, 4, 105, 88, 181, 158, 207, 236, 162, 250, 253, 240,
  12877                     72, 8, 253, 50, 220, 247, 76, 170, 143, 68, 225, 231, 113, 64, 244, 17, 138,
  12878                     162, 233, 33, 2, 67, 11, 223, 188, 232, 152, 193, 20, 32, 243, 52, 64, 43, 2,
  12879                     243, 8, 77, 150, 232, 109, 148, 95, 127, 55, 71, 162, 34, 54, 83, 135, 52, 172,
  12880                     191, 32, 42, 106, 43, 211, 206, 100, 104, 110, 232, 5, 43, 120, 180, 166, 40,
  12881                     144, 233, 239, 103, 134, 103, 255, 224, 138, 184, 208, 137, 127, 36, 189, 143,
  12882                     248, 201, 2, 218, 51, 232, 96, 30, 83, 124, 109, 241, 23, 179, 247, 151, 238,
  12883                     212, 204, 44, 43, 223, 148, 241, 172, 10, 235, 155, 94, 68, 116, 24, 116, 191,
  12884                     86, 53, 127, 35, 133, 198, 204, 59, 76, 110, 16, 1, 15, 148, 135, 157,
  12885                 ]
  12886                 .as_slice(),
  12887             ),
  12888             0x0001_0001u32.into(),
  12889             BoxedUint::from_le_slice_vartime(
  12890                 [
  12891                     129, 93, 123, 251, 104, 29, 84, 203, 116, 100, 75, 237, 111, 160, 12, 100, 172,
  12892                     76, 57, 178, 144, 235, 81, 61, 115, 243, 28, 40, 183, 22, 56, 150, 68, 38, 220,
  12893                     62, 233, 110, 48, 174, 35, 197, 244, 109, 148, 109, 36, 69, 69, 82, 225, 113,
  12894                     175, 6, 239, 27, 193, 101, 50, 239, 122, 102, 7, 46, 98, 79, 195, 116, 155,
  12895                     158, 138, 147, 51, 93, 24, 237, 246, 82, 14, 109, 144, 250, 239, 93, 63, 214,
  12896                     96, 130, 226, 134, 198, 145, 161, 11, 231, 97, 214, 180, 255, 95, 158, 88, 108,
  12897                     254, 243, 177, 133, 184, 92, 95, 148, 88, 55, 124, 245, 244, 84, 86, 4, 121,
  12898                     44, 231, 97, 176, 190, 29, 155, 40, 57, 69, 165, 80, 168, 9, 56, 43, 233, 6,
  12899                     14, 157, 112, 223, 64, 88, 141, 7, 65, 23, 64, 208, 6, 83, 61, 8, 182, 248,
  12900                     126, 84, 179, 163, 80, 238, 90, 133, 4, 14, 71, 177, 175, 27, 29, 151, 211,
  12901                     108, 162, 195, 7, 157, 167, 86, 169, 3, 87, 235, 89, 158, 237, 216, 31, 243,
  12902                     197, 62, 5, 84, 131, 230, 186, 248, 49, 12, 93, 244, 61, 135, 180, 17, 162,
  12903                     241, 13, 115, 241, 138, 219, 98, 155, 166, 191, 63, 12, 37, 1, 165, 178, 84,
  12904                     200, 72, 80, 41, 77, 136, 217, 141, 246, 209, 31, 243, 159, 71, 43, 246, 159,
  12905                     182, 171, 116, 12, 3, 142, 235, 218, 164, 70, 90, 147, 238, 42, 75,
  12906                 ]
  12907                 .as_slice(),
  12908             ),
  12909             vec![
  12910                 BoxedUint::from_le_slice_vartime(
  12911                     [
  12912                         215, 199, 110, 28, 64, 16, 16, 109, 106, 152, 150, 124, 52, 166, 121, 92,
  12913                         242, 13, 0, 69, 7, 152, 72, 172, 118, 63, 156, 180, 140, 39, 53, 29, 197,
  12914                         224, 177, 48, 41, 221, 102, 65, 17, 185, 55, 62, 219, 152, 227, 7, 78, 219,
  12915                         14, 139, 71, 204, 144, 152, 14, 39, 247, 244, 165, 224, 234, 60, 213, 74,
  12916                         237, 30, 102, 177, 242, 138, 168, 31, 122, 47, 206, 155, 225, 113, 103,
  12917                         175, 152, 244, 27, 233, 112, 223, 248, 38, 215, 178, 20, 244, 8, 121, 26,
  12918                         11, 70, 122, 16, 85, 167, 87, 64, 216, 228, 227, 173, 57, 250, 8, 221, 38,
  12919                         12, 203, 212, 1, 112, 43, 72, 91, 225, 97, 228, 57, 154, 193,
  12920                     ]
  12921                     .as_slice(),
  12922                 ),
  12923                 BoxedUint::from_le_slice_vartime(
  12924                     [
  12925                         233, 89, 204, 152, 31, 242, 8, 110, 38, 190, 111, 159, 105, 105, 45, 85,
  12926                         15, 244, 30, 250, 174, 226, 219, 111, 107, 191, 196, 135, 17, 123, 186,
  12927                         167, 85, 13, 120, 197, 159, 129, 78, 237, 152, 31, 230, 26, 229, 253, 197,
  12928                         211, 105, 204, 126, 142, 250, 55, 26, 172, 65, 160, 45, 6, 99, 86, 66, 238,
  12929                         107, 6, 98, 171, 93, 224, 201, 160, 31, 204, 82, 120, 228, 158, 238, 6,
  12930                         190, 12, 150, 153, 239, 95, 57, 71, 100, 239, 235, 155, 73, 200, 5, 225,
  12931                         127, 185, 46, 48, 243, 84, 33, 142, 17, 19, 20, 23, 215, 16, 114, 58, 211,
  12932                         14, 73, 148, 168, 252, 159, 252, 125, 57, 101, 211, 188, 12, 77, 208,
  12933                     ]
  12934                     .as_slice(),
  12935                 ),
  12936             ],
  12937         )
  12938         .unwrap()
  12939         .to_public_key();
  12940         err = Error::invalid_value(
  12941             Unexpected::Bytes([0; 32].as_slice()),
  12942             &format!(
  12943                 "DER-encoded public key to match the public key within the attestation object: Rsa(RsaPubKey({:?}, 65537))",
  12944                 // Correct and won't `panic`.
  12945                 &att_obj[n_start_idx..e_meta_start_idx],
  12946             )
  12947             .as_str(),
  12948         )
  12949         .to_string().into_bytes();
  12950         assert_eq!(serde_json::from_str::<Registration>(
  12951             serde_json::json!({
  12952                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12953                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12954                 "response": {
  12955                     "clientDataJSON": b64_cdata_json,
  12956                     "authenticatorData": b64_adata,
  12957                     "transports": [],
  12958                     "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
  12959                     "publicKeyAlgorithm": -257i16,
  12960                     "attestationObject": b64_aobj,
  12961                 },
  12962                 "clientExtensionResults": {},
  12963                 "type": "public-key"
  12964             })
  12965             .to_string()
  12966             .as_str()
  12967             )
  12968             .unwrap_err().to_string().into_bytes().get(..err.len()),
  12969             Some(err.as_slice())
  12970         );
  12971         // Missing `publicKey` when using EdDSA, ES256, or RS256.
  12972         err = Error::missing_field("publicKey").to_string().into_bytes();
  12973         assert_eq!(
  12974             serde_json::from_str::<Registration>(
  12975                 serde_json::json!({
  12976                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  12977                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  12978                     "response": {
  12979                         "clientDataJSON": b64_cdata_json,
  12980                         "authenticatorData": b64_adata,
  12981                         "transports": [],
  12982                         "publicKeyAlgorithm": -257i16,
  12983                         "attestationObject": b64_aobj,
  12984                     },
  12985                     "clientExtensionResults": {},
  12986                     "type": "public-key"
  12987                 })
  12988                 .to_string()
  12989                 .as_str()
  12990             )
  12991             .unwrap_err()
  12992             .to_string()
  12993             .into_bytes()
  12994             .get(..err.len()),
  12995             Some(err.as_slice())
  12996         );
  12997         // `null` `publicKey` when using EdDSA, ES256, or RS256.
  12998         err = Error::invalid_type(Unexpected::Other("null"), &"publicKey")
  12999             .to_string()
  13000             .into_bytes();
  13001         assert_eq!(
  13002             serde_json::from_str::<Registration>(
  13003                 serde_json::json!({
  13004                     "id": "AAAAAAAAAAAAAAAAAAAAAA",
  13005                     "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  13006                     "response": {
  13007                         "clientDataJSON": b64_cdata_json,
  13008                         "authenticatorData": b64_adata,
  13009                         "transports": [],
  13010                         "publicKey": null,
  13011                         "publicKeyAlgorithm": -257i16,
  13012                         "attestationObject": b64_aobj,
  13013                     },
  13014                     "clientExtensionResults": {},
  13015                     "type": "public-key"
  13016                 })
  13017                 .to_string()
  13018                 .as_str()
  13019             )
  13020             .unwrap_err()
  13021             .to_string()
  13022             .into_bytes()
  13023             .get(..err.len()),
  13024             Some(err.as_slice())
  13025         );
  13026     }
  13027 }