webauthn_rp

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

tests.rs (233669B)


      1 use super::{
      2     super::{
      3         super::super::request::register::CoseAlgorithmIdentifier, AKP, ALG,
      4         AuthenticatorAttachment, EC2, EDDSA, ES256, ES384, KTY, MLDSA44, MLDSA65, MLDSA87, OKP,
      5         RSA, cbor,
      6     },
      7     CustomRegistration, RegistrationRelaxed,
      8 };
      9 use ed25519_dalek::{VerifyingKey, pkcs8::EncodePublicKey as _};
     10 use ml_dsa::{MlDsa44, MlDsa65, MlDsa87, VerifyingKey as MlDsaVerKey};
     11 use p256::{
     12     PublicKey as P256PubKey, Sec1Point as P256Pt, SecretKey as P256Key,
     13     elliptic_curve::sec1::{FromSec1Point as _, ToSec1Point as _},
     14 };
     15 use p384::{PublicKey as P384PubKey, Sec1Point as P384Pt, SecretKey as P384Key};
     16 use rsa::{
     17     BoxedUint, RsaPrivateKey,
     18     sha2::{Digest as _, Sha256},
     19     traits::PublicKeyParts as _,
     20 };
     21 use serde::de::{Error as _, Unexpected};
     22 use serde_json::Error;
     23 #[expect(clippy::unwrap_used, reason = "OK in tests")]
     24 #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
     25 #[expect(
     26     clippy::cognitive_complexity,
     27     clippy::too_many_lines,
     28     reason = "a lot to test"
     29 )]
     30 #[test]
     31 fn eddsa_registration_deserialize_data_mismatch() {
     32     let c_data_json = serde_json::json!({}).to_string();
     33     let att_obj: [u8; 143] = [
     34         cbor::MAP_3,
     35         cbor::TEXT_3,
     36         b'f',
     37         b'm',
     38         b't',
     39         cbor::TEXT_4,
     40         b'n',
     41         b'o',
     42         b'n',
     43         b'e',
     44         cbor::TEXT_7,
     45         b'a',
     46         b't',
     47         b't',
     48         b'S',
     49         b't',
     50         b'm',
     51         b't',
     52         cbor::MAP_0,
     53         cbor::TEXT_8,
     54         b'a',
     55         b'u',
     56         b't',
     57         b'h',
     58         b'D',
     59         b'a',
     60         b't',
     61         b'a',
     62         cbor::BYTES_INFO_24,
     63         113,
     64         // `rpIdHash`.
     65         0,
     66         0,
     67         0,
     68         0,
     69         0,
     70         0,
     71         0,
     72         0,
     73         0,
     74         0,
     75         0,
     76         0,
     77         0,
     78         0,
     79         0,
     80         0,
     81         0,
     82         0,
     83         0,
     84         0,
     85         0,
     86         0,
     87         0,
     88         0,
     89         0,
     90         0,
     91         0,
     92         0,
     93         0,
     94         0,
     95         0,
     96         0,
     97         // `flags`.
     98         0b0100_0101,
     99         // `signCount`.
    100         0,
    101         0,
    102         0,
    103         0,
    104         // `aaguid`.
    105         0,
    106         0,
    107         0,
    108         0,
    109         0,
    110         0,
    111         0,
    112         0,
    113         0,
    114         0,
    115         0,
    116         0,
    117         0,
    118         0,
    119         0,
    120         0,
    121         // `credentialIdLength`.
    122         0,
    123         16,
    124         // `credentialId`.
    125         0,
    126         0,
    127         0,
    128         0,
    129         0,
    130         0,
    131         0,
    132         0,
    133         0,
    134         0,
    135         0,
    136         0,
    137         0,
    138         0,
    139         0,
    140         0,
    141         // Ed25519 COSE key.
    142         cbor::MAP_4,
    143         KTY,
    144         OKP,
    145         ALG,
    146         EDDSA,
    147         // `crv`.
    148         cbor::NEG_ONE,
    149         // `Ed25519`.
    150         cbor::SIX,
    151         // `x`.
    152         cbor::NEG_TWO,
    153         cbor::BYTES_INFO_24,
    154         32,
    155         // Compressed y-coordinate.
    156         1,
    157         1,
    158         1,
    159         1,
    160         1,
    161         1,
    162         1,
    163         1,
    164         1,
    165         1,
    166         1,
    167         1,
    168         1,
    169         1,
    170         1,
    171         1,
    172         1,
    173         1,
    174         1,
    175         1,
    176         1,
    177         1,
    178         1,
    179         1,
    180         1,
    181         1,
    182         1,
    183         1,
    184         1,
    185         1,
    186         1,
    187         1,
    188     ];
    189     let pub_key = VerifyingKey::from_bytes(&[1; 32])
    190         .unwrap()
    191         .to_public_key_der()
    192         .unwrap();
    193     let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
    194     let att_obj_len = att_obj.len();
    195     let auth_data_start = att_obj_len - 113;
    196     let b64_adata = base64url_nopad::encode(&att_obj[auth_data_start..]);
    197     let b64_key = base64url_nopad::encode(pub_key.as_bytes());
    198     let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
    199     // Base case is valid.
    200     assert!(
    201         serde_json::from_str::<RegistrationRelaxed>(
    202             serde_json::json!({
    203                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    204                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    205                 "response": {
    206                     "clientDataJSON": b64_cdata_json,
    207                     "authenticatorData": b64_adata,
    208                     "transports": ["ble", "usb", "hybrid", "internal", "nfc", "smart-card"],
    209                     "publicKey": b64_key,
    210                     "publicKeyAlgorithm": -8i8,
    211                     "attestationObject": b64_aobj,
    212                 },
    213                 "authenticatorAttachment": "cross-platform",
    214                 "clientExtensionResults": {},
    215                 "type": "public-key"
    216             })
    217             .to_string()
    218             .as_str()
    219         )
    220         .is_ok_and(
    221             |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
    222                 && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
    223                 && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
    224                     == *Sha256::digest(c_data_json.as_bytes())
    225                 && reg.0.response.transports.count() == 6
    226                 && matches!(
    227                     reg.0.authenticator_attachment,
    228                     AuthenticatorAttachment::CrossPlatform
    229                 )
    230                 && reg.0.client_extension_results.cred_props.is_none()
    231                 && reg.0.client_extension_results.prf.is_none()
    232         )
    233     );
    234     // `id` and `rawId` mismatch.
    235     let mut err = Error::invalid_value(
    236         Unexpected::Bytes(
    237             base64url_nopad::decode(b"ABABABABABABABABABABAA")
    238                 .unwrap()
    239                 .as_slice(),
    240         ),
    241         &format!("id and rawId to match: CredentialId({:?})", [0u8; 16]).as_str(),
    242     )
    243     .to_string()
    244     .into_bytes();
    245     assert_eq!(
    246         serde_json::from_str::<RegistrationRelaxed>(
    247             serde_json::json!({
    248                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    249                 "rawId": "ABABABABABABABABABABAA",
    250                 "response": {
    251                     "clientDataJSON": b64_cdata_json,
    252                     "authenticatorData": b64_adata,
    253                     "transports": [],
    254                     "publicKey": b64_key,
    255                     "publicKeyAlgorithm": -8i8,
    256                     "attestationObject": b64_aobj,
    257                 },
    258                 "clientExtensionResults": {},
    259                 "type": "public-key"
    260             })
    261             .to_string()
    262             .as_str()
    263         )
    264         .unwrap_err()
    265         .to_string()
    266         .into_bytes()
    267         .get(..err.len()),
    268         Some(err.as_slice())
    269     );
    270     // missing `id`.
    271     drop(
    272         serde_json::from_str::<RegistrationRelaxed>(
    273             serde_json::json!({
    274                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    275                 "response": {
    276                     "clientDataJSON": b64_cdata_json,
    277                     "authenticatorData": b64_adata,
    278                     "transports": [],
    279                     "publicKey": b64_key,
    280                     "publicKeyAlgorithm": -8i8,
    281                     "attestationObject": b64_aobj,
    282                 },
    283                 "clientExtensionResults": {},
    284                 "type": "public-key"
    285             })
    286             .to_string()
    287             .as_str(),
    288         )
    289         .unwrap(),
    290     );
    291     // `null` `id`.
    292     err = Error::invalid_type(Unexpected::Other("null"), &"CredentialId")
    293         .to_string()
    294         .into_bytes();
    295     assert_eq!(
    296         serde_json::from_str::<RegistrationRelaxed>(
    297             serde_json::json!({
    298                 "id": null,
    299                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    300                 "response": {
    301                     "clientDataJSON": null,
    302                     "authenticatorData": b64_adata,
    303                     "transports": [],
    304                     "publicKey": b64_key,
    305                     "publicKeyAlgorithm": -8i8,
    306                     "attestationObject": b64_aobj,
    307                 },
    308                 "clientExtensionResults": {},
    309                 "type": "public-key"
    310             })
    311             .to_string()
    312             .as_str()
    313         )
    314         .unwrap_err()
    315         .to_string()
    316         .into_bytes()
    317         .get(..err.len()),
    318         Some(err.as_slice())
    319     );
    320     // Missing `rawId`.
    321     drop(
    322         serde_json::from_str::<RegistrationRelaxed>(
    323             serde_json::json!({
    324                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    325                 "response": {
    326                     "clientDataJSON": b64_cdata_json,
    327                     "authenticatorData": b64_adata,
    328                     "transports": [],
    329                     "publicKey": b64_key,
    330                     "publicKeyAlgorithm": -8i8,
    331                     "attestationObject": b64_aobj,
    332                 },
    333                 "clientExtensionResults": {},
    334                 "type": "public-key"
    335             })
    336             .to_string()
    337             .as_str(),
    338         )
    339         .unwrap(),
    340     );
    341     // `null` `rawId`.
    342     err = Error::invalid_type(Unexpected::Other("null"), &"CredentialId")
    343         .to_string()
    344         .into_bytes();
    345     assert_eq!(
    346         serde_json::from_str::<RegistrationRelaxed>(
    347             serde_json::json!({
    348                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    349                 "rawId": null,
    350                 "response": {
    351                     "clientDataJSON": b64_cdata_json,
    352                     "authenticatorData": b64_adata,
    353                     "transports": [],
    354                     "publicKey": b64_key,
    355                     "publicKeyAlgorithm": -8i8,
    356                     "attestationObject": b64_aobj,
    357                 },
    358                 "clientExtensionResults": {},
    359                 "type": "public-key"
    360             })
    361             .to_string()
    362             .as_str()
    363         )
    364         .unwrap_err()
    365         .to_string()
    366         .into_bytes()
    367         .get(..err.len()),
    368         Some(err.as_slice())
    369     );
    370     // `id` and the credential id in authenticator data mismatch.
    371     err = Error::invalid_value(
    372         Unexpected::Bytes(
    373             base64url_nopad::decode(b"ABABABABABABABABABABAA")
    374                 .unwrap()
    375                 .as_slice(),
    376         ),
    377         &format!(
    378             "id, rawId, and the credential id in the attested credential data to all match: {:?}",
    379             [0u8; 16]
    380         )
    381         .as_str(),
    382     )
    383     .to_string()
    384     .into_bytes();
    385     assert_eq!(
    386         serde_json::from_str::<RegistrationRelaxed>(
    387             serde_json::json!({
    388                 "id": "ABABABABABABABABABABAA",
    389                 "rawId": "ABABABABABABABABABABAA",
    390                 "response": {
    391                     "clientDataJSON": b64_cdata_json,
    392                     "authenticatorData": b64_adata,
    393                     "transports": [],
    394                     "publicKey": b64_key,
    395                     "publicKeyAlgorithm": -8i8,
    396                     "attestationObject": b64_aobj,
    397                 },
    398                 "clientExtensionResults": {},
    399                 "type": "public-key"
    400             })
    401             .to_string()
    402             .as_str()
    403         )
    404         .unwrap_err()
    405         .to_string()
    406         .into_bytes()
    407         .get(..err.len()),
    408         Some(err.as_slice())
    409     );
    410     // `authenticatorData` mismatches `authData` in attestation object.
    411     let mut bad_auth = [0; 113];
    412     let bad_auth_len = bad_auth.len();
    413     bad_auth.copy_from_slice(&att_obj[auth_data_start..]);
    414     bad_auth[bad_auth_len - 32..].copy_from_slice([0; 32].as_slice());
    415     err = Error::invalid_value(
    416         Unexpected::Bytes(bad_auth.as_slice()),
    417         &format!("authenticator data to match the authenticator data portion of attestation object: {:?}", &att_obj[att_obj_len - bad_auth_len..]).as_str(),
    418     )
    419     .to_string().into_bytes();
    420     assert_eq!(
    421         serde_json::from_str::<RegistrationRelaxed>(
    422             serde_json::json!({
    423                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    424                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    425                 "response": {
    426                     "clientDataJSON": b64_cdata_json,
    427                     "authenticatorData": base64url_nopad::encode(bad_auth.as_slice()),
    428                     "transports": [],
    429                     "publicKey": b64_key,
    430                     "publicKeyAlgorithm": -8i8,
    431                     "attestationObject": b64_aobj,
    432                 },
    433                 "clientExtensionResults": {},
    434                 "type": "public-key"
    435             })
    436             .to_string()
    437             .as_str()
    438         )
    439         .unwrap_err()
    440         .to_string()
    441         .into_bytes()
    442         .get(..err.len()),
    443         Some(err.as_slice())
    444     );
    445     // Missing `authenticatorData`.
    446     drop(
    447         serde_json::from_str::<RegistrationRelaxed>(
    448             serde_json::json!({
    449                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    450                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    451                 "response": {
    452                     "clientDataJSON": b64_cdata_json,
    453                     "transports": [],
    454                     "publicKey": b64_key,
    455                     "publicKeyAlgorithm": -8i8,
    456                     "attestationObject": b64_aobj,
    457                 },
    458                 "clientExtensionResults": {},
    459                 "type": "public-key"
    460             })
    461             .to_string()
    462             .as_str(),
    463         )
    464         .unwrap(),
    465     );
    466     // `null `authenticatorData`.
    467     drop(
    468         serde_json::from_str::<RegistrationRelaxed>(
    469             serde_json::json!({
    470                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    471                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    472                 "response": {
    473                     "clientDataJSON": b64_cdata_json,
    474                     "transports": [],
    475                     "authenticatorData": null,
    476                     "publicKey": b64_key,
    477                     "publicKeyAlgorithm": -8i8,
    478                     "attestationObject": b64_aobj,
    479                 },
    480                 "clientExtensionResults": {},
    481                 "type": "public-key"
    482             })
    483             .to_string()
    484             .as_str(),
    485         )
    486         .unwrap(),
    487     );
    488     // `publicKeyAlgorithm` mismatch.
    489     err = Error::invalid_value(
    490         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
    491         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Eddsa).as_str()
    492     )
    493     .to_string().into_bytes();
    494     assert_eq!(
    495         serde_json::from_str::<RegistrationRelaxed>(
    496             serde_json::json!({
    497                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    498                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    499                 "response": {
    500                     "clientDataJSON": b64_cdata_json,
    501                     "authenticatorData": b64_adata,
    502                     "transports": [],
    503                     "publicKey": b64_key,
    504                     "publicKeyAlgorithm": -7i8,
    505                     "attestationObject": b64_aobj,
    506                 },
    507                 "clientExtensionResults": {},
    508                 "type": "public-key"
    509             })
    510             .to_string()
    511             .as_str()
    512         )
    513         .unwrap_err()
    514         .to_string()
    515         .into_bytes()
    516         .get(..err.len()),
    517         Some(err.as_slice())
    518     );
    519     // Missing `publicKeyAlgorithm`.
    520     drop(
    521         serde_json::from_str::<RegistrationRelaxed>(
    522             serde_json::json!({
    523                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    524                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    525                 "response": {
    526                     "clientDataJSON": b64_cdata_json,
    527                     "authenticatorData": b64_adata,
    528                     "transports": [],
    529                     "publicKey": b64_key,
    530                     "attestationObject": b64_aobj,
    531                 },
    532                 "clientExtensionResults": {},
    533                 "type": "public-key"
    534             })
    535             .to_string()
    536             .as_str(),
    537         )
    538         .unwrap(),
    539     );
    540     // `null` `publicKeyAlgorithm`.
    541     drop(
    542         serde_json::from_str::<RegistrationRelaxed>(
    543             serde_json::json!({
    544                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    545                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    546                 "response": {
    547                     "clientDataJSON": b64_cdata_json,
    548                     "authenticatorData": b64_adata,
    549                     "transports": [],
    550                     "publicKey": b64_key,
    551                     "publicKeyAlgorithm": null,
    552                     "attestationObject": b64_aobj,
    553                 },
    554                 "clientExtensionResults": {},
    555                 "type": "public-key"
    556             })
    557             .to_string()
    558             .as_str(),
    559         )
    560         .unwrap(),
    561     );
    562     // `publicKey` mismatch.
    563     err = Error::invalid_value(
    564         Unexpected::Bytes([0; 32].as_slice()),
    565         &format!(
    566             "DER-encoded public key to match the public key within the attestation object: Ed25519(Ed25519PubKey({:?}))",
    567             &att_obj[att_obj_len - 32..],
    568         )
    569         .as_str(),
    570     )
    571     .to_string().into_bytes();
    572     assert_eq!(serde_json::from_str::<RegistrationRelaxed>(
    573         serde_json::json!({
    574             "id": "AAAAAAAAAAAAAAAAAAAAAA",
    575             "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    576             "response": {
    577                 "clientDataJSON": b64_cdata_json,
    578                 "authenticatorData": b64_adata,
    579                 "transports": [],
    580                 "publicKey": base64url_nopad::encode(VerifyingKey::from_bytes(&[0; 32]).unwrap().to_public_key_der().unwrap().as_bytes()),
    581                 "publicKeyAlgorithm": -8i8,
    582                 "attestationObject": b64_aobj,
    583             },
    584             "clientExtensionResults": {},
    585             "type": "public-key"
    586         })
    587         .to_string()
    588         .as_str()
    589         )
    590         .unwrap_err().to_string().into_bytes().get(..err.len()),
    591         Some(err.as_slice())
    592     );
    593     // Missing `publicKey`.
    594     drop(
    595         serde_json::from_str::<RegistrationRelaxed>(
    596             serde_json::json!({
    597                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    598                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    599                 "response": {
    600                     "clientDataJSON": b64_cdata_json,
    601                     "authenticatorData": b64_adata,
    602                     "transports": [],
    603                     "publicKeyAlgorithm": -8i8,
    604                     "attestationObject": b64_aobj,
    605                 },
    606                 "clientExtensionResults": {},
    607                 "type": "public-key"
    608             })
    609             .to_string()
    610             .as_str(),
    611         )
    612         .unwrap(),
    613     );
    614     // `null` `publicKey`.
    615     drop(
    616         serde_json::from_str::<RegistrationRelaxed>(
    617             serde_json::json!({
    618                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    619                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    620                 "response": {
    621                     "clientDataJSON": b64_cdata_json,
    622                     "authenticatorData": b64_adata,
    623                     "transports": [],
    624                     "publicKey": null,
    625                     "publicKeyAlgorithm": -8i8,
    626                     "attestationObject": b64_aobj,
    627                 },
    628                 "clientExtensionResults": {},
    629                 "type": "public-key"
    630             })
    631             .to_string()
    632             .as_str(),
    633         )
    634         .unwrap(),
    635     );
    636     // Missing `transports`.
    637     drop(
    638         serde_json::from_str::<RegistrationRelaxed>(
    639             serde_json::json!({
    640                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    641                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    642                 "response": {
    643                     "clientDataJSON": b64_cdata_json,
    644                     "authenticatorData": b64_adata,
    645                     "publicKey": b64_key,
    646                     "publicKeyAlgorithm": -8i8,
    647                     "attestationObject": b64_aobj,
    648                 },
    649                 "clientExtensionResults": {},
    650                 "type": "public-key"
    651             })
    652             .to_string()
    653             .as_str(),
    654         )
    655         .unwrap(),
    656     );
    657     // Duplicate `transports` are allowed.
    658     assert!(
    659         serde_json::from_str::<RegistrationRelaxed>(
    660             serde_json::json!({
    661                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    662                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    663                 "response": {
    664                     "clientDataJSON": b64_cdata_json,
    665                     "authenticatorData": b64_adata,
    666                     "transports": ["usb", "usb"],
    667                     "publicKey": b64_key,
    668                     "publicKeyAlgorithm": -8i8,
    669                     "attestationObject": b64_aobj,
    670                 },
    671                 "clientExtensionResults": {},
    672                 "type": "public-key"
    673             })
    674             .to_string()
    675             .as_str()
    676         )
    677         .is_ok_and(|reg| reg.0.response.transports.count() == 1)
    678     );
    679     // `null` `transports`.
    680     drop(
    681         serde_json::from_str::<RegistrationRelaxed>(
    682             serde_json::json!({
    683                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    684                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    685                 "response": {
    686                     "clientDataJSON": b64_cdata_json,
    687                     "authenticatorData": b64_adata,
    688                     "transports": null,
    689                     "publicKey": b64_key,
    690                     "publicKeyAlgorithm": -8i8,
    691                     "attestationObject": b64_aobj,
    692                 },
    693                 "clientExtensionResults": {},
    694                 "type": "public-key"
    695             })
    696             .to_string()
    697             .as_str(),
    698         )
    699         .unwrap(),
    700     );
    701     // Unknown `transports`.
    702     err = Error::invalid_value(
    703         Unexpected::Str("Usb"),
    704         &"'ble', 'cable', 'hybrid', 'internal', 'nfc', 'smart-card', or 'usb'",
    705     )
    706     .to_string()
    707     .into_bytes();
    708     assert_eq!(
    709         serde_json::from_str::<RegistrationRelaxed>(
    710             serde_json::json!({
    711                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    712                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    713                 "response": {
    714                     "clientDataJSON": b64_cdata_json,
    715                     "authenticatorData": b64_adata,
    716                     "transports": ["Usb"],
    717                     "publicKey": b64_key,
    718                     "publicKeyAlgorithm": -8i8,
    719                     "attestationObject": b64_aobj,
    720                 },
    721                 "clientExtensionResults": {},
    722                 "type": "public-key"
    723             })
    724             .to_string()
    725             .as_str()
    726         )
    727         .unwrap_err()
    728         .to_string()
    729         .into_bytes()
    730         .get(..err.len()),
    731         Some(err.as_slice())
    732     );
    733     // `null` `authenticatorAttachment`.
    734     assert!(
    735         serde_json::from_str::<RegistrationRelaxed>(
    736             serde_json::json!({
    737                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    738                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    739                 "response": {
    740                     "clientDataJSON": b64_cdata_json,
    741                     "authenticatorData": b64_adata,
    742                     "transports": [],
    743                     "publicKey": b64_key,
    744                     "publicKeyAlgorithm": -8i8,
    745                     "attestationObject": b64_aobj,
    746                 },
    747                 "authenticatorAttachment": null,
    748                 "clientExtensionResults": {},
    749                 "type": "public-key"
    750             })
    751             .to_string()
    752             .as_str()
    753         )
    754         .is_ok_and(|reg| matches!(
    755             reg.0.authenticator_attachment,
    756             AuthenticatorAttachment::None
    757         ))
    758     );
    759     // Unknown `authenticatorAttachment`.
    760     err = Error::invalid_value(
    761         Unexpected::Str("Platform"),
    762         &"'platform' or 'cross-platform'",
    763     )
    764     .to_string()
    765     .into_bytes();
    766     assert_eq!(
    767         serde_json::from_str::<RegistrationRelaxed>(
    768             serde_json::json!({
    769                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    770                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    771                 "response": {
    772                     "clientDataJSON": b64_cdata_json,
    773                     "authenticatorData": b64_adata,
    774                     "transports": [],
    775                     "publicKey": b64_key,
    776                     "publicKeyAlgorithm": -8i8,
    777                     "attestationObject": b64_aobj,
    778                 },
    779                 "authenticatorAttachment": "Platform",
    780                 "clientExtensionResults": {},
    781                 "type": "public-key"
    782             })
    783             .to_string()
    784             .as_str()
    785         )
    786         .unwrap_err()
    787         .to_string()
    788         .into_bytes()
    789         .get(..err.len()),
    790         Some(err.as_slice())
    791     );
    792     // Missing `clientDataJSON`.
    793     err = Error::missing_field("clientDataJSON")
    794         .to_string()
    795         .into_bytes();
    796     assert_eq!(
    797         serde_json::from_str::<RegistrationRelaxed>(
    798             serde_json::json!({
    799                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    800                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    801                 "response": {
    802                     "authenticatorData": b64_adata,
    803                     "transports": [],
    804                     "publicKey": b64_key,
    805                     "publicKeyAlgorithm": -8i8,
    806                     "attestationObject": b64_aobj,
    807                 },
    808                 "clientExtensionResults": {},
    809                 "type": "public-key"
    810             })
    811             .to_string()
    812             .as_str()
    813         )
    814         .unwrap_err()
    815         .to_string()
    816         .into_bytes()
    817         .get(..err.len()),
    818         Some(err.as_slice())
    819     );
    820     // `null` `clientDataJSON`.
    821     err = Error::invalid_type(Unexpected::Other("null"), &"base64url-encoded data")
    822         .to_string()
    823         .into_bytes();
    824     assert_eq!(
    825         serde_json::from_str::<RegistrationRelaxed>(
    826             serde_json::json!({
    827                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    828                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    829                 "response": {
    830                     "clientDataJSON": null,
    831                     "authenticatorData": b64_adata,
    832                     "transports": [],
    833                     "publicKey": b64_key,
    834                     "publicKeyAlgorithm": -8i8,
    835                     "attestationObject": b64_aobj,
    836                 },
    837                 "clientExtensionResults": {},
    838                 "type": "public-key"
    839             })
    840             .to_string()
    841             .as_str()
    842         )
    843         .unwrap_err()
    844         .to_string()
    845         .into_bytes()
    846         .get(..err.len()),
    847         Some(err.as_slice())
    848     );
    849     // Missing `attestationObject`.
    850     err = Error::missing_field("attestationObject")
    851         .to_string()
    852         .into_bytes();
    853     assert_eq!(
    854         serde_json::from_str::<RegistrationRelaxed>(
    855             serde_json::json!({
    856                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    857                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    858                 "response": {
    859                     "clientDataJSON": b64_cdata_json,
    860                     "authenticatorData": b64_adata,
    861                     "transports": [],
    862                     "publicKey": b64_key,
    863                     "publicKeyAlgorithm": -8i8,
    864                 },
    865                 "clientExtensionResults": {},
    866                 "type": "public-key"
    867             })
    868             .to_string()
    869             .as_str()
    870         )
    871         .unwrap_err()
    872         .to_string()
    873         .into_bytes()
    874         .get(..err.len()),
    875         Some(err.as_slice())
    876     );
    877     // `null` `attestationObject`.
    878     err = Error::invalid_type(
    879         Unexpected::Other("null"),
    880         &"base64url-encoded attestation object",
    881     )
    882     .to_string()
    883     .into_bytes();
    884     assert_eq!(
    885         serde_json::from_str::<RegistrationRelaxed>(
    886             serde_json::json!({
    887                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    888                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    889                 "response": {
    890                     "clientDataJSON": b64_cdata_json,
    891                     "authenticatorData": b64_adata,
    892                     "transports": [],
    893                     "publicKey": b64_key,
    894                     "publicKeyAlgorithm": -8i8,
    895                     "attestationObject": null,
    896                 },
    897                 "clientExtensionResults": {},
    898                 "type": "public-key"
    899             })
    900             .to_string()
    901             .as_str()
    902         )
    903         .unwrap_err()
    904         .to_string()
    905         .into_bytes()
    906         .get(..err.len()),
    907         Some(err.as_slice())
    908     );
    909     // Missing `response`.
    910     err = Error::missing_field("response").to_string().into_bytes();
    911     assert_eq!(
    912         serde_json::from_str::<RegistrationRelaxed>(
    913             serde_json::json!({
    914                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    915                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    916                 "clientExtensionResults": {},
    917                 "type": "public-key"
    918             })
    919             .to_string()
    920             .as_str()
    921         )
    922         .unwrap_err()
    923         .to_string()
    924         .into_bytes()
    925         .get(..err.len()),
    926         Some(err.as_slice())
    927     );
    928     // `null` `response`.
    929     err = Error::invalid_type(Unexpected::Other("null"), &"AuthenticatorAttestation")
    930         .to_string()
    931         .into_bytes();
    932     assert_eq!(
    933         serde_json::from_str::<RegistrationRelaxed>(
    934             serde_json::json!({
    935                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    936                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    937                 "response": null,
    938                 "clientExtensionResults": {},
    939                 "type": "public-key"
    940             })
    941             .to_string()
    942             .as_str()
    943         )
    944         .unwrap_err()
    945         .to_string()
    946         .into_bytes()
    947         .get(..err.len()),
    948         Some(err.as_slice())
    949     );
    950     // Empty `response`.
    951     err = Error::missing_field("clientDataJSON")
    952         .to_string()
    953         .into_bytes();
    954     assert_eq!(
    955         serde_json::from_str::<RegistrationRelaxed>(
    956             serde_json::json!({
    957                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    958                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    959                 "response": {},
    960                 "clientExtensionResults": {},
    961                 "type": "public-key"
    962             })
    963             .to_string()
    964             .as_str()
    965         )
    966         .unwrap_err()
    967         .to_string()
    968         .into_bytes()
    969         .get(..err.len()),
    970         Some(err.as_slice())
    971     );
    972     // Missing `clientExtensionResults`.
    973     drop(
    974         serde_json::from_str::<RegistrationRelaxed>(
    975             serde_json::json!({
    976                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    977                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    978                 "response": {
    979                     "clientDataJSON": b64_cdata_json,
    980                     "authenticatorData": b64_adata,
    981                     "transports": [],
    982                     "publicKey": b64_key,
    983                     "publicKeyAlgorithm": -8i8,
    984                     "attestationObject": b64_aobj,
    985                 },
    986                 "type": "public-key"
    987             })
    988             .to_string()
    989             .as_str(),
    990         )
    991         .unwrap(),
    992     );
    993     // `null` `clientExtensionResults`.
    994     drop(
    995         serde_json::from_str::<RegistrationRelaxed>(
    996             serde_json::json!({
    997                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
    998                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
    999                 "response": {
   1000                     "clientDataJSON": b64_cdata_json,
   1001                     "authenticatorData": b64_adata,
   1002                     "transports": [],
   1003                     "publicKey": b64_key,
   1004                     "publicKeyAlgorithm": -8i8,
   1005                     "attestationObject": b64_aobj,
   1006                 },
   1007                 "clientExtensionResults": null,
   1008                 "type": "public-key"
   1009             })
   1010             .to_string()
   1011             .as_str(),
   1012         )
   1013         .unwrap(),
   1014     );
   1015     // Missing `type`.
   1016     drop(
   1017         serde_json::from_str::<RegistrationRelaxed>(
   1018             serde_json::json!({
   1019                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1020                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1021                 "response": {
   1022                     "clientDataJSON": b64_cdata_json,
   1023                     "authenticatorData": b64_adata,
   1024                     "transports": [],
   1025                     "publicKey": b64_key,
   1026                     "publicKeyAlgorithm": -8i8,
   1027                     "attestationObject": b64_aobj,
   1028                 },
   1029                 "clientExtensionResults": {},
   1030             })
   1031             .to_string()
   1032             .as_str(),
   1033         )
   1034         .unwrap(),
   1035     );
   1036     // `null` `type`.
   1037     err = Error::invalid_type(Unexpected::Other("null"), &"public-key")
   1038         .to_string()
   1039         .into_bytes();
   1040     assert_eq!(
   1041         serde_json::from_str::<RegistrationRelaxed>(
   1042             serde_json::json!({
   1043                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1044                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1045                 "response": {
   1046                     "clientDataJSON": b64_cdata_json,
   1047                     "authenticatorData": b64_adata,
   1048                     "transports": [],
   1049                     "publicKey": b64_key,
   1050                     "publicKeyAlgorithm": -8i8,
   1051                     "attestationObject": b64_aobj,
   1052                 },
   1053                 "clientExtensionResults": {},
   1054                 "type": null
   1055             })
   1056             .to_string()
   1057             .as_str()
   1058         )
   1059         .unwrap_err()
   1060         .to_string()
   1061         .into_bytes()
   1062         .get(..err.len()),
   1063         Some(err.as_slice())
   1064     );
   1065     // Not exactly `public-type` `type`.
   1066     err = Error::invalid_value(Unexpected::Str("Public-key"), &"public-key")
   1067         .to_string()
   1068         .into_bytes();
   1069     assert_eq!(
   1070         serde_json::from_str::<RegistrationRelaxed>(
   1071             serde_json::json!({
   1072                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1073                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1074                 "response": {
   1075                     "clientDataJSON": b64_cdata_json,
   1076                     "authenticatorData": b64_adata,
   1077                     "transports": [],
   1078                     "publicKey": b64_key,
   1079                     "publicKeyAlgorithm": -8i8,
   1080                     "attestationObject": b64_aobj,
   1081                 },
   1082                 "clientExtensionResults": {},
   1083                 "type": "Public-key"
   1084             })
   1085             .to_string()
   1086             .as_str()
   1087         )
   1088         .unwrap_err()
   1089         .to_string()
   1090         .into_bytes()
   1091         .get(..err.len()),
   1092         Some(err.as_slice())
   1093     );
   1094     // `null`.
   1095     err = Error::invalid_type(Unexpected::Other("null"), &"PublicKeyCredential")
   1096         .to_string()
   1097         .into_bytes();
   1098     assert_eq!(
   1099         serde_json::from_str::<RegistrationRelaxed>(serde_json::json!(null).to_string().as_str())
   1100             .unwrap_err()
   1101             .to_string()
   1102             .into_bytes()
   1103             .get(..err.len()),
   1104         Some(err.as_slice())
   1105     );
   1106     // Empty.
   1107     err = Error::missing_field("response").to_string().into_bytes();
   1108     assert_eq!(
   1109         serde_json::from_str::<RegistrationRelaxed>(serde_json::json!({}).to_string().as_str())
   1110             .unwrap_err()
   1111             .to_string()
   1112             .into_bytes()
   1113             .get(..err.len()),
   1114         Some(err.as_slice())
   1115     );
   1116     // Unknown field in `response`.
   1117     drop(
   1118         serde_json::from_str::<RegistrationRelaxed>(
   1119             serde_json::json!({
   1120                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1121                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1122                 "response": {
   1123                     "clientDataJSON": b64_cdata_json,
   1124                     "authenticatorData": b64_adata,
   1125                     "transports": [],
   1126                     "publicKey": b64_key,
   1127                     "publicKeyAlgorithm": -8i8,
   1128                     "attestationObject": b64_aobj,
   1129                     "foo": true,
   1130                 },
   1131                 "clientExtensionResults": {},
   1132                 "type": "public-key"
   1133             })
   1134             .to_string()
   1135             .as_str(),
   1136         )
   1137         .unwrap(),
   1138     );
   1139     // Duplicate field in `response`.
   1140     err = Error::duplicate_field("transports")
   1141         .to_string()
   1142         .into_bytes();
   1143     assert_eq!(
   1144         serde_json::from_str::<RegistrationRelaxed>(
   1145             format!(
   1146                 "{{
   1147                    \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   1148                    \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   1149                    \"response\": {{
   1150                        \"clientDataJSON\": \"{b64_cdata_json}\",
   1151                        \"authenticatorData\": \"{b64_adata}\",
   1152                        \"transports\": [],
   1153                        \"publicKey\": \"{b64_key}\",
   1154                        \"publicKeyAlgorithm\": -8,
   1155                        \"attestationObject\": \"{b64_aobj}\",
   1156                        \"transports\": []
   1157                    }},
   1158                    \"clientExtensionResults\": {{}},
   1159                    \"type\": \"public-key\"
   1160                  }}"
   1161             )
   1162             .as_str()
   1163         )
   1164         .unwrap_err()
   1165         .to_string()
   1166         .into_bytes()
   1167         .get(..err.len()),
   1168         Some(err.as_slice())
   1169     );
   1170     // Unknown field in `PublicKeyCredential`.
   1171     drop(
   1172         serde_json::from_str::<RegistrationRelaxed>(
   1173             serde_json::json!({
   1174                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1175                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1176                 "response": {
   1177                     "clientDataJSON": b64_cdata_json,
   1178                     "authenticatorData": b64_adata,
   1179                     "transports": [],
   1180                     "publicKey": b64_key,
   1181                     "publicKeyAlgorithm": -8i8,
   1182                     "attestationObject": b64_aobj
   1183                 },
   1184                 "clientExtensionResults": {},
   1185                 "type": "public-key",
   1186                 "foo": true,
   1187             })
   1188             .to_string()
   1189             .as_str(),
   1190         )
   1191         .unwrap(),
   1192     );
   1193     // Duplicate field in `PublicKeyCredential`.
   1194     err = Error::duplicate_field("id").to_string().into_bytes();
   1195     assert_eq!(
   1196         serde_json::from_str::<RegistrationRelaxed>(
   1197             format!(
   1198                 "{{
   1199                    \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   1200                    \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   1201                    \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   1202                    \"response\": {{
   1203                        \"clientDataJSON\": \"{b64_cdata_json}\",
   1204                        \"authenticatorData\": \"{b64_adata}\",
   1205                        \"transports\": [],
   1206                        \"publicKey\": \"{b64_key}\",
   1207                        \"publicKeyAlgorithm\": -8,
   1208                        \"attestationObject\": \"{b64_aobj}\"
   1209                    }},
   1210                    \"clientExtensionResults\": {{}},
   1211                    \"type\": \"public-key\"
   1212                  }}"
   1213             )
   1214             .as_str()
   1215         )
   1216         .unwrap_err()
   1217         .to_string()
   1218         .into_bytes()
   1219         .get(..err.len()),
   1220         Some(err.as_slice())
   1221     );
   1222     // Base case is correct.
   1223     assert!(
   1224         serde_json::from_str::<CustomRegistration>(
   1225             serde_json::json!({
   1226                 "attestationObject": b64_aobj,
   1227                 "authenticatorAttachment": "cross-platform",
   1228                 "clientDataJSON": b64_cdata_json,
   1229                 "clientExtensionResults": {},
   1230                 "transports": ["ble", "usb", "hybrid", "internal", "nfc", "smart-card"],
   1231                 "type": "public-key"
   1232             })
   1233             .to_string()
   1234             .as_str()
   1235         )
   1236         .is_ok_and(
   1237             |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
   1238                 && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
   1239                 && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
   1240                     == *Sha256::digest(c_data_json.as_bytes())
   1241                 && reg.0.response.transports.count() == 6
   1242                 && matches!(
   1243                     reg.0.authenticator_attachment,
   1244                     AuthenticatorAttachment::CrossPlatform
   1245                 )
   1246                 && reg.0.client_extension_results.cred_props.is_none()
   1247                 && reg.0.client_extension_results.prf.is_none()
   1248         )
   1249     );
   1250     // Missing `transports`.
   1251     err = Error::missing_field("transports").to_string().into_bytes();
   1252     assert_eq!(
   1253         serde_json::from_str::<CustomRegistration>(
   1254             serde_json::json!({
   1255                 "attestationObject": b64_aobj,
   1256                 "authenticatorAttachment": "cross-platform",
   1257                 "clientDataJSON": b64_cdata_json,
   1258                 "clientExtensionResults": {},
   1259                 "type": "public-key"
   1260             })
   1261             .to_string()
   1262             .as_str()
   1263         )
   1264         .unwrap_err()
   1265         .to_string()
   1266         .into_bytes()
   1267         .get(..err.len()),
   1268         Some(err.as_slice())
   1269     );
   1270     // Duplicate `transports` are allowed.
   1271     assert!(
   1272         serde_json::from_str::<CustomRegistration>(
   1273             serde_json::json!({
   1274                 "attestationObject": b64_aobj,
   1275                 "authenticatorAttachment": "cross-platform",
   1276                 "clientDataJSON": b64_cdata_json,
   1277                 "clientExtensionResults": {},
   1278                 "transports": ["usb", "usb"],
   1279                 "type": "public-key"
   1280             })
   1281             .to_string()
   1282             .as_str()
   1283         )
   1284         .is_ok_and(|reg| reg.0.response.transports.count() == 1)
   1285     );
   1286     // `null` `transports`.
   1287     err = Error::invalid_type(Unexpected::Other("null"), &"AuthTransports")
   1288         .to_string()
   1289         .into_bytes();
   1290     assert_eq!(
   1291         serde_json::from_str::<CustomRegistration>(
   1292             serde_json::json!({
   1293                 "clientDataJSON": b64_cdata_json,
   1294                 "transports": null,
   1295                 "attestationObject": b64_aobj,
   1296                 "clientExtensionResults": {},
   1297                 "type": "public-key"
   1298             })
   1299             .to_string()
   1300             .as_str()
   1301         )
   1302         .unwrap_err()
   1303         .to_string()
   1304         .into_bytes()
   1305         .get(..err.len()),
   1306         Some(err.as_slice())
   1307     );
   1308     // Unknown `transports`.
   1309     err = Error::invalid_value(
   1310         Unexpected::Str("Usb"),
   1311         &"'ble', 'cable', 'hybrid', 'internal', 'nfc', 'smart-card', or 'usb'",
   1312     )
   1313     .to_string()
   1314     .into_bytes();
   1315     assert_eq!(
   1316         serde_json::from_str::<CustomRegistration>(
   1317             serde_json::json!({
   1318                 "attestationObject": b64_aobj,
   1319                 "authenticatorAttachment": "cross-platform",
   1320                 "clientDataJSON": b64_cdata_json,
   1321                 "clientExtensionResults": {},
   1322                 "transports": ["Usb"],
   1323                 "type": "public-key"
   1324             })
   1325             .to_string()
   1326             .as_str()
   1327         )
   1328         .unwrap_err()
   1329         .to_string()
   1330         .into_bytes()
   1331         .get(..err.len()),
   1332         Some(err.as_slice())
   1333     );
   1334     // `null` `authenticatorAttachment`.
   1335     assert!(
   1336         serde_json::from_str::<CustomRegistration>(
   1337             serde_json::json!({
   1338                 "attestationObject": b64_aobj,
   1339                 "authenticatorAttachment": null,
   1340                 "clientDataJSON": b64_cdata_json,
   1341                 "clientExtensionResults": {},
   1342                 "transports": [],
   1343                 "type": "public-key"
   1344             })
   1345             .to_string()
   1346             .as_str()
   1347         )
   1348         .is_ok_and(|reg| matches!(
   1349             reg.0.authenticator_attachment,
   1350             AuthenticatorAttachment::None
   1351         ))
   1352     );
   1353     // Unknown `authenticatorAttachment`.
   1354     err = Error::invalid_value(
   1355         Unexpected::Str("Platform"),
   1356         &"'platform' or 'cross-platform'",
   1357     )
   1358     .to_string()
   1359     .into_bytes();
   1360     assert_eq!(
   1361         serde_json::from_str::<CustomRegistration>(
   1362             serde_json::json!({
   1363                 "attestationObject": b64_aobj,
   1364                 "authenticatorAttachment": "Platform",
   1365                 "clientDataJSON": b64_cdata_json,
   1366                 "clientExtensionResults": {},
   1367                 "transports": [],
   1368                 "type": "public-key"
   1369             })
   1370             .to_string()
   1371             .as_str()
   1372         )
   1373         .unwrap_err()
   1374         .to_string()
   1375         .into_bytes()
   1376         .get(..err.len()),
   1377         Some(err.as_slice())
   1378     );
   1379     // Missing `clientDataJSON`.
   1380     err = Error::missing_field("clientDataJSON")
   1381         .to_string()
   1382         .into_bytes();
   1383     assert_eq!(
   1384         serde_json::from_str::<CustomRegistration>(
   1385             serde_json::json!({
   1386                 "transports": [],
   1387                 "attestationObject": b64_aobj,
   1388                 "clientExtensionResults": {},
   1389                 "type": "public-key"
   1390             })
   1391             .to_string()
   1392             .as_str()
   1393         )
   1394         .unwrap_err()
   1395         .to_string()
   1396         .into_bytes()
   1397         .get(..err.len()),
   1398         Some(err.as_slice())
   1399     );
   1400     // `null` `clientDataJSON`.
   1401     err = Error::invalid_type(Unexpected::Other("null"), &"base64url-encoded data")
   1402         .to_string()
   1403         .into_bytes();
   1404     assert_eq!(
   1405         serde_json::from_str::<CustomRegistration>(
   1406             serde_json::json!({
   1407                 "clientDataJSON": null,
   1408                 "transports": [],
   1409                 "attestationObject": b64_aobj,
   1410             })
   1411             .to_string()
   1412             .as_str()
   1413         )
   1414         .unwrap_err()
   1415         .to_string()
   1416         .into_bytes()
   1417         .get(..err.len()),
   1418         Some(err.as_slice())
   1419     );
   1420     // Missing `attestationObject`.
   1421     err = Error::missing_field("attestationObject")
   1422         .to_string()
   1423         .into_bytes();
   1424     assert_eq!(
   1425         serde_json::from_str::<CustomRegistration>(
   1426             serde_json::json!({
   1427                 "clientDataJSON": b64_cdata_json,
   1428                 "transports": [],
   1429                 "clientExtensionResults": {},
   1430                 "type": "public-key"
   1431             })
   1432             .to_string()
   1433             .as_str()
   1434         )
   1435         .unwrap_err()
   1436         .to_string()
   1437         .into_bytes()
   1438         .get(..err.len()),
   1439         Some(err.as_slice())
   1440     );
   1441     // `null` `attestationObject`.
   1442     err = Error::invalid_type(
   1443         Unexpected::Other("null"),
   1444         &"base64url-encoded attestation object",
   1445     )
   1446     .to_string()
   1447     .into_bytes();
   1448     assert_eq!(
   1449         serde_json::from_str::<CustomRegistration>(
   1450             serde_json::json!({
   1451                 "clientDataJSON": b64_cdata_json,
   1452                 "transports": [],
   1453                 "attestationObject": null,
   1454                 "clientExtensionResults": {},
   1455                 "type": "public-key"
   1456             })
   1457             .to_string()
   1458             .as_str()
   1459         )
   1460         .unwrap_err()
   1461         .to_string()
   1462         .into_bytes()
   1463         .get(..err.len()),
   1464         Some(err.as_slice())
   1465     );
   1466     // Missing `clientExtensionResults`.
   1467     err = Error::missing_field("clientExtensionResults")
   1468         .to_string()
   1469         .into_bytes();
   1470     assert_eq!(
   1471         serde_json::from_str::<CustomRegistration>(
   1472             serde_json::json!({
   1473                 "clientDataJSON": b64_cdata_json,
   1474                 "transports": [],
   1475                 "attestationObject": b64_aobj,
   1476                 "type": "public-key"
   1477             })
   1478             .to_string()
   1479             .as_str()
   1480         )
   1481         .unwrap_err()
   1482         .to_string()
   1483         .into_bytes()
   1484         .get(..err.len()),
   1485         Some(err.as_slice())
   1486     );
   1487     // `null` `clientExtensionResults`.
   1488     err = Error::invalid_type(Unexpected::Other("null"), &"ClientExtensionsOutputs")
   1489         .to_string()
   1490         .into_bytes();
   1491     assert_eq!(
   1492         serde_json::from_str::<CustomRegistration>(
   1493             serde_json::json!({
   1494                 "clientDataJSON": b64_cdata_json,
   1495                 "transports": [],
   1496                 "attestationObject": b64_aobj,
   1497                 "clientExtensionResults": null,
   1498                 "type": "public-key"
   1499             })
   1500             .to_string()
   1501             .as_str()
   1502         )
   1503         .unwrap_err()
   1504         .to_string()
   1505         .into_bytes()
   1506         .get(..err.len()),
   1507         Some(err.as_slice())
   1508     );
   1509     // Missing `type`.
   1510     assert!(
   1511         serde_json::from_str::<CustomRegistration>(
   1512             serde_json::json!({
   1513                 "attestationObject": b64_aobj,
   1514                 "clientDataJSON": b64_cdata_json,
   1515                 "clientExtensionResults": {},
   1516                 "transports": []
   1517             })
   1518             .to_string()
   1519             .as_str()
   1520         )
   1521         .is_ok_and(|_| true)
   1522     );
   1523     // `null` `type`.
   1524     err = Error::invalid_type(Unexpected::Other("null"), &"public-key")
   1525         .to_string()
   1526         .into_bytes();
   1527     assert_eq!(
   1528         serde_json::from_str::<CustomRegistration>(
   1529             serde_json::json!({
   1530                 "attestationObject": b64_aobj,
   1531                 "clientDataJSON": b64_cdata_json,
   1532                 "clientExtensionResults": {},
   1533                 "transports": [],
   1534                 "type": null
   1535             })
   1536             .to_string()
   1537             .as_str()
   1538         )
   1539         .unwrap_err()
   1540         .to_string()
   1541         .into_bytes()
   1542         .get(..err.len()),
   1543         Some(err.as_slice())
   1544     );
   1545     // Not exactly `public-type` `type`.
   1546     err = Error::invalid_value(Unexpected::Str("Public-key"), &"public-key")
   1547         .to_string()
   1548         .into_bytes();
   1549     assert_eq!(
   1550         serde_json::from_str::<CustomRegistration>(
   1551             serde_json::json!({
   1552                 "clientDataJSON": b64_cdata_json,
   1553                 "transports": [],
   1554                 "attestationObject": b64_aobj,
   1555                 "clientExtensionResults": {},
   1556                 "type": "Public-key"
   1557             })
   1558             .to_string()
   1559             .as_str()
   1560         )
   1561         .unwrap_err()
   1562         .to_string()
   1563         .into_bytes()
   1564         .get(..err.len()),
   1565         Some(err.as_slice())
   1566     );
   1567     // `null`.
   1568     err = Error::invalid_type(Unexpected::Other("null"), &"CustomRegistration")
   1569         .to_string()
   1570         .into_bytes();
   1571     assert_eq!(
   1572         serde_json::from_str::<CustomRegistration>(serde_json::json!(null).to_string().as_str())
   1573             .unwrap_err()
   1574             .to_string()
   1575             .into_bytes()
   1576             .get(..err.len()),
   1577         Some(err.as_slice())
   1578     );
   1579     // Empty.
   1580     err = Error::missing_field("attestationObject")
   1581         .to_string()
   1582         .into_bytes();
   1583     assert_eq!(
   1584         serde_json::from_str::<CustomRegistration>(serde_json::json!({}).to_string().as_str())
   1585             .unwrap_err()
   1586             .to_string()
   1587             .into_bytes()
   1588             .get(..err.len()),
   1589         Some(err.as_slice())
   1590     );
   1591     // Unknown field.
   1592     err = Error::unknown_field(
   1593         "foo",
   1594         [
   1595             "attestationObject",
   1596             "authenticatorAttachment",
   1597             "clientDataJSON",
   1598             "clientExtensionResults",
   1599             "transports",
   1600             "type",
   1601         ]
   1602         .as_slice(),
   1603     )
   1604     .to_string()
   1605     .into_bytes();
   1606     assert_eq!(
   1607         serde_json::from_str::<CustomRegistration>(
   1608             serde_json::json!({
   1609                 "clientDataJSON": b64_cdata_json,
   1610                 "transports": [],
   1611                 "attestationObject": b64_aobj,
   1612                 "foo": true,
   1613                 "clientExtensionResults": {},
   1614                 "type": "public-key"
   1615             })
   1616             .to_string()
   1617             .as_str()
   1618         )
   1619         .unwrap_err()
   1620         .to_string()
   1621         .into_bytes()
   1622         .get(..err.len()),
   1623         Some(err.as_slice())
   1624     );
   1625     // Duplicate field.
   1626     err = Error::duplicate_field("transports")
   1627         .to_string()
   1628         .into_bytes();
   1629     assert_eq!(
   1630         serde_json::from_str::<CustomRegistration>(
   1631             format!(
   1632                 "{{
   1633                    \"clientDataJSON\": \"{b64_cdata_json}\",
   1634                    \"transports\": [],
   1635                    \"attestationObject\": \"{b64_aobj}\",
   1636                    \"transports\": []
   1637                    \"clientExtensionResults\": {{}},
   1638                    \"type\": \"public-key\"
   1639                  }}"
   1640             )
   1641             .as_str()
   1642         )
   1643         .unwrap_err()
   1644         .to_string()
   1645         .into_bytes()
   1646         .get(..err.len()),
   1647         Some(err.as_slice())
   1648     );
   1649 }
   1650 #[expect(clippy::unwrap_used, reason = "OK in tests")]
   1651 #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
   1652 #[expect(clippy::too_many_lines, reason = "a lot to test")]
   1653 #[test]
   1654 fn client_extensions() {
   1655     let c_data_json = serde_json::json!({}).to_string();
   1656     let att_obj: [u8; 143] = [
   1657         cbor::MAP_3,
   1658         cbor::TEXT_3,
   1659         b'f',
   1660         b'm',
   1661         b't',
   1662         cbor::TEXT_4,
   1663         b'n',
   1664         b'o',
   1665         b'n',
   1666         b'e',
   1667         cbor::TEXT_7,
   1668         b'a',
   1669         b't',
   1670         b't',
   1671         b'S',
   1672         b't',
   1673         b'm',
   1674         b't',
   1675         cbor::MAP_0,
   1676         cbor::TEXT_8,
   1677         b'a',
   1678         b'u',
   1679         b't',
   1680         b'h',
   1681         b'D',
   1682         b'a',
   1683         b't',
   1684         b'a',
   1685         cbor::BYTES_INFO_24,
   1686         113,
   1687         // `rpIdHash`.
   1688         0,
   1689         0,
   1690         0,
   1691         0,
   1692         0,
   1693         0,
   1694         0,
   1695         0,
   1696         0,
   1697         0,
   1698         0,
   1699         0,
   1700         0,
   1701         0,
   1702         0,
   1703         0,
   1704         0,
   1705         0,
   1706         0,
   1707         0,
   1708         0,
   1709         0,
   1710         0,
   1711         0,
   1712         0,
   1713         0,
   1714         0,
   1715         0,
   1716         0,
   1717         0,
   1718         0,
   1719         0,
   1720         // `flags`.
   1721         0b0100_0101,
   1722         // `signCount`.
   1723         0,
   1724         0,
   1725         0,
   1726         0,
   1727         // `aaguid`.
   1728         0,
   1729         0,
   1730         0,
   1731         0,
   1732         0,
   1733         0,
   1734         0,
   1735         0,
   1736         0,
   1737         0,
   1738         0,
   1739         0,
   1740         0,
   1741         0,
   1742         0,
   1743         0,
   1744         // `credentialIdLength`.
   1745         0,
   1746         16,
   1747         // `credentialId`.
   1748         0,
   1749         0,
   1750         0,
   1751         0,
   1752         0,
   1753         0,
   1754         0,
   1755         0,
   1756         0,
   1757         0,
   1758         0,
   1759         0,
   1760         0,
   1761         0,
   1762         0,
   1763         0,
   1764         // Ed25519 COSE key.
   1765         cbor::MAP_4,
   1766         KTY,
   1767         OKP,
   1768         ALG,
   1769         EDDSA,
   1770         // `crv`.
   1771         cbor::NEG_ONE,
   1772         // `Ed25519`.
   1773         cbor::SIX,
   1774         // `x`.
   1775         cbor::NEG_TWO,
   1776         cbor::BYTES_INFO_24,
   1777         32,
   1778         // Compressed y-coordinate.
   1779         1,
   1780         1,
   1781         1,
   1782         1,
   1783         1,
   1784         1,
   1785         1,
   1786         1,
   1787         1,
   1788         1,
   1789         1,
   1790         1,
   1791         1,
   1792         1,
   1793         1,
   1794         1,
   1795         1,
   1796         1,
   1797         1,
   1798         1,
   1799         1,
   1800         1,
   1801         1,
   1802         1,
   1803         1,
   1804         1,
   1805         1,
   1806         1,
   1807         1,
   1808         1,
   1809         1,
   1810         1,
   1811     ];
   1812     let pub_key = VerifyingKey::from_bytes(&[1; 32])
   1813         .unwrap()
   1814         .to_public_key_der()
   1815         .unwrap();
   1816     let att_obj_len = att_obj.len();
   1817     let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
   1818     let auth_data_start = att_obj_len - 113;
   1819     let b64_adata = base64url_nopad::encode(&att_obj[auth_data_start..]);
   1820     let b64_key = base64url_nopad::encode(pub_key.as_bytes());
   1821     let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
   1822     // Base case is valid.
   1823     assert!(
   1824         serde_json::from_str::<RegistrationRelaxed>(
   1825             serde_json::json!({
   1826                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1827                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1828                 "response": {
   1829                     "clientDataJSON": b64_cdata_json,
   1830                     "authenticatorData": b64_adata,
   1831                     "transports": [],
   1832                     "publicKey": b64_key,
   1833                     "publicKeyAlgorithm": -8i8,
   1834                     "attestationObject": b64_aobj,
   1835                 },
   1836                 "clientExtensionResults": {},
   1837                 "type": "public-key"
   1838             })
   1839             .to_string()
   1840             .as_str()
   1841         )
   1842         .is_ok_and(
   1843             |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
   1844                 && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
   1845                 && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
   1846                     == *Sha256::digest(c_data_json.as_bytes())
   1847                 && reg.0.response.transports.is_empty()
   1848                 && matches!(
   1849                     reg.0.authenticator_attachment,
   1850                     AuthenticatorAttachment::None
   1851                 )
   1852                 && reg.0.client_extension_results.cred_props.is_none()
   1853                 && reg.0.client_extension_results.prf.is_none()
   1854         )
   1855     );
   1856     // `null` `credProps`.
   1857     assert!(
   1858         serde_json::from_str::<RegistrationRelaxed>(
   1859             serde_json::json!({
   1860                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1861                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1862                 "response": {
   1863                     "clientDataJSON": b64_cdata_json,
   1864                     "authenticatorData": b64_adata,
   1865                     "transports": [],
   1866                     "publicKey": b64_key,
   1867                     "publicKeyAlgorithm": -8i8,
   1868                     "attestationObject": b64_aobj,
   1869                 },
   1870                 "clientExtensionResults": {
   1871                     "credProps": null
   1872                 },
   1873                 "type": "public-key"
   1874             })
   1875             .to_string()
   1876             .as_str()
   1877         )
   1878         .is_ok_and(|reg| reg.0.client_extension_results.cred_props.is_none()
   1879             && reg.0.client_extension_results.prf.is_none())
   1880     );
   1881     // `null` `prf`.
   1882     assert!(
   1883         serde_json::from_str::<RegistrationRelaxed>(
   1884             serde_json::json!({
   1885                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1886                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1887                 "response": {
   1888                     "clientDataJSON": b64_cdata_json,
   1889                     "authenticatorData": b64_adata,
   1890                     "transports": [],
   1891                     "publicKey": b64_key,
   1892                     "publicKeyAlgorithm": -8i8,
   1893                     "attestationObject": b64_aobj,
   1894                 },
   1895                 "clientExtensionResults": {
   1896                     "prf": null
   1897                 },
   1898                 "type": "public-key"
   1899             })
   1900             .to_string()
   1901             .as_str()
   1902         )
   1903         .is_ok_and(|reg| reg.0.client_extension_results.cred_props.is_none()
   1904             && reg.0.client_extension_results.prf.is_none())
   1905     );
   1906     // Unknown `clientExtensionResults`.
   1907     drop(
   1908         serde_json::from_str::<RegistrationRelaxed>(
   1909             serde_json::json!({
   1910                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1911                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1912                 "response": {
   1913                     "clientDataJSON": b64_cdata_json,
   1914                     "authenticatorData": b64_adata,
   1915                     "transports": [],
   1916                     "publicKey": b64_key,
   1917                     "publicKeyAlgorithm": -8i8,
   1918                     "attestationObject": b64_aobj,
   1919                 },
   1920                 "clientExtensionResults": {
   1921                     "CredProps": {
   1922                         "rk": true
   1923                     }
   1924                 },
   1925                 "type": "public-key"
   1926             })
   1927             .to_string()
   1928             .as_str(),
   1929         )
   1930         .unwrap(),
   1931     );
   1932     // Duplicate field.
   1933     let mut err = Error::duplicate_field("credProps").to_string().into_bytes();
   1934     assert_eq!(
   1935         serde_json::from_str::<RegistrationRelaxed>(
   1936             format!(
   1937                 "{{
   1938                    \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   1939                    \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   1940                    \"response\": {{
   1941                        \"clientDataJSON\": \"{b64_cdata_json}\",
   1942                        \"authenticatorData\": \"{b64_adata}\",
   1943                        \"transports\": [],
   1944                        \"publicKey\": \"{b64_key}\",
   1945                        \"publicKeyAlgorithm\": -8,
   1946                        \"attestationObject\": \"{b64_aobj}\"
   1947                    }},
   1948                    \"clientExtensionResults\": {{
   1949                        \"credProps\": null,
   1950                        \"credProps\": null
   1951                    }},
   1952                    \"type\": \"public-key\"
   1953                  }}"
   1954             )
   1955             .as_str()
   1956         )
   1957         .unwrap_err()
   1958         .to_string()
   1959         .into_bytes()
   1960         .get(..err.len()),
   1961         Some(err.as_slice())
   1962     );
   1963     // `null` `rk`.
   1964     assert!(
   1965         serde_json::from_str::<RegistrationRelaxed>(
   1966             serde_json::json!({
   1967                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1968                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   1969                 "response": {
   1970                     "clientDataJSON": b64_cdata_json,
   1971                     "authenticatorData": b64_adata,
   1972                     "transports": [],
   1973                     "publicKey": b64_key,
   1974                     "publicKeyAlgorithm": -8i8,
   1975                     "attestationObject": b64_aobj,
   1976                 },
   1977                 "clientExtensionResults": {
   1978                     "credProps": {
   1979                         "rk": null
   1980                     }
   1981                 },
   1982                 "type": "public-key"
   1983             })
   1984             .to_string()
   1985             .as_str()
   1986         )
   1987         .is_ok_and(|reg| reg
   1988             .0
   1989             .client_extension_results
   1990             .cred_props
   1991             .is_some_and(|props| props.rk.is_none())
   1992             && reg.0.client_extension_results.prf.is_none())
   1993     );
   1994     // Missing `rk`.
   1995     assert!(
   1996         serde_json::from_str::<RegistrationRelaxed>(
   1997             serde_json::json!({
   1998                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   1999                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2000                 "response": {
   2001                     "clientDataJSON": b64_cdata_json,
   2002                     "authenticatorData": b64_adata,
   2003                     "transports": [],
   2004                     "publicKey": b64_key,
   2005                     "publicKeyAlgorithm": -8i8,
   2006                     "attestationObject": b64_aobj,
   2007                 },
   2008                 "clientExtensionResults": {
   2009                     "credProps": {}
   2010                 },
   2011                 "type": "public-key"
   2012             })
   2013             .to_string()
   2014             .as_str()
   2015         )
   2016         .is_ok_and(|reg| reg
   2017             .0
   2018             .client_extension_results
   2019             .cred_props
   2020             .is_some_and(|props| props.rk.is_none())
   2021             && reg.0.client_extension_results.prf.is_none())
   2022     );
   2023     // `true` rk`.
   2024     assert!(
   2025         serde_json::from_str::<RegistrationRelaxed>(
   2026             serde_json::json!({
   2027                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2028                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2029                 "response": {
   2030                     "clientDataJSON": b64_cdata_json,
   2031                     "authenticatorData": b64_adata,
   2032                     "transports": [],
   2033                     "publicKey": b64_key,
   2034                     "publicKeyAlgorithm": -8i8,
   2035                     "attestationObject": b64_aobj,
   2036                 },
   2037                 "clientExtensionResults": {
   2038                     "credProps": {
   2039                         "rk": true
   2040                     }
   2041                 },
   2042                 "type": "public-key"
   2043             })
   2044             .to_string()
   2045             .as_str()
   2046         )
   2047         .is_ok_and(|reg| reg
   2048             .0
   2049             .client_extension_results
   2050             .cred_props
   2051             .is_some_and(|props| props.rk.unwrap_or_default())
   2052             && reg.0.client_extension_results.prf.is_none())
   2053     );
   2054     // `false` rk`.
   2055     assert!(
   2056         serde_json::from_str::<RegistrationRelaxed>(
   2057             serde_json::json!({
   2058                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2059                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2060                 "response": {
   2061                     "clientDataJSON": b64_cdata_json,
   2062                     "authenticatorData": b64_adata,
   2063                     "transports": [],
   2064                     "publicKey": b64_key,
   2065                     "publicKeyAlgorithm": -8i8,
   2066                     "attestationObject": b64_aobj,
   2067                 },
   2068                 "clientExtensionResults": {
   2069                     "credProps": {
   2070                         "rk": false
   2071                     }
   2072                 },
   2073                 "type": "public-key"
   2074             })
   2075             .to_string()
   2076             .as_str()
   2077         )
   2078         .is_ok_and(|reg| reg
   2079             .0
   2080             .client_extension_results
   2081             .cred_props
   2082             .is_some_and(|props| props.rk.is_some_and(|rk| !rk))
   2083             && reg.0.client_extension_results.prf.is_none())
   2084     );
   2085     // Invalid `rk`.
   2086     err = Error::invalid_type(Unexpected::Unsigned(3), &"a boolean")
   2087         .to_string()
   2088         .into_bytes();
   2089     assert_eq!(
   2090         serde_json::from_str::<RegistrationRelaxed>(
   2091             serde_json::json!({
   2092                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2093                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2094                 "response": {
   2095                     "clientDataJSON": b64_cdata_json,
   2096                     "authenticatorData": b64_adata,
   2097                     "transports": [],
   2098                     "publicKey": b64_key,
   2099                     "publicKeyAlgorithm": -8i8,
   2100                     "attestationObject": b64_aobj,
   2101                 },
   2102                 "clientExtensionResults": {
   2103                     "credProps": {
   2104                         "rk": 3u8
   2105                     }
   2106                 },
   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     // Unknown `credProps` field.
   2119     drop(
   2120         serde_json::from_str::<RegistrationRelaxed>(
   2121             serde_json::json!({
   2122                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   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                     "credProps": {
   2134                         "Rk": true,
   2135                     }
   2136                 },
   2137                 "type": "public-key"
   2138             })
   2139             .to_string()
   2140             .as_str(),
   2141         )
   2142         .unwrap(),
   2143     );
   2144     // Duplicate field in `credProps`.
   2145     err = Error::duplicate_field("rk").to_string().into_bytes();
   2146     assert_eq!(
   2147         serde_json::from_str::<RegistrationRelaxed>(
   2148             format!(
   2149                 "{{
   2150                    \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   2151                    \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   2152                    \"response\": {{
   2153                        \"clientDataJSON\": \"{b64_cdata_json}\",
   2154                        \"authenticatorData\": \"{b64_adata}\",
   2155                        \"transports\": [],
   2156                        \"publicKey\": \"{b64_key}\",
   2157                        \"publicKeyAlgorithm\": -8,
   2158                        \"attestationObject\": \"{b64_aobj}\"
   2159                    }},
   2160                    \"clientExtensionResults\": {{
   2161                        \"credProps\": {{
   2162                            \"rk\": true,
   2163                            \"rk\": true
   2164                        }}
   2165                    }},
   2166                    \"type\": \"public-key\"
   2167                  }}"
   2168             )
   2169             .as_str()
   2170         )
   2171         .unwrap_err()
   2172         .to_string()
   2173         .into_bytes()
   2174         .get(..err.len()),
   2175         Some(err.as_slice())
   2176     );
   2177     // `null` `enabled`.
   2178     err = Error::invalid_type(Unexpected::Other("null"), &"a boolean")
   2179         .to_string()
   2180         .into_bytes();
   2181     assert_eq!(
   2182         serde_json::from_str::<RegistrationRelaxed>(
   2183             serde_json::json!({
   2184                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2185                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2186                 "response": {
   2187                     "clientDataJSON": b64_cdata_json,
   2188                     "authenticatorData": b64_adata,
   2189                     "transports": [],
   2190                     "publicKey": b64_key,
   2191                     "publicKeyAlgorithm": -8i8,
   2192                     "attestationObject": b64_aobj,
   2193                 },
   2194                 "clientExtensionResults": {
   2195                     "prf": {
   2196                         "enabled": null
   2197                     }
   2198                 },
   2199                 "type": "public-key"
   2200             })
   2201             .to_string()
   2202             .as_str()
   2203         )
   2204         .unwrap_err()
   2205         .to_string()
   2206         .into_bytes()
   2207         .get(..err.len()),
   2208         Some(err.as_slice())
   2209     );
   2210     // Missing `enabled`.
   2211     err = Error::missing_field("enabled").to_string().into_bytes();
   2212     assert_eq!(
   2213         serde_json::from_str::<RegistrationRelaxed>(
   2214             serde_json::json!({
   2215                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2216                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2217                 "response": {
   2218                     "clientDataJSON": b64_cdata_json,
   2219                     "authenticatorData": b64_adata,
   2220                     "transports": [],
   2221                     "publicKey": b64_key,
   2222                     "publicKeyAlgorithm": -8i8,
   2223                     "attestationObject": b64_aobj,
   2224                 },
   2225                 "clientExtensionResults": {
   2226                     "prf": {}
   2227                 },
   2228                 "type": "public-key"
   2229             })
   2230             .to_string()
   2231             .as_str()
   2232         )
   2233         .unwrap_err()
   2234         .to_string()
   2235         .into_bytes()
   2236         .get(..err.len()),
   2237         Some(err.as_slice())
   2238     );
   2239     // `true` `enabled`.
   2240     assert!(
   2241         serde_json::from_str::<RegistrationRelaxed>(
   2242             serde_json::json!({
   2243                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2244                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2245                 "response": {
   2246                     "clientDataJSON": b64_cdata_json,
   2247                     "authenticatorData": b64_adata,
   2248                     "transports": [],
   2249                     "publicKey": b64_key,
   2250                     "publicKeyAlgorithm": -8i8,
   2251                     "attestationObject": b64_aobj,
   2252                 },
   2253                 "clientExtensionResults": {
   2254                     "prf": {
   2255                         "enabled": true
   2256                     }
   2257                 },
   2258                 "type": "public-key"
   2259             })
   2260             .to_string()
   2261             .as_str()
   2262         )
   2263         .is_ok_and(|reg| reg.0.client_extension_results.cred_props.is_none()
   2264             && reg
   2265                 .0
   2266                 .client_extension_results
   2267                 .prf
   2268                 .is_some_and(|prf| prf.enabled))
   2269     );
   2270     // `false` `enabled`.
   2271     assert!(
   2272         serde_json::from_str::<RegistrationRelaxed>(
   2273             serde_json::json!({
   2274                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2275                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2276                 "response": {
   2277                     "clientDataJSON": b64_cdata_json,
   2278                     "authenticatorData": b64_adata,
   2279                     "transports": [],
   2280                     "publicKey": b64_key,
   2281                     "publicKeyAlgorithm": -8i8,
   2282                     "attestationObject": b64_aobj,
   2283                 },
   2284                 "clientExtensionResults": {
   2285                     "prf": {
   2286                         "enabled": false,
   2287                     }
   2288                 },
   2289                 "type": "public-key"
   2290             })
   2291             .to_string()
   2292             .as_str()
   2293         )
   2294         .is_ok_and(|reg| reg.0.client_extension_results.cred_props.is_none()
   2295             && reg
   2296                 .0
   2297                 .client_extension_results
   2298                 .prf
   2299                 .is_some_and(|prf| !prf.enabled))
   2300     );
   2301     // Invalid `enabled`.
   2302     err = Error::invalid_type(Unexpected::Unsigned(3), &"a boolean")
   2303         .to_string()
   2304         .into_bytes();
   2305     assert_eq!(
   2306         serde_json::from_str::<RegistrationRelaxed>(
   2307             serde_json::json!({
   2308                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2309                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2310                 "response": {
   2311                     "clientDataJSON": b64_cdata_json,
   2312                     "authenticatorData": b64_adata,
   2313                     "transports": [],
   2314                     "publicKey": b64_key,
   2315                     "publicKeyAlgorithm": -8i8,
   2316                     "attestationObject": b64_aobj,
   2317                 },
   2318                 "clientExtensionResults": {
   2319                     "prf": {
   2320                         "enabled": 3u8
   2321                     }
   2322                 },
   2323                 "type": "public-key"
   2324             })
   2325             .to_string()
   2326             .as_str()
   2327         )
   2328         .unwrap_err()
   2329         .to_string()
   2330         .into_bytes()
   2331         .get(..err.len()),
   2332         Some(err.as_slice())
   2333     );
   2334     // `null` `results` with `enabled` `true`.
   2335     assert!(
   2336         serde_json::from_str::<RegistrationRelaxed>(
   2337             serde_json::json!({
   2338                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2339                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2340                 "response": {
   2341                     "clientDataJSON": b64_cdata_json,
   2342                     "authenticatorData": b64_adata,
   2343                     "transports": [],
   2344                     "publicKey": b64_key,
   2345                     "publicKeyAlgorithm": -8i8,
   2346                     "attestationObject": b64_aobj,
   2347                 },
   2348                 "clientExtensionResults": {
   2349                     "prf": {
   2350                         "enabled": true,
   2351                         "results": null,
   2352                     }
   2353                 },
   2354                 "type": "public-key"
   2355             })
   2356             .to_string()
   2357             .as_str()
   2358         )
   2359         .is_ok_and(|reg| reg.0.client_extension_results.cred_props.is_none()
   2360             && reg
   2361                 .0
   2362                 .client_extension_results
   2363                 .prf
   2364                 .is_some_and(|prf| prf.enabled))
   2365     );
   2366     // `null` `results` with `enabled` `false`.
   2367     err = Error::custom(
   2368         "prf must not have 'results', including a null 'results', if 'enabled' is false",
   2369     )
   2370     .to_string()
   2371     .into_bytes();
   2372     assert_eq!(
   2373         serde_json::from_str::<RegistrationRelaxed>(
   2374             serde_json::json!({
   2375                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2376                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2377                 "response": {
   2378                     "clientDataJSON": b64_cdata_json,
   2379                     "authenticatorData": b64_adata,
   2380                     "transports": [],
   2381                     "publicKey": b64_key,
   2382                     "publicKeyAlgorithm": -8i8,
   2383                     "attestationObject": b64_aobj,
   2384                 },
   2385                 "clientExtensionResults": {
   2386                     "prf": {
   2387                         "enabled": false,
   2388                         "results": null
   2389                     }
   2390                 },
   2391                 "type": "public-key"
   2392             })
   2393             .to_string()
   2394             .as_str()
   2395         )
   2396         .unwrap_err()
   2397         .to_string()
   2398         .into_bytes()
   2399         .get(..err.len()),
   2400         Some(err.as_slice())
   2401     );
   2402     // Duplicate field in `prf`.
   2403     err = Error::duplicate_field("enabled").to_string().into_bytes();
   2404     assert_eq!(
   2405         serde_json::from_str::<RegistrationRelaxed>(
   2406             format!(
   2407                 "{{
   2408                    \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   2409                    \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   2410                    \"response\": {{
   2411                        \"clientDataJSON\": \"{b64_cdata_json}\",
   2412                        \"authenticatorData\": \"{b64_adata}\",
   2413                        \"transports\": [],
   2414                        \"publicKey\": \"{b64_key}\",
   2415                        \"publicKeyAlgorithm\": -8,
   2416                        \"attestationObject\": \"{b64_aobj}\"
   2417                    }},
   2418                    \"clientExtensionResults\": {{
   2419                        \"prf\": {{
   2420                            \"enabled\": true,
   2421                            \"enabled\": true
   2422                        }}
   2423                    }},
   2424                    \"type\": \"public-key\"
   2425                  }}"
   2426             )
   2427             .as_str()
   2428         )
   2429         .unwrap_err()
   2430         .to_string()
   2431         .into_bytes()
   2432         .get(..err.len()),
   2433         Some(err.as_slice())
   2434     );
   2435     // Missing `first`.
   2436     drop(
   2437         serde_json::from_str::<RegistrationRelaxed>(
   2438             serde_json::json!({
   2439                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2440                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2441                 "response": {
   2442                     "clientDataJSON": b64_cdata_json,
   2443                     "authenticatorData": b64_adata,
   2444                     "transports": [],
   2445                     "publicKey": b64_key,
   2446                     "publicKeyAlgorithm": -8i8,
   2447                     "attestationObject": b64_aobj,
   2448                 },
   2449                 "clientExtensionResults": {
   2450                     "prf": {
   2451                         "enabled": true,
   2452                         "results": {},
   2453                     }
   2454                 },
   2455                 "type": "public-key"
   2456             })
   2457             .to_string()
   2458             .as_str(),
   2459         )
   2460         .unwrap(),
   2461     );
   2462     // `null` `first`.
   2463     assert!(
   2464         serde_json::from_str::<RegistrationRelaxed>(
   2465             serde_json::json!({
   2466                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2467                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2468                 "response": {
   2469                     "clientDataJSON": b64_cdata_json,
   2470                     "authenticatorData": b64_adata,
   2471                     "transports": [],
   2472                     "publicKey": b64_key,
   2473                     "publicKeyAlgorithm": -8i8,
   2474                     "attestationObject": b64_aobj,
   2475                 },
   2476                 "clientExtensionResults": {
   2477                     "prf": {
   2478                         "enabled": true,
   2479                         "results": {
   2480                             "first": null
   2481                         },
   2482                     }
   2483                 },
   2484                 "type": "public-key"
   2485             })
   2486             .to_string()
   2487             .as_str()
   2488         )
   2489         .is_ok_and(|reg| reg.0.client_extension_results.cred_props.is_none()
   2490             && reg
   2491                 .0
   2492                 .client_extension_results
   2493                 .prf
   2494                 .is_some_and(|prf| prf.enabled))
   2495     );
   2496     // `null` `second`.
   2497     assert!(
   2498         serde_json::from_str::<RegistrationRelaxed>(
   2499             serde_json::json!({
   2500                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2501                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2502                 "response": {
   2503                     "clientDataJSON": b64_cdata_json,
   2504                     "authenticatorData": b64_adata,
   2505                     "transports": [],
   2506                     "publicKey": b64_key,
   2507                     "publicKeyAlgorithm": -8i8,
   2508                     "attestationObject": b64_aobj,
   2509                 },
   2510                 "clientExtensionResults": {
   2511                     "prf": {
   2512                         "enabled": true,
   2513                         "results": {
   2514                             "first": null,
   2515                             "second": null
   2516                         },
   2517                     }
   2518                 },
   2519                 "type": "public-key"
   2520             })
   2521             .to_string()
   2522             .as_str()
   2523         )
   2524         .is_ok_and(|reg| reg.0.client_extension_results.cred_props.is_none()
   2525             && reg
   2526                 .0
   2527                 .client_extension_results
   2528                 .prf
   2529                 .is_some_and(|prf| prf.enabled))
   2530     );
   2531     // Non-`null` `first`.
   2532     err = Error::invalid_type(Unexpected::Option, &"null")
   2533         .to_string()
   2534         .into_bytes();
   2535     assert_eq!(
   2536         serde_json::from_str::<RegistrationRelaxed>(
   2537             serde_json::json!({
   2538                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2539                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2540                 "response": {
   2541                     "clientDataJSON": b64_cdata_json,
   2542                     "authenticatorData": b64_adata,
   2543                     "transports": [],
   2544                     "publicKey": b64_key,
   2545                     "publicKeyAlgorithm": -8i8,
   2546                     "attestationObject": b64_aobj,
   2547                 },
   2548                 "clientExtensionResults": {
   2549                     "prf": {
   2550                         "enabled": true,
   2551                         "results": {
   2552                             "first": ""
   2553                         },
   2554                     }
   2555                 },
   2556                 "type": "public-key"
   2557             })
   2558             .to_string()
   2559             .as_str()
   2560         )
   2561         .unwrap_err()
   2562         .to_string()
   2563         .into_bytes()
   2564         .get(..err.len()),
   2565         Some(err.as_slice())
   2566     );
   2567     // Non-`null` `second`.
   2568     err = Error::invalid_type(Unexpected::Option, &"null")
   2569         .to_string()
   2570         .into_bytes();
   2571     assert_eq!(
   2572         serde_json::from_str::<RegistrationRelaxed>(
   2573             serde_json::json!({
   2574                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2575                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2576                 "response": {
   2577                     "clientDataJSON": b64_cdata_json,
   2578                     "authenticatorData": b64_adata,
   2579                     "transports": [],
   2580                     "publicKey": b64_key,
   2581                     "publicKeyAlgorithm": -8i8,
   2582                     "attestationObject": b64_aobj,
   2583                 },
   2584                 "clientExtensionResults": {
   2585                     "prf": {
   2586                         "enabled": true,
   2587                         "results": {
   2588                             "first": null,
   2589                             "second": ""
   2590                         },
   2591                     }
   2592                 },
   2593                 "type": "public-key"
   2594             })
   2595             .to_string()
   2596             .as_str()
   2597         )
   2598         .unwrap_err()
   2599         .to_string()
   2600         .into_bytes()
   2601         .get(..err.len()),
   2602         Some(err.as_slice())
   2603     );
   2604     // Unknown `prf` field.
   2605     drop(
   2606         serde_json::from_str::<RegistrationRelaxed>(
   2607             serde_json::json!({
   2608                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2609                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2610                 "response": {
   2611                     "clientDataJSON": b64_cdata_json,
   2612                     "authenticatorData": b64_adata,
   2613                     "transports": [],
   2614                     "publicKey": b64_key,
   2615                     "publicKeyAlgorithm": -8i8,
   2616                     "attestationObject": b64_aobj,
   2617                 },
   2618                 "clientExtensionResults": {
   2619                     "prf": {
   2620                         "enabled": true,
   2621                         "Results": null
   2622                     }
   2623                 },
   2624                 "type": "public-key"
   2625             })
   2626             .to_string()
   2627             .as_str(),
   2628         )
   2629         .unwrap(),
   2630     );
   2631     // Unknown `results` field.
   2632     drop(
   2633         serde_json::from_str::<RegistrationRelaxed>(
   2634             serde_json::json!({
   2635                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   2636                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   2637                 "response": {
   2638                     "clientDataJSON": b64_cdata_json,
   2639                     "authenticatorData": b64_adata,
   2640                     "transports": [],
   2641                     "publicKey": b64_key,
   2642                     "publicKeyAlgorithm": -8i8,
   2643                     "attestationObject": b64_aobj,
   2644                 },
   2645                 "clientExtensionResults": {
   2646                     "prf": {
   2647                         "enabled": true,
   2648                         "results": {
   2649                             "first": null,
   2650                             "Second": null
   2651                         }
   2652                     }
   2653                 },
   2654                 "type": "public-key"
   2655             })
   2656             .to_string()
   2657             .as_str(),
   2658         )
   2659         .unwrap(),
   2660     );
   2661     // Duplicate field in `results`.
   2662     err = Error::duplicate_field("first").to_string().into_bytes();
   2663     assert_eq!(
   2664         serde_json::from_str::<RegistrationRelaxed>(
   2665             format!(
   2666                 "{{
   2667                    \"id\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   2668                    \"rawId\": \"AAAAAAAAAAAAAAAAAAAAAA\",
   2669                    \"response\": {{
   2670                        \"clientDataJSON\": \"{b64_cdata_json}\",
   2671                        \"authenticatorData\": \"{b64_adata}\",
   2672                        \"transports\": [],
   2673                        \"publicKey\": \"{b64_key}\",
   2674                        \"publicKeyAlgorithm\": -8,
   2675                        \"attestationObject\": \"{b64_aobj}\"
   2676                    }},
   2677                    \"clientExtensionResults\": {{
   2678                        \"prf\": {{
   2679                            \"enabled\": true,
   2680                            \"results\": {{
   2681                                \"first\": null,
   2682                                \"first\": null
   2683                            }}
   2684                        }}
   2685                    }},
   2686                    \"type\": \"public-key\"
   2687                  }}"
   2688             )
   2689             .as_str()
   2690         )
   2691         .unwrap_err()
   2692         .to_string()
   2693         .into_bytes()
   2694         .get(..err.len()),
   2695         Some(err.as_slice())
   2696     );
   2697 }
   2698 #[expect(
   2699     clippy::assertions_on_result_states,
   2700     clippy::unwrap_used,
   2701     reason = "OK in tests"
   2702 )]
   2703 #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
   2704 #[expect(clippy::too_many_lines, reason = "a lot to test")]
   2705 #[test]
   2706 fn mldsa87_registration_deserialize_data_mismatch() {
   2707     let c_data_json = serde_json::json!({}).to_string();
   2708     let att_obj: [u8; 2704] = [
   2709         cbor::MAP_3,
   2710         cbor::TEXT_3,
   2711         b'f',
   2712         b'm',
   2713         b't',
   2714         cbor::TEXT_4,
   2715         b'n',
   2716         b'o',
   2717         b'n',
   2718         b'e',
   2719         cbor::TEXT_7,
   2720         b'a',
   2721         b't',
   2722         b't',
   2723         b'S',
   2724         b't',
   2725         b'm',
   2726         b't',
   2727         cbor::MAP_0,
   2728         cbor::TEXT_8,
   2729         b'a',
   2730         b'u',
   2731         b't',
   2732         b'h',
   2733         b'D',
   2734         b'a',
   2735         b't',
   2736         b'a',
   2737         cbor::BYTES_INFO_25,
   2738         10,
   2739         113,
   2740         // `rpIdHash`.
   2741         0,
   2742         0,
   2743         0,
   2744         0,
   2745         0,
   2746         0,
   2747         0,
   2748         0,
   2749         0,
   2750         0,
   2751         0,
   2752         0,
   2753         0,
   2754         0,
   2755         0,
   2756         0,
   2757         0,
   2758         0,
   2759         0,
   2760         0,
   2761         0,
   2762         0,
   2763         0,
   2764         0,
   2765         0,
   2766         0,
   2767         0,
   2768         0,
   2769         0,
   2770         0,
   2771         0,
   2772         0,
   2773         // `flags`.
   2774         0b0100_0101,
   2775         // `signCount`.
   2776         0,
   2777         0,
   2778         0,
   2779         0,
   2780         // `aaguid`.
   2781         0,
   2782         0,
   2783         0,
   2784         0,
   2785         0,
   2786         0,
   2787         0,
   2788         0,
   2789         0,
   2790         0,
   2791         0,
   2792         0,
   2793         0,
   2794         0,
   2795         0,
   2796         0,
   2797         // `credentialIdLength`.
   2798         0,
   2799         16,
   2800         // `credentialId`.
   2801         0,
   2802         0,
   2803         0,
   2804         0,
   2805         0,
   2806         0,
   2807         0,
   2808         0,
   2809         0,
   2810         0,
   2811         0,
   2812         0,
   2813         0,
   2814         0,
   2815         0,
   2816         0,
   2817         // ML-DSA-87 COSE key.
   2818         cbor::MAP_3,
   2819         KTY,
   2820         AKP,
   2821         ALG,
   2822         cbor::NEG_INFO_24,
   2823         MLDSA87,
   2824         // `pub`.
   2825         cbor::NEG_ONE,
   2826         cbor::BYTES_INFO_25,
   2827         10,
   2828         32,
   2829         // Encoded key.
   2830         1,
   2831         1,
   2832         1,
   2833         1,
   2834         1,
   2835         1,
   2836         1,
   2837         1,
   2838         1,
   2839         1,
   2840         1,
   2841         1,
   2842         1,
   2843         1,
   2844         1,
   2845         1,
   2846         1,
   2847         1,
   2848         1,
   2849         1,
   2850         1,
   2851         1,
   2852         1,
   2853         1,
   2854         1,
   2855         1,
   2856         1,
   2857         1,
   2858         1,
   2859         1,
   2860         1,
   2861         1,
   2862         1,
   2863         1,
   2864         1,
   2865         1,
   2866         1,
   2867         1,
   2868         1,
   2869         1,
   2870         1,
   2871         1,
   2872         1,
   2873         1,
   2874         1,
   2875         1,
   2876         1,
   2877         1,
   2878         1,
   2879         1,
   2880         1,
   2881         1,
   2882         1,
   2883         1,
   2884         1,
   2885         1,
   2886         1,
   2887         1,
   2888         1,
   2889         1,
   2890         1,
   2891         1,
   2892         1,
   2893         1,
   2894         1,
   2895         1,
   2896         1,
   2897         1,
   2898         1,
   2899         1,
   2900         1,
   2901         1,
   2902         1,
   2903         1,
   2904         1,
   2905         1,
   2906         1,
   2907         1,
   2908         1,
   2909         1,
   2910         1,
   2911         1,
   2912         1,
   2913         1,
   2914         1,
   2915         1,
   2916         1,
   2917         1,
   2918         1,
   2919         1,
   2920         1,
   2921         1,
   2922         1,
   2923         1,
   2924         1,
   2925         1,
   2926         1,
   2927         1,
   2928         1,
   2929         1,
   2930         1,
   2931         1,
   2932         1,
   2933         1,
   2934         1,
   2935         1,
   2936         1,
   2937         1,
   2938         1,
   2939         1,
   2940         1,
   2941         1,
   2942         1,
   2943         1,
   2944         1,
   2945         1,
   2946         1,
   2947         1,
   2948         1,
   2949         1,
   2950         1,
   2951         1,
   2952         1,
   2953         1,
   2954         1,
   2955         1,
   2956         1,
   2957         1,
   2958         1,
   2959         1,
   2960         1,
   2961         1,
   2962         1,
   2963         1,
   2964         1,
   2965         1,
   2966         1,
   2967         1,
   2968         1,
   2969         1,
   2970         1,
   2971         1,
   2972         1,
   2973         1,
   2974         1,
   2975         1,
   2976         1,
   2977         1,
   2978         1,
   2979         1,
   2980         1,
   2981         1,
   2982         1,
   2983         1,
   2984         1,
   2985         1,
   2986         1,
   2987         1,
   2988         1,
   2989         1,
   2990         1,
   2991         1,
   2992         1,
   2993         1,
   2994         1,
   2995         1,
   2996         1,
   2997         1,
   2998         1,
   2999         1,
   3000         1,
   3001         1,
   3002         1,
   3003         1,
   3004         1,
   3005         1,
   3006         1,
   3007         1,
   3008         1,
   3009         1,
   3010         1,
   3011         1,
   3012         1,
   3013         1,
   3014         1,
   3015         1,
   3016         1,
   3017         1,
   3018         1,
   3019         1,
   3020         1,
   3021         1,
   3022         1,
   3023         1,
   3024         1,
   3025         1,
   3026         1,
   3027         1,
   3028         1,
   3029         1,
   3030         1,
   3031         1,
   3032         1,
   3033         1,
   3034         1,
   3035         1,
   3036         1,
   3037         1,
   3038         1,
   3039         1,
   3040         1,
   3041         1,
   3042         1,
   3043         1,
   3044         1,
   3045         1,
   3046         1,
   3047         1,
   3048         1,
   3049         1,
   3050         1,
   3051         1,
   3052         1,
   3053         1,
   3054         1,
   3055         1,
   3056         1,
   3057         1,
   3058         1,
   3059         1,
   3060         1,
   3061         1,
   3062         1,
   3063         1,
   3064         1,
   3065         1,
   3066         1,
   3067         1,
   3068         1,
   3069         1,
   3070         1,
   3071         1,
   3072         1,
   3073         1,
   3074         1,
   3075         1,
   3076         1,
   3077         1,
   3078         1,
   3079         1,
   3080         1,
   3081         1,
   3082         1,
   3083         1,
   3084         1,
   3085         1,
   3086         1,
   3087         1,
   3088         1,
   3089         1,
   3090         1,
   3091         1,
   3092         1,
   3093         1,
   3094         1,
   3095         1,
   3096         1,
   3097         1,
   3098         1,
   3099         1,
   3100         1,
   3101         1,
   3102         1,
   3103         1,
   3104         1,
   3105         1,
   3106         1,
   3107         1,
   3108         1,
   3109         1,
   3110         1,
   3111         1,
   3112         1,
   3113         1,
   3114         1,
   3115         1,
   3116         1,
   3117         1,
   3118         1,
   3119         1,
   3120         1,
   3121         1,
   3122         1,
   3123         1,
   3124         1,
   3125         1,
   3126         1,
   3127         1,
   3128         1,
   3129         1,
   3130         1,
   3131         1,
   3132         1,
   3133         1,
   3134         1,
   3135         1,
   3136         1,
   3137         1,
   3138         1,
   3139         1,
   3140         1,
   3141         1,
   3142         1,
   3143         1,
   3144         1,
   3145         1,
   3146         1,
   3147         1,
   3148         1,
   3149         1,
   3150         1,
   3151         1,
   3152         1,
   3153         1,
   3154         1,
   3155         1,
   3156         1,
   3157         1,
   3158         1,
   3159         1,
   3160         1,
   3161         1,
   3162         1,
   3163         1,
   3164         1,
   3165         1,
   3166         1,
   3167         1,
   3168         1,
   3169         1,
   3170         1,
   3171         1,
   3172         1,
   3173         1,
   3174         1,
   3175         1,
   3176         1,
   3177         1,
   3178         1,
   3179         1,
   3180         1,
   3181         1,
   3182         1,
   3183         1,
   3184         1,
   3185         1,
   3186         1,
   3187         1,
   3188         1,
   3189         1,
   3190         1,
   3191         1,
   3192         1,
   3193         1,
   3194         1,
   3195         1,
   3196         1,
   3197         1,
   3198         1,
   3199         1,
   3200         1,
   3201         1,
   3202         1,
   3203         1,
   3204         1,
   3205         1,
   3206         1,
   3207         1,
   3208         1,
   3209         1,
   3210         1,
   3211         1,
   3212         1,
   3213         1,
   3214         1,
   3215         1,
   3216         1,
   3217         1,
   3218         1,
   3219         1,
   3220         1,
   3221         1,
   3222         1,
   3223         1,
   3224         1,
   3225         1,
   3226         1,
   3227         1,
   3228         1,
   3229         1,
   3230         1,
   3231         1,
   3232         1,
   3233         1,
   3234         1,
   3235         1,
   3236         1,
   3237         1,
   3238         1,
   3239         1,
   3240         1,
   3241         1,
   3242         1,
   3243         1,
   3244         1,
   3245         1,
   3246         1,
   3247         1,
   3248         1,
   3249         1,
   3250         1,
   3251         1,
   3252         1,
   3253         1,
   3254         1,
   3255         1,
   3256         1,
   3257         1,
   3258         1,
   3259         1,
   3260         1,
   3261         1,
   3262         1,
   3263         1,
   3264         1,
   3265         1,
   3266         1,
   3267         1,
   3268         1,
   3269         1,
   3270         1,
   3271         1,
   3272         1,
   3273         1,
   3274         1,
   3275         1,
   3276         1,
   3277         1,
   3278         1,
   3279         1,
   3280         1,
   3281         1,
   3282         1,
   3283         1,
   3284         1,
   3285         1,
   3286         1,
   3287         1,
   3288         1,
   3289         1,
   3290         1,
   3291         1,
   3292         1,
   3293         1,
   3294         1,
   3295         1,
   3296         1,
   3297         1,
   3298         1,
   3299         1,
   3300         1,
   3301         1,
   3302         1,
   3303         1,
   3304         1,
   3305         1,
   3306         1,
   3307         1,
   3308         1,
   3309         1,
   3310         1,
   3311         1,
   3312         1,
   3313         1,
   3314         1,
   3315         1,
   3316         1,
   3317         1,
   3318         1,
   3319         1,
   3320         1,
   3321         1,
   3322         1,
   3323         1,
   3324         1,
   3325         1,
   3326         1,
   3327         1,
   3328         1,
   3329         1,
   3330         1,
   3331         1,
   3332         1,
   3333         1,
   3334         1,
   3335         1,
   3336         1,
   3337         1,
   3338         1,
   3339         1,
   3340         1,
   3341         1,
   3342         1,
   3343         1,
   3344         1,
   3345         1,
   3346         1,
   3347         1,
   3348         1,
   3349         1,
   3350         1,
   3351         1,
   3352         1,
   3353         1,
   3354         1,
   3355         1,
   3356         1,
   3357         1,
   3358         1,
   3359         1,
   3360         1,
   3361         1,
   3362         1,
   3363         1,
   3364         1,
   3365         1,
   3366         1,
   3367         1,
   3368         1,
   3369         1,
   3370         1,
   3371         1,
   3372         1,
   3373         1,
   3374         1,
   3375         1,
   3376         1,
   3377         1,
   3378         1,
   3379         1,
   3380         1,
   3381         1,
   3382         1,
   3383         1,
   3384         1,
   3385         1,
   3386         1,
   3387         1,
   3388         1,
   3389         1,
   3390         1,
   3391         1,
   3392         1,
   3393         1,
   3394         1,
   3395         1,
   3396         1,
   3397         1,
   3398         1,
   3399         1,
   3400         1,
   3401         1,
   3402         1,
   3403         1,
   3404         1,
   3405         1,
   3406         1,
   3407         1,
   3408         1,
   3409         1,
   3410         1,
   3411         1,
   3412         1,
   3413         1,
   3414         1,
   3415         1,
   3416         1,
   3417         1,
   3418         1,
   3419         1,
   3420         1,
   3421         1,
   3422         1,
   3423         1,
   3424         1,
   3425         1,
   3426         1,
   3427         1,
   3428         1,
   3429         1,
   3430         1,
   3431         1,
   3432         1,
   3433         1,
   3434         1,
   3435         1,
   3436         1,
   3437         1,
   3438         1,
   3439         1,
   3440         1,
   3441         1,
   3442         1,
   3443         1,
   3444         1,
   3445         1,
   3446         1,
   3447         1,
   3448         1,
   3449         1,
   3450         1,
   3451         1,
   3452         1,
   3453         1,
   3454         1,
   3455         1,
   3456         1,
   3457         1,
   3458         1,
   3459         1,
   3460         1,
   3461         1,
   3462         1,
   3463         1,
   3464         1,
   3465         1,
   3466         1,
   3467         1,
   3468         1,
   3469         1,
   3470         1,
   3471         1,
   3472         1,
   3473         1,
   3474         1,
   3475         1,
   3476         1,
   3477         1,
   3478         1,
   3479         1,
   3480         1,
   3481         1,
   3482         1,
   3483         1,
   3484         1,
   3485         1,
   3486         1,
   3487         1,
   3488         1,
   3489         1,
   3490         1,
   3491         1,
   3492         1,
   3493         1,
   3494         1,
   3495         1,
   3496         1,
   3497         1,
   3498         1,
   3499         1,
   3500         1,
   3501         1,
   3502         1,
   3503         1,
   3504         1,
   3505         1,
   3506         1,
   3507         1,
   3508         1,
   3509         1,
   3510         1,
   3511         1,
   3512         1,
   3513         1,
   3514         1,
   3515         1,
   3516         1,
   3517         1,
   3518         1,
   3519         1,
   3520         1,
   3521         1,
   3522         1,
   3523         1,
   3524         1,
   3525         1,
   3526         1,
   3527         1,
   3528         1,
   3529         1,
   3530         1,
   3531         1,
   3532         1,
   3533         1,
   3534         1,
   3535         1,
   3536         1,
   3537         1,
   3538         1,
   3539         1,
   3540         1,
   3541         1,
   3542         1,
   3543         1,
   3544         1,
   3545         1,
   3546         1,
   3547         1,
   3548         1,
   3549         1,
   3550         1,
   3551         1,
   3552         1,
   3553         1,
   3554         1,
   3555         1,
   3556         1,
   3557         1,
   3558         1,
   3559         1,
   3560         1,
   3561         1,
   3562         1,
   3563         1,
   3564         1,
   3565         1,
   3566         1,
   3567         1,
   3568         1,
   3569         1,
   3570         1,
   3571         1,
   3572         1,
   3573         1,
   3574         1,
   3575         1,
   3576         1,
   3577         1,
   3578         1,
   3579         1,
   3580         1,
   3581         1,
   3582         1,
   3583         1,
   3584         1,
   3585         1,
   3586         1,
   3587         1,
   3588         1,
   3589         1,
   3590         1,
   3591         1,
   3592         1,
   3593         1,
   3594         1,
   3595         1,
   3596         1,
   3597         1,
   3598         1,
   3599         1,
   3600         1,
   3601         1,
   3602         1,
   3603         1,
   3604         1,
   3605         1,
   3606         1,
   3607         1,
   3608         1,
   3609         1,
   3610         1,
   3611         1,
   3612         1,
   3613         1,
   3614         1,
   3615         1,
   3616         1,
   3617         1,
   3618         1,
   3619         1,
   3620         1,
   3621         1,
   3622         1,
   3623         1,
   3624         1,
   3625         1,
   3626         1,
   3627         1,
   3628         1,
   3629         1,
   3630         1,
   3631         1,
   3632         1,
   3633         1,
   3634         1,
   3635         1,
   3636         1,
   3637         1,
   3638         1,
   3639         1,
   3640         1,
   3641         1,
   3642         1,
   3643         1,
   3644         1,
   3645         1,
   3646         1,
   3647         1,
   3648         1,
   3649         1,
   3650         1,
   3651         1,
   3652         1,
   3653         1,
   3654         1,
   3655         1,
   3656         1,
   3657         1,
   3658         1,
   3659         1,
   3660         1,
   3661         1,
   3662         1,
   3663         1,
   3664         1,
   3665         1,
   3666         1,
   3667         1,
   3668         1,
   3669         1,
   3670         1,
   3671         1,
   3672         1,
   3673         1,
   3674         1,
   3675         1,
   3676         1,
   3677         1,
   3678         1,
   3679         1,
   3680         1,
   3681         1,
   3682         1,
   3683         1,
   3684         1,
   3685         1,
   3686         1,
   3687         1,
   3688         1,
   3689         1,
   3690         1,
   3691         1,
   3692         1,
   3693         1,
   3694         1,
   3695         1,
   3696         1,
   3697         1,
   3698         1,
   3699         1,
   3700         1,
   3701         1,
   3702         1,
   3703         1,
   3704         1,
   3705         1,
   3706         1,
   3707         1,
   3708         1,
   3709         1,
   3710         1,
   3711         1,
   3712         1,
   3713         1,
   3714         1,
   3715         1,
   3716         1,
   3717         1,
   3718         1,
   3719         1,
   3720         1,
   3721         1,
   3722         1,
   3723         1,
   3724         1,
   3725         1,
   3726         1,
   3727         1,
   3728         1,
   3729         1,
   3730         1,
   3731         1,
   3732         1,
   3733         1,
   3734         1,
   3735         1,
   3736         1,
   3737         1,
   3738         1,
   3739         1,
   3740         1,
   3741         1,
   3742         1,
   3743         1,
   3744         1,
   3745         1,
   3746         1,
   3747         1,
   3748         1,
   3749         1,
   3750         1,
   3751         1,
   3752         1,
   3753         1,
   3754         1,
   3755         1,
   3756         1,
   3757         1,
   3758         1,
   3759         1,
   3760         1,
   3761         1,
   3762         1,
   3763         1,
   3764         1,
   3765         1,
   3766         1,
   3767         1,
   3768         1,
   3769         1,
   3770         1,
   3771         1,
   3772         1,
   3773         1,
   3774         1,
   3775         1,
   3776         1,
   3777         1,
   3778         1,
   3779         1,
   3780         1,
   3781         1,
   3782         1,
   3783         1,
   3784         1,
   3785         1,
   3786         1,
   3787         1,
   3788         1,
   3789         1,
   3790         1,
   3791         1,
   3792         1,
   3793         1,
   3794         1,
   3795         1,
   3796         1,
   3797         1,
   3798         1,
   3799         1,
   3800         1,
   3801         1,
   3802         1,
   3803         1,
   3804         1,
   3805         1,
   3806         1,
   3807         1,
   3808         1,
   3809         1,
   3810         1,
   3811         1,
   3812         1,
   3813         1,
   3814         1,
   3815         1,
   3816         1,
   3817         1,
   3818         1,
   3819         1,
   3820         1,
   3821         1,
   3822         1,
   3823         1,
   3824         1,
   3825         1,
   3826         1,
   3827         1,
   3828         1,
   3829         1,
   3830         1,
   3831         1,
   3832         1,
   3833         1,
   3834         1,
   3835         1,
   3836         1,
   3837         1,
   3838         1,
   3839         1,
   3840         1,
   3841         1,
   3842         1,
   3843         1,
   3844         1,
   3845         1,
   3846         1,
   3847         1,
   3848         1,
   3849         1,
   3850         1,
   3851         1,
   3852         1,
   3853         1,
   3854         1,
   3855         1,
   3856         1,
   3857         1,
   3858         1,
   3859         1,
   3860         1,
   3861         1,
   3862         1,
   3863         1,
   3864         1,
   3865         1,
   3866         1,
   3867         1,
   3868         1,
   3869         1,
   3870         1,
   3871         1,
   3872         1,
   3873         1,
   3874         1,
   3875         1,
   3876         1,
   3877         1,
   3878         1,
   3879         1,
   3880         1,
   3881         1,
   3882         1,
   3883         1,
   3884         1,
   3885         1,
   3886         1,
   3887         1,
   3888         1,
   3889         1,
   3890         1,
   3891         1,
   3892         1,
   3893         1,
   3894         1,
   3895         1,
   3896         1,
   3897         1,
   3898         1,
   3899         1,
   3900         1,
   3901         1,
   3902         1,
   3903         1,
   3904         1,
   3905         1,
   3906         1,
   3907         1,
   3908         1,
   3909         1,
   3910         1,
   3911         1,
   3912         1,
   3913         1,
   3914         1,
   3915         1,
   3916         1,
   3917         1,
   3918         1,
   3919         1,
   3920         1,
   3921         1,
   3922         1,
   3923         1,
   3924         1,
   3925         1,
   3926         1,
   3927         1,
   3928         1,
   3929         1,
   3930         1,
   3931         1,
   3932         1,
   3933         1,
   3934         1,
   3935         1,
   3936         1,
   3937         1,
   3938         1,
   3939         1,
   3940         1,
   3941         1,
   3942         1,
   3943         1,
   3944         1,
   3945         1,
   3946         1,
   3947         1,
   3948         1,
   3949         1,
   3950         1,
   3951         1,
   3952         1,
   3953         1,
   3954         1,
   3955         1,
   3956         1,
   3957         1,
   3958         1,
   3959         1,
   3960         1,
   3961         1,
   3962         1,
   3963         1,
   3964         1,
   3965         1,
   3966         1,
   3967         1,
   3968         1,
   3969         1,
   3970         1,
   3971         1,
   3972         1,
   3973         1,
   3974         1,
   3975         1,
   3976         1,
   3977         1,
   3978         1,
   3979         1,
   3980         1,
   3981         1,
   3982         1,
   3983         1,
   3984         1,
   3985         1,
   3986         1,
   3987         1,
   3988         1,
   3989         1,
   3990         1,
   3991         1,
   3992         1,
   3993         1,
   3994         1,
   3995         1,
   3996         1,
   3997         1,
   3998         1,
   3999         1,
   4000         1,
   4001         1,
   4002         1,
   4003         1,
   4004         1,
   4005         1,
   4006         1,
   4007         1,
   4008         1,
   4009         1,
   4010         1,
   4011         1,
   4012         1,
   4013         1,
   4014         1,
   4015         1,
   4016         1,
   4017         1,
   4018         1,
   4019         1,
   4020         1,
   4021         1,
   4022         1,
   4023         1,
   4024         1,
   4025         1,
   4026         1,
   4027         1,
   4028         1,
   4029         1,
   4030         1,
   4031         1,
   4032         1,
   4033         1,
   4034         1,
   4035         1,
   4036         1,
   4037         1,
   4038         1,
   4039         1,
   4040         1,
   4041         1,
   4042         1,
   4043         1,
   4044         1,
   4045         1,
   4046         1,
   4047         1,
   4048         1,
   4049         1,
   4050         1,
   4051         1,
   4052         1,
   4053         1,
   4054         1,
   4055         1,
   4056         1,
   4057         1,
   4058         1,
   4059         1,
   4060         1,
   4061         1,
   4062         1,
   4063         1,
   4064         1,
   4065         1,
   4066         1,
   4067         1,
   4068         1,
   4069         1,
   4070         1,
   4071         1,
   4072         1,
   4073         1,
   4074         1,
   4075         1,
   4076         1,
   4077         1,
   4078         1,
   4079         1,
   4080         1,
   4081         1,
   4082         1,
   4083         1,
   4084         1,
   4085         1,
   4086         1,
   4087         1,
   4088         1,
   4089         1,
   4090         1,
   4091         1,
   4092         1,
   4093         1,
   4094         1,
   4095         1,
   4096         1,
   4097         1,
   4098         1,
   4099         1,
   4100         1,
   4101         1,
   4102         1,
   4103         1,
   4104         1,
   4105         1,
   4106         1,
   4107         1,
   4108         1,
   4109         1,
   4110         1,
   4111         1,
   4112         1,
   4113         1,
   4114         1,
   4115         1,
   4116         1,
   4117         1,
   4118         1,
   4119         1,
   4120         1,
   4121         1,
   4122         1,
   4123         1,
   4124         1,
   4125         1,
   4126         1,
   4127         1,
   4128         1,
   4129         1,
   4130         1,
   4131         1,
   4132         1,
   4133         1,
   4134         1,
   4135         1,
   4136         1,
   4137         1,
   4138         1,
   4139         1,
   4140         1,
   4141         1,
   4142         1,
   4143         1,
   4144         1,
   4145         1,
   4146         1,
   4147         1,
   4148         1,
   4149         1,
   4150         1,
   4151         1,
   4152         1,
   4153         1,
   4154         1,
   4155         1,
   4156         1,
   4157         1,
   4158         1,
   4159         1,
   4160         1,
   4161         1,
   4162         1,
   4163         1,
   4164         1,
   4165         1,
   4166         1,
   4167         1,
   4168         1,
   4169         1,
   4170         1,
   4171         1,
   4172         1,
   4173         1,
   4174         1,
   4175         1,
   4176         1,
   4177         1,
   4178         1,
   4179         1,
   4180         1,
   4181         1,
   4182         1,
   4183         1,
   4184         1,
   4185         1,
   4186         1,
   4187         1,
   4188         1,
   4189         1,
   4190         1,
   4191         1,
   4192         1,
   4193         1,
   4194         1,
   4195         1,
   4196         1,
   4197         1,
   4198         1,
   4199         1,
   4200         1,
   4201         1,
   4202         1,
   4203         1,
   4204         1,
   4205         1,
   4206         1,
   4207         1,
   4208         1,
   4209         1,
   4210         1,
   4211         1,
   4212         1,
   4213         1,
   4214         1,
   4215         1,
   4216         1,
   4217         1,
   4218         1,
   4219         1,
   4220         1,
   4221         1,
   4222         1,
   4223         1,
   4224         1,
   4225         1,
   4226         1,
   4227         1,
   4228         1,
   4229         1,
   4230         1,
   4231         1,
   4232         1,
   4233         1,
   4234         1,
   4235         1,
   4236         1,
   4237         1,
   4238         1,
   4239         1,
   4240         1,
   4241         1,
   4242         1,
   4243         1,
   4244         1,
   4245         1,
   4246         1,
   4247         1,
   4248         1,
   4249         1,
   4250         1,
   4251         1,
   4252         1,
   4253         1,
   4254         1,
   4255         1,
   4256         1,
   4257         1,
   4258         1,
   4259         1,
   4260         1,
   4261         1,
   4262         1,
   4263         1,
   4264         1,
   4265         1,
   4266         1,
   4267         1,
   4268         1,
   4269         1,
   4270         1,
   4271         1,
   4272         1,
   4273         1,
   4274         1,
   4275         1,
   4276         1,
   4277         1,
   4278         1,
   4279         1,
   4280         1,
   4281         1,
   4282         1,
   4283         1,
   4284         1,
   4285         1,
   4286         1,
   4287         1,
   4288         1,
   4289         1,
   4290         1,
   4291         1,
   4292         1,
   4293         1,
   4294         1,
   4295         1,
   4296         1,
   4297         1,
   4298         1,
   4299         1,
   4300         1,
   4301         1,
   4302         1,
   4303         1,
   4304         1,
   4305         1,
   4306         1,
   4307         1,
   4308         1,
   4309         1,
   4310         1,
   4311         1,
   4312         1,
   4313         1,
   4314         1,
   4315         1,
   4316         1,
   4317         1,
   4318         1,
   4319         1,
   4320         1,
   4321         1,
   4322         1,
   4323         1,
   4324         1,
   4325         1,
   4326         1,
   4327         1,
   4328         1,
   4329         1,
   4330         1,
   4331         1,
   4332         1,
   4333         1,
   4334         1,
   4335         1,
   4336         1,
   4337         1,
   4338         1,
   4339         1,
   4340         1,
   4341         1,
   4342         1,
   4343         1,
   4344         1,
   4345         1,
   4346         1,
   4347         1,
   4348         1,
   4349         1,
   4350         1,
   4351         1,
   4352         1,
   4353         1,
   4354         1,
   4355         1,
   4356         1,
   4357         1,
   4358         1,
   4359         1,
   4360         1,
   4361         1,
   4362         1,
   4363         1,
   4364         1,
   4365         1,
   4366         1,
   4367         1,
   4368         1,
   4369         1,
   4370         1,
   4371         1,
   4372         1,
   4373         1,
   4374         1,
   4375         1,
   4376         1,
   4377         1,
   4378         1,
   4379         1,
   4380         1,
   4381         1,
   4382         1,
   4383         1,
   4384         1,
   4385         1,
   4386         1,
   4387         1,
   4388         1,
   4389         1,
   4390         1,
   4391         1,
   4392         1,
   4393         1,
   4394         1,
   4395         1,
   4396         1,
   4397         1,
   4398         1,
   4399         1,
   4400         1,
   4401         1,
   4402         1,
   4403         1,
   4404         1,
   4405         1,
   4406         1,
   4407         1,
   4408         1,
   4409         1,
   4410         1,
   4411         1,
   4412         1,
   4413         1,
   4414         1,
   4415         1,
   4416         1,
   4417         1,
   4418         1,
   4419         1,
   4420         1,
   4421         1,
   4422         1,
   4423         1,
   4424         1,
   4425         1,
   4426         1,
   4427         1,
   4428         1,
   4429         1,
   4430         1,
   4431         1,
   4432         1,
   4433         1,
   4434         1,
   4435         1,
   4436         1,
   4437         1,
   4438         1,
   4439         1,
   4440         1,
   4441         1,
   4442         1,
   4443         1,
   4444         1,
   4445         1,
   4446         1,
   4447         1,
   4448         1,
   4449         1,
   4450         1,
   4451         1,
   4452         1,
   4453         1,
   4454         1,
   4455         1,
   4456         1,
   4457         1,
   4458         1,
   4459         1,
   4460         1,
   4461         1,
   4462         1,
   4463         1,
   4464         1,
   4465         1,
   4466         1,
   4467         1,
   4468         1,
   4469         1,
   4470         1,
   4471         1,
   4472         1,
   4473         1,
   4474         1,
   4475         1,
   4476         1,
   4477         1,
   4478         1,
   4479         1,
   4480         1,
   4481         1,
   4482         1,
   4483         1,
   4484         1,
   4485         1,
   4486         1,
   4487         1,
   4488         1,
   4489         1,
   4490         1,
   4491         1,
   4492         1,
   4493         1,
   4494         1,
   4495         1,
   4496         1,
   4497         1,
   4498         1,
   4499         1,
   4500         1,
   4501         1,
   4502         1,
   4503         1,
   4504         1,
   4505         1,
   4506         1,
   4507         1,
   4508         1,
   4509         1,
   4510         1,
   4511         1,
   4512         1,
   4513         1,
   4514         1,
   4515         1,
   4516         1,
   4517         1,
   4518         1,
   4519         1,
   4520         1,
   4521         1,
   4522         1,
   4523         1,
   4524         1,
   4525         1,
   4526         1,
   4527         1,
   4528         1,
   4529         1,
   4530         1,
   4531         1,
   4532         1,
   4533         1,
   4534         1,
   4535         1,
   4536         1,
   4537         1,
   4538         1,
   4539         1,
   4540         1,
   4541         1,
   4542         1,
   4543         1,
   4544         1,
   4545         1,
   4546         1,
   4547         1,
   4548         1,
   4549         1,
   4550         1,
   4551         1,
   4552         1,
   4553         1,
   4554         1,
   4555         1,
   4556         1,
   4557         1,
   4558         1,
   4559         1,
   4560         1,
   4561         1,
   4562         1,
   4563         1,
   4564         1,
   4565         1,
   4566         1,
   4567         1,
   4568         1,
   4569         1,
   4570         1,
   4571         1,
   4572         1,
   4573         1,
   4574         1,
   4575         1,
   4576         1,
   4577         1,
   4578         1,
   4579         1,
   4580         1,
   4581         1,
   4582         1,
   4583         1,
   4584         1,
   4585         1,
   4586         1,
   4587         1,
   4588         1,
   4589         1,
   4590         1,
   4591         1,
   4592         1,
   4593         1,
   4594         1,
   4595         1,
   4596         1,
   4597         1,
   4598         1,
   4599         1,
   4600         1,
   4601         1,
   4602         1,
   4603         1,
   4604         1,
   4605         1,
   4606         1,
   4607         1,
   4608         1,
   4609         1,
   4610         1,
   4611         1,
   4612         1,
   4613         1,
   4614         1,
   4615         1,
   4616         1,
   4617         1,
   4618         1,
   4619         1,
   4620         1,
   4621         1,
   4622         1,
   4623         1,
   4624         1,
   4625         1,
   4626         1,
   4627         1,
   4628         1,
   4629         1,
   4630         1,
   4631         1,
   4632         1,
   4633         1,
   4634         1,
   4635         1,
   4636         1,
   4637         1,
   4638         1,
   4639         1,
   4640         1,
   4641         1,
   4642         1,
   4643         1,
   4644         1,
   4645         1,
   4646         1,
   4647         1,
   4648         1,
   4649         1,
   4650         1,
   4651         1,
   4652         1,
   4653         1,
   4654         1,
   4655         1,
   4656         1,
   4657         1,
   4658         1,
   4659         1,
   4660         1,
   4661         1,
   4662         1,
   4663         1,
   4664         1,
   4665         1,
   4666         1,
   4667         1,
   4668         1,
   4669         1,
   4670         1,
   4671         1,
   4672         1,
   4673         1,
   4674         1,
   4675         1,
   4676         1,
   4677         1,
   4678         1,
   4679         1,
   4680         1,
   4681         1,
   4682         1,
   4683         1,
   4684         1,
   4685         1,
   4686         1,
   4687         1,
   4688         1,
   4689         1,
   4690         1,
   4691         1,
   4692         1,
   4693         1,
   4694         1,
   4695         1,
   4696         1,
   4697         1,
   4698         1,
   4699         1,
   4700         1,
   4701         1,
   4702         1,
   4703         1,
   4704         1,
   4705         1,
   4706         1,
   4707         1,
   4708         1,
   4709         1,
   4710         1,
   4711         1,
   4712         1,
   4713         1,
   4714         1,
   4715         1,
   4716         1,
   4717         1,
   4718         1,
   4719         1,
   4720         1,
   4721         1,
   4722         1,
   4723         1,
   4724         1,
   4725         1,
   4726         1,
   4727         1,
   4728         1,
   4729         1,
   4730         1,
   4731         1,
   4732         1,
   4733         1,
   4734         1,
   4735         1,
   4736         1,
   4737         1,
   4738         1,
   4739         1,
   4740         1,
   4741         1,
   4742         1,
   4743         1,
   4744         1,
   4745         1,
   4746         1,
   4747         1,
   4748         1,
   4749         1,
   4750         1,
   4751         1,
   4752         1,
   4753         1,
   4754         1,
   4755         1,
   4756         1,
   4757         1,
   4758         1,
   4759         1,
   4760         1,
   4761         1,
   4762         1,
   4763         1,
   4764         1,
   4765         1,
   4766         1,
   4767         1,
   4768         1,
   4769         1,
   4770         1,
   4771         1,
   4772         1,
   4773         1,
   4774         1,
   4775         1,
   4776         1,
   4777         1,
   4778         1,
   4779         1,
   4780         1,
   4781         1,
   4782         1,
   4783         1,
   4784         1,
   4785         1,
   4786         1,
   4787         1,
   4788         1,
   4789         1,
   4790         1,
   4791         1,
   4792         1,
   4793         1,
   4794         1,
   4795         1,
   4796         1,
   4797         1,
   4798         1,
   4799         1,
   4800         1,
   4801         1,
   4802         1,
   4803         1,
   4804         1,
   4805         1,
   4806         1,
   4807         1,
   4808         1,
   4809         1,
   4810         1,
   4811         1,
   4812         1,
   4813         1,
   4814         1,
   4815         1,
   4816         1,
   4817         1,
   4818         1,
   4819         1,
   4820         1,
   4821         1,
   4822         1,
   4823         1,
   4824         1,
   4825         1,
   4826         1,
   4827         1,
   4828         1,
   4829         1,
   4830         1,
   4831         1,
   4832         1,
   4833         1,
   4834         1,
   4835         1,
   4836         1,
   4837         1,
   4838         1,
   4839         1,
   4840         1,
   4841         1,
   4842         1,
   4843         1,
   4844         1,
   4845         1,
   4846         1,
   4847         1,
   4848         1,
   4849         1,
   4850         1,
   4851         1,
   4852         1,
   4853         1,
   4854         1,
   4855         1,
   4856         1,
   4857         1,
   4858         1,
   4859         1,
   4860         1,
   4861         1,
   4862         1,
   4863         1,
   4864         1,
   4865         1,
   4866         1,
   4867         1,
   4868         1,
   4869         1,
   4870         1,
   4871         1,
   4872         1,
   4873         1,
   4874         1,
   4875         1,
   4876         1,
   4877         1,
   4878         1,
   4879         1,
   4880         1,
   4881         1,
   4882         1,
   4883         1,
   4884         1,
   4885         1,
   4886         1,
   4887         1,
   4888         1,
   4889         1,
   4890         1,
   4891         1,
   4892         1,
   4893         1,
   4894         1,
   4895         1,
   4896         1,
   4897         1,
   4898         1,
   4899         1,
   4900         1,
   4901         1,
   4902         1,
   4903         1,
   4904         1,
   4905         1,
   4906         1,
   4907         1,
   4908         1,
   4909         1,
   4910         1,
   4911         1,
   4912         1,
   4913         1,
   4914         1,
   4915         1,
   4916         1,
   4917         1,
   4918         1,
   4919         1,
   4920         1,
   4921         1,
   4922         1,
   4923         1,
   4924         1,
   4925         1,
   4926         1,
   4927         1,
   4928         1,
   4929         1,
   4930         1,
   4931         1,
   4932         1,
   4933         1,
   4934         1,
   4935         1,
   4936         1,
   4937         1,
   4938         1,
   4939         1,
   4940         1,
   4941         1,
   4942         1,
   4943         1,
   4944         1,
   4945         1,
   4946         1,
   4947         1,
   4948         1,
   4949         1,
   4950         1,
   4951         1,
   4952         1,
   4953         1,
   4954         1,
   4955         1,
   4956         1,
   4957         1,
   4958         1,
   4959         1,
   4960         1,
   4961         1,
   4962         1,
   4963         1,
   4964         1,
   4965         1,
   4966         1,
   4967         1,
   4968         1,
   4969         1,
   4970         1,
   4971         1,
   4972         1,
   4973         1,
   4974         1,
   4975         1,
   4976         1,
   4977         1,
   4978         1,
   4979         1,
   4980         1,
   4981         1,
   4982         1,
   4983         1,
   4984         1,
   4985         1,
   4986         1,
   4987         1,
   4988         1,
   4989         1,
   4990         1,
   4991         1,
   4992         1,
   4993         1,
   4994         1,
   4995         1,
   4996         1,
   4997         1,
   4998         1,
   4999         1,
   5000         1,
   5001         1,
   5002         1,
   5003         1,
   5004         1,
   5005         1,
   5006         1,
   5007         1,
   5008         1,
   5009         1,
   5010         1,
   5011         1,
   5012         1,
   5013         1,
   5014         1,
   5015         1,
   5016         1,
   5017         1,
   5018         1,
   5019         1,
   5020         1,
   5021         1,
   5022         1,
   5023         1,
   5024         1,
   5025         1,
   5026         1,
   5027         1,
   5028         1,
   5029         1,
   5030         1,
   5031         1,
   5032         1,
   5033         1,
   5034         1,
   5035         1,
   5036         1,
   5037         1,
   5038         1,
   5039         1,
   5040         1,
   5041         1,
   5042         1,
   5043         1,
   5044         1,
   5045         1,
   5046         1,
   5047         1,
   5048         1,
   5049         1,
   5050         1,
   5051         1,
   5052         1,
   5053         1,
   5054         1,
   5055         1,
   5056         1,
   5057         1,
   5058         1,
   5059         1,
   5060         1,
   5061         1,
   5062         1,
   5063         1,
   5064         1,
   5065         1,
   5066         1,
   5067         1,
   5068         1,
   5069         1,
   5070         1,
   5071         1,
   5072         1,
   5073         1,
   5074         1,
   5075         1,
   5076         1,
   5077         1,
   5078         1,
   5079         1,
   5080         1,
   5081         1,
   5082         1,
   5083         1,
   5084         1,
   5085         1,
   5086         1,
   5087         1,
   5088         1,
   5089         1,
   5090         1,
   5091         1,
   5092         1,
   5093         1,
   5094         1,
   5095         1,
   5096         1,
   5097         1,
   5098         1,
   5099         1,
   5100         1,
   5101         1,
   5102         1,
   5103         1,
   5104         1,
   5105         1,
   5106         1,
   5107         1,
   5108         1,
   5109         1,
   5110         1,
   5111         1,
   5112         1,
   5113         1,
   5114         1,
   5115         1,
   5116         1,
   5117         1,
   5118         1,
   5119         1,
   5120         1,
   5121         1,
   5122         1,
   5123         1,
   5124         1,
   5125         1,
   5126         1,
   5127         1,
   5128         1,
   5129         1,
   5130         1,
   5131         1,
   5132         1,
   5133         1,
   5134         1,
   5135         1,
   5136         1,
   5137         1,
   5138         1,
   5139         1,
   5140         1,
   5141         1,
   5142         1,
   5143         1,
   5144         1,
   5145         1,
   5146         1,
   5147         1,
   5148         1,
   5149         1,
   5150         1,
   5151         1,
   5152         1,
   5153         1,
   5154         1,
   5155         1,
   5156         1,
   5157         1,
   5158         1,
   5159         1,
   5160         1,
   5161         1,
   5162         1,
   5163         1,
   5164         1,
   5165         1,
   5166         1,
   5167         1,
   5168         1,
   5169         1,
   5170         1,
   5171         1,
   5172         1,
   5173         1,
   5174         1,
   5175         1,
   5176         1,
   5177         1,
   5178         1,
   5179         1,
   5180         1,
   5181         1,
   5182         1,
   5183         1,
   5184         1,
   5185         1,
   5186         1,
   5187         1,
   5188         1,
   5189         1,
   5190         1,
   5191         1,
   5192         1,
   5193         1,
   5194         1,
   5195         1,
   5196         1,
   5197         1,
   5198         1,
   5199         1,
   5200         1,
   5201         1,
   5202         1,
   5203         1,
   5204         1,
   5205         1,
   5206         1,
   5207         1,
   5208         1,
   5209         1,
   5210         1,
   5211         1,
   5212         1,
   5213         1,
   5214         1,
   5215         1,
   5216         1,
   5217         1,
   5218         1,
   5219         1,
   5220         1,
   5221         1,
   5222         1,
   5223         1,
   5224         1,
   5225         1,
   5226         1,
   5227         1,
   5228         1,
   5229         1,
   5230         1,
   5231         1,
   5232         1,
   5233         1,
   5234         1,
   5235         1,
   5236         1,
   5237         1,
   5238         1,
   5239         1,
   5240         1,
   5241         1,
   5242         1,
   5243         1,
   5244         1,
   5245         1,
   5246         1,
   5247         1,
   5248         1,
   5249         1,
   5250         1,
   5251         1,
   5252         1,
   5253         1,
   5254         1,
   5255         1,
   5256         1,
   5257         1,
   5258         1,
   5259         1,
   5260         1,
   5261         1,
   5262         1,
   5263         1,
   5264         1,
   5265         1,
   5266         1,
   5267         1,
   5268         1,
   5269         1,
   5270         1,
   5271         1,
   5272         1,
   5273         1,
   5274         1,
   5275         1,
   5276         1,
   5277         1,
   5278         1,
   5279         1,
   5280         1,
   5281         1,
   5282         1,
   5283         1,
   5284         1,
   5285         1,
   5286         1,
   5287         1,
   5288         1,
   5289         1,
   5290         1,
   5291         1,
   5292         1,
   5293         1,
   5294         1,
   5295         1,
   5296         1,
   5297         1,
   5298         1,
   5299         1,
   5300         1,
   5301         1,
   5302         1,
   5303         1,
   5304         1,
   5305         1,
   5306         1,
   5307         1,
   5308         1,
   5309         1,
   5310         1,
   5311         1,
   5312         1,
   5313         1,
   5314         1,
   5315         1,
   5316         1,
   5317         1,
   5318         1,
   5319         1,
   5320         1,
   5321         1,
   5322         1,
   5323         1,
   5324         1,
   5325         1,
   5326         1,
   5327         1,
   5328         1,
   5329         1,
   5330         1,
   5331         1,
   5332         1,
   5333         1,
   5334         1,
   5335         1,
   5336         1,
   5337         1,
   5338         1,
   5339         1,
   5340         1,
   5341         1,
   5342         1,
   5343         1,
   5344         1,
   5345         1,
   5346         1,
   5347         1,
   5348         1,
   5349         1,
   5350         1,
   5351         1,
   5352         1,
   5353         1,
   5354         1,
   5355         1,
   5356         1,
   5357         1,
   5358         1,
   5359         1,
   5360         1,
   5361         1,
   5362         1,
   5363         1,
   5364         1,
   5365         1,
   5366         1,
   5367         1,
   5368         1,
   5369         1,
   5370         1,
   5371         1,
   5372         1,
   5373         1,
   5374         1,
   5375         1,
   5376         1,
   5377         1,
   5378         1,
   5379         1,
   5380         1,
   5381         1,
   5382         1,
   5383         1,
   5384         1,
   5385         1,
   5386         1,
   5387         1,
   5388         1,
   5389         1,
   5390         1,
   5391         1,
   5392         1,
   5393         1,
   5394         1,
   5395         1,
   5396         1,
   5397         1,
   5398         1,
   5399         1,
   5400         1,
   5401         1,
   5402         1,
   5403         1,
   5404         1,
   5405         1,
   5406         1,
   5407         1,
   5408         1,
   5409         1,
   5410         1,
   5411         1,
   5412         1,
   5413         1,
   5414         1,
   5415         1,
   5416         1,
   5417         1,
   5418         1,
   5419         1,
   5420         1,
   5421         1,
   5422     ];
   5423     let pub_key = MlDsaVerKey::<MlDsa87>::decode(&[1u8; 2592].into())
   5424         .to_public_key_der()
   5425         .unwrap();
   5426     let att_obj_len = att_obj.len();
   5427     let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
   5428     let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 2673..]);
   5429     let b64_key = base64url_nopad::encode(pub_key.as_bytes());
   5430     let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
   5431     // Base case is valid.
   5432     assert!(
   5433         serde_json::from_str::<RegistrationRelaxed>(
   5434             serde_json::json!({
   5435                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   5436                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   5437                 "response": {
   5438                     "clientDataJSON": b64_cdata_json,
   5439                     "authenticatorData": b64_adata,
   5440                     "transports": [],
   5441                     "publicKey": b64_key,
   5442                     "publicKeyAlgorithm": -50i8,
   5443                     "attestationObject": b64_aobj,
   5444                 },
   5445                 "clientExtensionResults": {},
   5446                 "type": "public-key"
   5447             })
   5448             .to_string()
   5449             .as_str()
   5450         )
   5451         .is_ok_and(
   5452             |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
   5453                 && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
   5454                 && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
   5455                     == *Sha256::digest(c_data_json.as_bytes())
   5456                 && reg.0.response.transports.is_empty()
   5457                 && matches!(
   5458                     reg.0.authenticator_attachment,
   5459                     AuthenticatorAttachment::None
   5460                 )
   5461                 && reg.0.client_extension_results.cred_props.is_none()
   5462                 && reg.0.client_extension_results.prf.is_none()
   5463         )
   5464     );
   5465     // `publicKeyAlgorithm` mismatch.
   5466     let mut err = Error::invalid_value(
   5467         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
   5468         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa87).as_str()
   5469     )
   5470     .to_string().into_bytes();
   5471     assert_eq!(
   5472         serde_json::from_str::<RegistrationRelaxed>(
   5473             serde_json::json!({
   5474                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   5475                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   5476                 "response": {
   5477                     "clientDataJSON": b64_cdata_json,
   5478                     "authenticatorData": b64_adata,
   5479                     "transports": [],
   5480                     "publicKey": b64_key,
   5481                     "publicKeyAlgorithm": -8i8,
   5482                     "attestationObject": b64_aobj,
   5483                 },
   5484                 "clientExtensionResults": {},
   5485                 "type": "public-key"
   5486             })
   5487             .to_string()
   5488             .as_str()
   5489         )
   5490         .unwrap_err()
   5491         .to_string()
   5492         .into_bytes()
   5493         .get(..err.len()),
   5494         Some(err.as_slice())
   5495     );
   5496     // Missing `publicKeyAlgorithm`.
   5497     drop(
   5498         serde_json::from_str::<RegistrationRelaxed>(
   5499             serde_json::json!({
   5500                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   5501                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   5502                 "response": {
   5503                     "clientDataJSON": b64_cdata_json,
   5504                     "authenticatorData": b64_adata,
   5505                     "transports": [],
   5506                     "publicKey": b64_key,
   5507                     "attestationObject": b64_aobj,
   5508                 },
   5509                 "clientExtensionResults": {},
   5510                 "type": "public-key"
   5511             })
   5512             .to_string()
   5513             .as_str(),
   5514         )
   5515         .unwrap(),
   5516     );
   5517     // `null` `publicKeyAlgorithm`.
   5518     drop(
   5519         serde_json::from_str::<RegistrationRelaxed>(
   5520             serde_json::json!({
   5521                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   5522                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   5523                 "response": {
   5524                     "clientDataJSON": b64_cdata_json,
   5525                     "authenticatorData": b64_adata,
   5526                     "transports": [],
   5527                     "publicKey": b64_key,
   5528                     "publicKeyAlgorithm": null,
   5529                     "attestationObject": b64_aobj,
   5530                 },
   5531                 "clientExtensionResults": {},
   5532                 "type": "public-key"
   5533             })
   5534             .to_string()
   5535             .as_str(),
   5536         )
   5537         .unwrap(),
   5538     );
   5539     // `publicKey` mismatch.
   5540     let bad_pub_key = MlDsaVerKey::<MlDsa87>::decode(&[2; 2592].into());
   5541     err = Error::invalid_value(
   5542         Unexpected::Bytes([0; 32].as_slice()),
   5543         &format!(
   5544             "DER-encoded public key to match the public key within the attestation object: MlDsa87(MlDsa87PubKey({:?}))",
   5545             &[1u8; 2592]
   5546         )
   5547         .as_str(),
   5548     )
   5549     .to_string().into_bytes();
   5550     assert_eq!(serde_json::from_str::<RegistrationRelaxed>(
   5551         serde_json::json!({
   5552             "id": "AAAAAAAAAAAAAAAAAAAAAA",
   5553             "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   5554             "response": {
   5555                 "clientDataJSON": b64_cdata_json,
   5556                 "authenticatorData": b64_adata,
   5557                 "transports": [],
   5558                 "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
   5559                 "publicKeyAlgorithm": -50i8,
   5560                 "attestationObject": b64_aobj,
   5561             },
   5562             "clientExtensionResults": {},
   5563             "type": "public-key"
   5564         })
   5565         .to_string()
   5566         .as_str()
   5567         )
   5568         .unwrap_err().to_string().into_bytes().get(..err.len()),
   5569         Some(err.as_slice())
   5570     );
   5571     // Missing `publicKey` is allowed when not using EdDSA, ES256, or RS256.
   5572     assert!(
   5573         serde_json::from_str::<RegistrationRelaxed>(
   5574             serde_json::json!({
   5575                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   5576                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   5577                 "response": {
   5578                     "clientDataJSON": b64_cdata_json,
   5579                     "authenticatorData": b64_adata,
   5580                     "transports": [],
   5581                     "publicKeyAlgorithm": -50i8,
   5582                     "attestationObject": b64_aobj,
   5583                 },
   5584                 "clientExtensionResults": {},
   5585                 "type": "public-key"
   5586             })
   5587             .to_string()
   5588             .as_str()
   5589         )
   5590         .is_ok()
   5591     );
   5592     // `publicKeyAlgorithm` mismatch when `publicKey` does not exist.
   5593     err = Error::invalid_value(
   5594         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   5595         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa87).as_str()
   5596     )
   5597     .to_string().into_bytes();
   5598     assert_eq!(
   5599         serde_json::from_str::<RegistrationRelaxed>(
   5600             serde_json::json!({
   5601                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   5602                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   5603                 "response": {
   5604                     "clientDataJSON": b64_cdata_json,
   5605                     "authenticatorData": b64_adata,
   5606                     "transports": [],
   5607                     "publicKeyAlgorithm": -7i8,
   5608                     "attestationObject": b64_aobj,
   5609                 },
   5610                 "clientExtensionResults": {},
   5611                 "type": "public-key"
   5612             })
   5613             .to_string()
   5614             .as_str()
   5615         )
   5616         .unwrap_err()
   5617         .to_string()
   5618         .into_bytes()
   5619         .get(..err.len()),
   5620         Some(err.as_slice())
   5621     );
   5622     // `null` `publicKey` is allowed when not using EdDSA, ES256, or RS256.
   5623     assert!(
   5624         serde_json::from_str::<RegistrationRelaxed>(
   5625             serde_json::json!({
   5626                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   5627                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   5628                 "response": {
   5629                     "clientDataJSON": b64_cdata_json,
   5630                     "authenticatorData": b64_adata,
   5631                     "transports": [],
   5632                     "publicKey": null,
   5633                     "publicKeyAlgorithm": -50i8,
   5634                     "attestationObject": b64_aobj,
   5635                 },
   5636                 "clientExtensionResults": {},
   5637                 "type": "public-key"
   5638             })
   5639             .to_string()
   5640             .as_str()
   5641         )
   5642         .is_ok()
   5643     );
   5644     // `publicKeyAlgorithm` mismatch when `publicKey` is null.
   5645     err = Error::invalid_value(
   5646         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   5647         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa87).as_str()
   5648     )
   5649     .to_string().into_bytes();
   5650     assert_eq!(
   5651         serde_json::from_str::<RegistrationRelaxed>(
   5652             serde_json::json!({
   5653                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   5654                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   5655                 "response": {
   5656                     "clientDataJSON": b64_cdata_json,
   5657                     "authenticatorData": b64_adata,
   5658                     "transports": [],
   5659                     "publicKey": null,
   5660                     "publicKeyAlgorithm": -7i8,
   5661                     "attestationObject": b64_aobj,
   5662                 },
   5663                 "clientExtensionResults": {},
   5664                 "type": "public-key"
   5665             })
   5666             .to_string()
   5667             .as_str()
   5668         )
   5669         .unwrap_err()
   5670         .to_string()
   5671         .into_bytes()
   5672         .get(..err.len()),
   5673         Some(err.as_slice())
   5674     );
   5675 }
   5676 #[expect(
   5677     clippy::assertions_on_result_states,
   5678     clippy::unwrap_used,
   5679     reason = "OK in tests"
   5680 )]
   5681 #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
   5682 #[expect(clippy::too_many_lines, reason = "a lot to test")]
   5683 #[test]
   5684 fn mldsa65_registration_deserialize_data_mismatch() {
   5685     let c_data_json = serde_json::json!({}).to_string();
   5686     let att_obj: [u8; 2064] = [
   5687         cbor::MAP_3,
   5688         cbor::TEXT_3,
   5689         b'f',
   5690         b'm',
   5691         b't',
   5692         cbor::TEXT_4,
   5693         b'n',
   5694         b'o',
   5695         b'n',
   5696         b'e',
   5697         cbor::TEXT_7,
   5698         b'a',
   5699         b't',
   5700         b't',
   5701         b'S',
   5702         b't',
   5703         b'm',
   5704         b't',
   5705         cbor::MAP_0,
   5706         cbor::TEXT_8,
   5707         b'a',
   5708         b'u',
   5709         b't',
   5710         b'h',
   5711         b'D',
   5712         b'a',
   5713         b't',
   5714         b'a',
   5715         cbor::BYTES_INFO_25,
   5716         7,
   5717         241,
   5718         // `rpIdHash`.
   5719         0,
   5720         0,
   5721         0,
   5722         0,
   5723         0,
   5724         0,
   5725         0,
   5726         0,
   5727         0,
   5728         0,
   5729         0,
   5730         0,
   5731         0,
   5732         0,
   5733         0,
   5734         0,
   5735         0,
   5736         0,
   5737         0,
   5738         0,
   5739         0,
   5740         0,
   5741         0,
   5742         0,
   5743         0,
   5744         0,
   5745         0,
   5746         0,
   5747         0,
   5748         0,
   5749         0,
   5750         0,
   5751         // `flags`.
   5752         0b0100_0101,
   5753         // `signCount`.
   5754         0,
   5755         0,
   5756         0,
   5757         0,
   5758         // `aaguid`.
   5759         0,
   5760         0,
   5761         0,
   5762         0,
   5763         0,
   5764         0,
   5765         0,
   5766         0,
   5767         0,
   5768         0,
   5769         0,
   5770         0,
   5771         0,
   5772         0,
   5773         0,
   5774         0,
   5775         // `credentialIdLength`.
   5776         0,
   5777         16,
   5778         // `credentialId`.
   5779         0,
   5780         0,
   5781         0,
   5782         0,
   5783         0,
   5784         0,
   5785         0,
   5786         0,
   5787         0,
   5788         0,
   5789         0,
   5790         0,
   5791         0,
   5792         0,
   5793         0,
   5794         0,
   5795         // ML-DSA-65 COSE key.
   5796         cbor::MAP_3,
   5797         KTY,
   5798         AKP,
   5799         ALG,
   5800         cbor::NEG_INFO_24,
   5801         MLDSA65,
   5802         // `pub`.
   5803         cbor::NEG_ONE,
   5804         cbor::BYTES_INFO_25,
   5805         7,
   5806         160,
   5807         // Encoded key.
   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         1,
   6981         1,
   6982         1,
   6983         1,
   6984         1,
   6985         1,
   6986         1,
   6987         1,
   6988         1,
   6989         1,
   6990         1,
   6991         1,
   6992         1,
   6993         1,
   6994         1,
   6995         1,
   6996         1,
   6997         1,
   6998         1,
   6999         1,
   7000         1,
   7001         1,
   7002         1,
   7003         1,
   7004         1,
   7005         1,
   7006         1,
   7007         1,
   7008         1,
   7009         1,
   7010         1,
   7011         1,
   7012         1,
   7013         1,
   7014         1,
   7015         1,
   7016         1,
   7017         1,
   7018         1,
   7019         1,
   7020         1,
   7021         1,
   7022         1,
   7023         1,
   7024         1,
   7025         1,
   7026         1,
   7027         1,
   7028         1,
   7029         1,
   7030         1,
   7031         1,
   7032         1,
   7033         1,
   7034         1,
   7035         1,
   7036         1,
   7037         1,
   7038         1,
   7039         1,
   7040         1,
   7041         1,
   7042         1,
   7043         1,
   7044         1,
   7045         1,
   7046         1,
   7047         1,
   7048         1,
   7049         1,
   7050         1,
   7051         1,
   7052         1,
   7053         1,
   7054         1,
   7055         1,
   7056         1,
   7057         1,
   7058         1,
   7059         1,
   7060         1,
   7061         1,
   7062         1,
   7063         1,
   7064         1,
   7065         1,
   7066         1,
   7067         1,
   7068         1,
   7069         1,
   7070         1,
   7071         1,
   7072         1,
   7073         1,
   7074         1,
   7075         1,
   7076         1,
   7077         1,
   7078         1,
   7079         1,
   7080         1,
   7081         1,
   7082         1,
   7083         1,
   7084         1,
   7085         1,
   7086         1,
   7087         1,
   7088         1,
   7089         1,
   7090         1,
   7091         1,
   7092         1,
   7093         1,
   7094         1,
   7095         1,
   7096         1,
   7097         1,
   7098         1,
   7099         1,
   7100         1,
   7101         1,
   7102         1,
   7103         1,
   7104         1,
   7105         1,
   7106         1,
   7107         1,
   7108         1,
   7109         1,
   7110         1,
   7111         1,
   7112         1,
   7113         1,
   7114         1,
   7115         1,
   7116         1,
   7117         1,
   7118         1,
   7119         1,
   7120         1,
   7121         1,
   7122         1,
   7123         1,
   7124         1,
   7125         1,
   7126         1,
   7127         1,
   7128         1,
   7129         1,
   7130         1,
   7131         1,
   7132         1,
   7133         1,
   7134         1,
   7135         1,
   7136         1,
   7137         1,
   7138         1,
   7139         1,
   7140         1,
   7141         1,
   7142         1,
   7143         1,
   7144         1,
   7145         1,
   7146         1,
   7147         1,
   7148         1,
   7149         1,
   7150         1,
   7151         1,
   7152         1,
   7153         1,
   7154         1,
   7155         1,
   7156         1,
   7157         1,
   7158         1,
   7159         1,
   7160         1,
   7161         1,
   7162         1,
   7163         1,
   7164         1,
   7165         1,
   7166         1,
   7167         1,
   7168         1,
   7169         1,
   7170         1,
   7171         1,
   7172         1,
   7173         1,
   7174         1,
   7175         1,
   7176         1,
   7177         1,
   7178         1,
   7179         1,
   7180         1,
   7181         1,
   7182         1,
   7183         1,
   7184         1,
   7185         1,
   7186         1,
   7187         1,
   7188         1,
   7189         1,
   7190         1,
   7191         1,
   7192         1,
   7193         1,
   7194         1,
   7195         1,
   7196         1,
   7197         1,
   7198         1,
   7199         1,
   7200         1,
   7201         1,
   7202         1,
   7203         1,
   7204         1,
   7205         1,
   7206         1,
   7207         1,
   7208         1,
   7209         1,
   7210         1,
   7211         1,
   7212         1,
   7213         1,
   7214         1,
   7215         1,
   7216         1,
   7217         1,
   7218         1,
   7219         1,
   7220         1,
   7221         1,
   7222         1,
   7223         1,
   7224         1,
   7225         1,
   7226         1,
   7227         1,
   7228         1,
   7229         1,
   7230         1,
   7231         1,
   7232         1,
   7233         1,
   7234         1,
   7235         1,
   7236         1,
   7237         1,
   7238         1,
   7239         1,
   7240         1,
   7241         1,
   7242         1,
   7243         1,
   7244         1,
   7245         1,
   7246         1,
   7247         1,
   7248         1,
   7249         1,
   7250         1,
   7251         1,
   7252         1,
   7253         1,
   7254         1,
   7255         1,
   7256         1,
   7257         1,
   7258         1,
   7259         1,
   7260         1,
   7261         1,
   7262         1,
   7263         1,
   7264         1,
   7265         1,
   7266         1,
   7267         1,
   7268         1,
   7269         1,
   7270         1,
   7271         1,
   7272         1,
   7273         1,
   7274         1,
   7275         1,
   7276         1,
   7277         1,
   7278         1,
   7279         1,
   7280         1,
   7281         1,
   7282         1,
   7283         1,
   7284         1,
   7285         1,
   7286         1,
   7287         1,
   7288         1,
   7289         1,
   7290         1,
   7291         1,
   7292         1,
   7293         1,
   7294         1,
   7295         1,
   7296         1,
   7297         1,
   7298         1,
   7299         1,
   7300         1,
   7301         1,
   7302         1,
   7303         1,
   7304         1,
   7305         1,
   7306         1,
   7307         1,
   7308         1,
   7309         1,
   7310         1,
   7311         1,
   7312         1,
   7313         1,
   7314         1,
   7315         1,
   7316         1,
   7317         1,
   7318         1,
   7319         1,
   7320         1,
   7321         1,
   7322         1,
   7323         1,
   7324         1,
   7325         1,
   7326         1,
   7327         1,
   7328         1,
   7329         1,
   7330         1,
   7331         1,
   7332         1,
   7333         1,
   7334         1,
   7335         1,
   7336         1,
   7337         1,
   7338         1,
   7339         1,
   7340         1,
   7341         1,
   7342         1,
   7343         1,
   7344         1,
   7345         1,
   7346         1,
   7347         1,
   7348         1,
   7349         1,
   7350         1,
   7351         1,
   7352         1,
   7353         1,
   7354         1,
   7355         1,
   7356         1,
   7357         1,
   7358         1,
   7359         1,
   7360         1,
   7361         1,
   7362         1,
   7363         1,
   7364         1,
   7365         1,
   7366         1,
   7367         1,
   7368         1,
   7369         1,
   7370         1,
   7371         1,
   7372         1,
   7373         1,
   7374         1,
   7375         1,
   7376         1,
   7377         1,
   7378         1,
   7379         1,
   7380         1,
   7381         1,
   7382         1,
   7383         1,
   7384         1,
   7385         1,
   7386         1,
   7387         1,
   7388         1,
   7389         1,
   7390         1,
   7391         1,
   7392         1,
   7393         1,
   7394         1,
   7395         1,
   7396         1,
   7397         1,
   7398         1,
   7399         1,
   7400         1,
   7401         1,
   7402         1,
   7403         1,
   7404         1,
   7405         1,
   7406         1,
   7407         1,
   7408         1,
   7409         1,
   7410         1,
   7411         1,
   7412         1,
   7413         1,
   7414         1,
   7415         1,
   7416         1,
   7417         1,
   7418         1,
   7419         1,
   7420         1,
   7421         1,
   7422         1,
   7423         1,
   7424         1,
   7425         1,
   7426         1,
   7427         1,
   7428         1,
   7429         1,
   7430         1,
   7431         1,
   7432         1,
   7433         1,
   7434         1,
   7435         1,
   7436         1,
   7437         1,
   7438         1,
   7439         1,
   7440         1,
   7441         1,
   7442         1,
   7443         1,
   7444         1,
   7445         1,
   7446         1,
   7447         1,
   7448         1,
   7449         1,
   7450         1,
   7451         1,
   7452         1,
   7453         1,
   7454         1,
   7455         1,
   7456         1,
   7457         1,
   7458         1,
   7459         1,
   7460         1,
   7461         1,
   7462         1,
   7463         1,
   7464         1,
   7465         1,
   7466         1,
   7467         1,
   7468         1,
   7469         1,
   7470         1,
   7471         1,
   7472         1,
   7473         1,
   7474         1,
   7475         1,
   7476         1,
   7477         1,
   7478         1,
   7479         1,
   7480         1,
   7481         1,
   7482         1,
   7483         1,
   7484         1,
   7485         1,
   7486         1,
   7487         1,
   7488         1,
   7489         1,
   7490         1,
   7491         1,
   7492         1,
   7493         1,
   7494         1,
   7495         1,
   7496         1,
   7497         1,
   7498         1,
   7499         1,
   7500         1,
   7501         1,
   7502         1,
   7503         1,
   7504         1,
   7505         1,
   7506         1,
   7507         1,
   7508         1,
   7509         1,
   7510         1,
   7511         1,
   7512         1,
   7513         1,
   7514         1,
   7515         1,
   7516         1,
   7517         1,
   7518         1,
   7519         1,
   7520         1,
   7521         1,
   7522         1,
   7523         1,
   7524         1,
   7525         1,
   7526         1,
   7527         1,
   7528         1,
   7529         1,
   7530         1,
   7531         1,
   7532         1,
   7533         1,
   7534         1,
   7535         1,
   7536         1,
   7537         1,
   7538         1,
   7539         1,
   7540         1,
   7541         1,
   7542         1,
   7543         1,
   7544         1,
   7545         1,
   7546         1,
   7547         1,
   7548         1,
   7549         1,
   7550         1,
   7551         1,
   7552         1,
   7553         1,
   7554         1,
   7555         1,
   7556         1,
   7557         1,
   7558         1,
   7559         1,
   7560         1,
   7561         1,
   7562         1,
   7563         1,
   7564         1,
   7565         1,
   7566         1,
   7567         1,
   7568         1,
   7569         1,
   7570         1,
   7571         1,
   7572         1,
   7573         1,
   7574         1,
   7575         1,
   7576         1,
   7577         1,
   7578         1,
   7579         1,
   7580         1,
   7581         1,
   7582         1,
   7583         1,
   7584         1,
   7585         1,
   7586         1,
   7587         1,
   7588         1,
   7589         1,
   7590         1,
   7591         1,
   7592         1,
   7593         1,
   7594         1,
   7595         1,
   7596         1,
   7597         1,
   7598         1,
   7599         1,
   7600         1,
   7601         1,
   7602         1,
   7603         1,
   7604         1,
   7605         1,
   7606         1,
   7607         1,
   7608         1,
   7609         1,
   7610         1,
   7611         1,
   7612         1,
   7613         1,
   7614         1,
   7615         1,
   7616         1,
   7617         1,
   7618         1,
   7619         1,
   7620         1,
   7621         1,
   7622         1,
   7623         1,
   7624         1,
   7625         1,
   7626         1,
   7627         1,
   7628         1,
   7629         1,
   7630         1,
   7631         1,
   7632         1,
   7633         1,
   7634         1,
   7635         1,
   7636         1,
   7637         1,
   7638         1,
   7639         1,
   7640         1,
   7641         1,
   7642         1,
   7643         1,
   7644         1,
   7645         1,
   7646         1,
   7647         1,
   7648         1,
   7649         1,
   7650         1,
   7651         1,
   7652         1,
   7653         1,
   7654         1,
   7655         1,
   7656         1,
   7657         1,
   7658         1,
   7659         1,
   7660         1,
   7661         1,
   7662         1,
   7663         1,
   7664         1,
   7665         1,
   7666         1,
   7667         1,
   7668         1,
   7669         1,
   7670         1,
   7671         1,
   7672         1,
   7673         1,
   7674         1,
   7675         1,
   7676         1,
   7677         1,
   7678         1,
   7679         1,
   7680         1,
   7681         1,
   7682         1,
   7683         1,
   7684         1,
   7685         1,
   7686         1,
   7687         1,
   7688         1,
   7689         1,
   7690         1,
   7691         1,
   7692         1,
   7693         1,
   7694         1,
   7695         1,
   7696         1,
   7697         1,
   7698         1,
   7699         1,
   7700         1,
   7701         1,
   7702         1,
   7703         1,
   7704         1,
   7705         1,
   7706         1,
   7707         1,
   7708         1,
   7709         1,
   7710         1,
   7711         1,
   7712         1,
   7713         1,
   7714         1,
   7715         1,
   7716         1,
   7717         1,
   7718         1,
   7719         1,
   7720         1,
   7721         1,
   7722         1,
   7723         1,
   7724         1,
   7725         1,
   7726         1,
   7727         1,
   7728         1,
   7729         1,
   7730         1,
   7731         1,
   7732         1,
   7733         1,
   7734         1,
   7735         1,
   7736         1,
   7737         1,
   7738         1,
   7739         1,
   7740         1,
   7741         1,
   7742         1,
   7743         1,
   7744         1,
   7745         1,
   7746         1,
   7747         1,
   7748         1,
   7749         1,
   7750         1,
   7751         1,
   7752         1,
   7753         1,
   7754         1,
   7755         1,
   7756         1,
   7757         1,
   7758         1,
   7759         1,
   7760     ];
   7761     let pub_key = MlDsaVerKey::<MlDsa65>::decode(&[1u8; 1952].into())
   7762         .to_public_key_der()
   7763         .unwrap();
   7764     let att_obj_len = att_obj.len();
   7765     let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
   7766     let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 2033..]);
   7767     let b64_key = base64url_nopad::encode(pub_key.as_bytes());
   7768     let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
   7769     // Base case is valid.
   7770     assert!(
   7771         serde_json::from_str::<RegistrationRelaxed>(
   7772             serde_json::json!({
   7773                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7774                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7775                 "response": {
   7776                     "clientDataJSON": b64_cdata_json,
   7777                     "authenticatorData": b64_adata,
   7778                     "transports": [],
   7779                     "publicKey": b64_key,
   7780                     "publicKeyAlgorithm": -49i8,
   7781                     "attestationObject": b64_aobj,
   7782                 },
   7783                 "clientExtensionResults": {},
   7784                 "type": "public-key"
   7785             })
   7786             .to_string()
   7787             .as_str()
   7788         )
   7789         .is_ok_and(
   7790             |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
   7791                 && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
   7792                 && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
   7793                     == *Sha256::digest(c_data_json.as_bytes())
   7794                 && reg.0.response.transports.is_empty()
   7795                 && matches!(
   7796                     reg.0.authenticator_attachment,
   7797                     AuthenticatorAttachment::None
   7798                 )
   7799                 && reg.0.client_extension_results.cred_props.is_none()
   7800                 && reg.0.client_extension_results.prf.is_none()
   7801         )
   7802     );
   7803     // `publicKeyAlgorithm` mismatch.
   7804     let mut err = Error::invalid_value(
   7805         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
   7806         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa65).as_str()
   7807     )
   7808     .to_string().into_bytes();
   7809     assert_eq!(
   7810         serde_json::from_str::<RegistrationRelaxed>(
   7811             serde_json::json!({
   7812                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7813                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7814                 "response": {
   7815                     "clientDataJSON": b64_cdata_json,
   7816                     "authenticatorData": b64_adata,
   7817                     "transports": [],
   7818                     "publicKey": b64_key,
   7819                     "publicKeyAlgorithm": -8i8,
   7820                     "attestationObject": b64_aobj,
   7821                 },
   7822                 "clientExtensionResults": {},
   7823                 "type": "public-key"
   7824             })
   7825             .to_string()
   7826             .as_str()
   7827         )
   7828         .unwrap_err()
   7829         .to_string()
   7830         .into_bytes()
   7831         .get(..err.len()),
   7832         Some(err.as_slice())
   7833     );
   7834     // Missing `publicKeyAlgorithm`.
   7835     drop(
   7836         serde_json::from_str::<RegistrationRelaxed>(
   7837             serde_json::json!({
   7838                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7839                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7840                 "response": {
   7841                     "clientDataJSON": b64_cdata_json,
   7842                     "authenticatorData": b64_adata,
   7843                     "transports": [],
   7844                     "publicKey": b64_key,
   7845                     "attestationObject": b64_aobj,
   7846                 },
   7847                 "clientExtensionResults": {},
   7848                 "type": "public-key"
   7849             })
   7850             .to_string()
   7851             .as_str(),
   7852         )
   7853         .unwrap(),
   7854     );
   7855     // `null` `publicKeyAlgorithm`.
   7856     drop(
   7857         serde_json::from_str::<RegistrationRelaxed>(
   7858             serde_json::json!({
   7859                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7860                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7861                 "response": {
   7862                     "clientDataJSON": b64_cdata_json,
   7863                     "authenticatorData": b64_adata,
   7864                     "transports": [],
   7865                     "publicKey": b64_key,
   7866                     "publicKeyAlgorithm": null,
   7867                     "attestationObject": b64_aobj,
   7868                 },
   7869                 "clientExtensionResults": {},
   7870                 "type": "public-key"
   7871             })
   7872             .to_string()
   7873             .as_str(),
   7874         )
   7875         .unwrap(),
   7876     );
   7877     // `publicKey` mismatch.
   7878     let bad_pub_key = MlDsaVerKey::<MlDsa65>::decode(&[2; 1952].into());
   7879     err = Error::invalid_value(
   7880         Unexpected::Bytes([0; 32].as_slice()),
   7881         &format!(
   7882             "DER-encoded public key to match the public key within the attestation object: MlDsa65(MlDsa65PubKey({:?}))",
   7883             &[1u8; 1952]
   7884         )
   7885         .as_str(),
   7886     )
   7887     .to_string().into_bytes();
   7888     assert_eq!(serde_json::from_str::<RegistrationRelaxed>(
   7889         serde_json::json!({
   7890             "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7891             "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7892             "response": {
   7893                 "clientDataJSON": b64_cdata_json,
   7894                 "authenticatorData": b64_adata,
   7895                 "transports": [],
   7896                 "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
   7897                 "publicKeyAlgorithm": -49i8,
   7898                 "attestationObject": b64_aobj,
   7899             },
   7900             "clientExtensionResults": {},
   7901             "type": "public-key"
   7902         })
   7903         .to_string()
   7904         .as_str()
   7905         )
   7906         .unwrap_err().to_string().into_bytes().get(..err.len()),
   7907         Some(err.as_slice())
   7908     );
   7909     // Missing `publicKey` is allowed when not using EdDSA, ES256, or RS256.
   7910     assert!(
   7911         serde_json::from_str::<RegistrationRelaxed>(
   7912             serde_json::json!({
   7913                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7914                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7915                 "response": {
   7916                     "clientDataJSON": b64_cdata_json,
   7917                     "authenticatorData": b64_adata,
   7918                     "transports": [],
   7919                     "publicKeyAlgorithm": -49i8,
   7920                     "attestationObject": b64_aobj,
   7921                 },
   7922                 "clientExtensionResults": {},
   7923                 "type": "public-key"
   7924             })
   7925             .to_string()
   7926             .as_str()
   7927         )
   7928         .is_ok()
   7929     );
   7930     // `publicKeyAlgorithm` mismatch when `publicKey` does not exist.
   7931     err = Error::invalid_value(
   7932         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   7933         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa65).as_str()
   7934     )
   7935     .to_string().into_bytes();
   7936     assert_eq!(
   7937         serde_json::from_str::<RegistrationRelaxed>(
   7938             serde_json::json!({
   7939                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7940                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7941                 "response": {
   7942                     "clientDataJSON": b64_cdata_json,
   7943                     "authenticatorData": b64_adata,
   7944                     "transports": [],
   7945                     "publicKeyAlgorithm": -7i8,
   7946                     "attestationObject": b64_aobj,
   7947                 },
   7948                 "clientExtensionResults": {},
   7949                 "type": "public-key"
   7950             })
   7951             .to_string()
   7952             .as_str()
   7953         )
   7954         .unwrap_err()
   7955         .to_string()
   7956         .into_bytes()
   7957         .get(..err.len()),
   7958         Some(err.as_slice())
   7959     );
   7960     // `null` `publicKey` is allowed when not using EdDSA, ES256, or RS256.
   7961     assert!(
   7962         serde_json::from_str::<RegistrationRelaxed>(
   7963             serde_json::json!({
   7964                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7965                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7966                 "response": {
   7967                     "clientDataJSON": b64_cdata_json,
   7968                     "authenticatorData": b64_adata,
   7969                     "transports": [],
   7970                     "publicKey": null,
   7971                     "publicKeyAlgorithm": -49i8,
   7972                     "attestationObject": b64_aobj,
   7973                 },
   7974                 "clientExtensionResults": {},
   7975                 "type": "public-key"
   7976             })
   7977             .to_string()
   7978             .as_str()
   7979         )
   7980         .is_ok()
   7981     );
   7982     // `publicKeyAlgorithm` mismatch when `publicKey` is null.
   7983     err = Error::invalid_value(
   7984         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   7985         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa65).as_str()
   7986     )
   7987     .to_string().into_bytes();
   7988     assert_eq!(
   7989         serde_json::from_str::<RegistrationRelaxed>(
   7990             serde_json::json!({
   7991                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   7992                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   7993                 "response": {
   7994                     "clientDataJSON": b64_cdata_json,
   7995                     "authenticatorData": b64_adata,
   7996                     "transports": [],
   7997                     "publicKey": null,
   7998                     "publicKeyAlgorithm": -7i8,
   7999                     "attestationObject": b64_aobj,
   8000                 },
   8001                 "clientExtensionResults": {},
   8002                 "type": "public-key"
   8003             })
   8004             .to_string()
   8005             .as_str()
   8006         )
   8007         .unwrap_err()
   8008         .to_string()
   8009         .into_bytes()
   8010         .get(..err.len()),
   8011         Some(err.as_slice())
   8012     );
   8013 }
   8014 #[expect(
   8015     clippy::assertions_on_result_states,
   8016     clippy::unwrap_used,
   8017     reason = "OK in tests"
   8018 )]
   8019 #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
   8020 #[expect(clippy::too_many_lines, reason = "a lot to test")]
   8021 #[test]
   8022 fn mldsa44_registration_deserialize_data_mismatch() {
   8023     let c_data_json = serde_json::json!({}).to_string();
   8024     let att_obj: [u8; 1424] = [
   8025         cbor::MAP_3,
   8026         cbor::TEXT_3,
   8027         b'f',
   8028         b'm',
   8029         b't',
   8030         cbor::TEXT_4,
   8031         b'n',
   8032         b'o',
   8033         b'n',
   8034         b'e',
   8035         cbor::TEXT_7,
   8036         b'a',
   8037         b't',
   8038         b't',
   8039         b'S',
   8040         b't',
   8041         b'm',
   8042         b't',
   8043         cbor::MAP_0,
   8044         cbor::TEXT_8,
   8045         b'a',
   8046         b'u',
   8047         b't',
   8048         b'h',
   8049         b'D',
   8050         b'a',
   8051         b't',
   8052         b'a',
   8053         cbor::BYTES_INFO_25,
   8054         5,
   8055         113,
   8056         // `rpIdHash`.
   8057         0,
   8058         0,
   8059         0,
   8060         0,
   8061         0,
   8062         0,
   8063         0,
   8064         0,
   8065         0,
   8066         0,
   8067         0,
   8068         0,
   8069         0,
   8070         0,
   8071         0,
   8072         0,
   8073         0,
   8074         0,
   8075         0,
   8076         0,
   8077         0,
   8078         0,
   8079         0,
   8080         0,
   8081         0,
   8082         0,
   8083         0,
   8084         0,
   8085         0,
   8086         0,
   8087         0,
   8088         0,
   8089         // `flags`.
   8090         0b0100_0101,
   8091         // `signCount`.
   8092         0,
   8093         0,
   8094         0,
   8095         0,
   8096         // `aaguid`.
   8097         0,
   8098         0,
   8099         0,
   8100         0,
   8101         0,
   8102         0,
   8103         0,
   8104         0,
   8105         0,
   8106         0,
   8107         0,
   8108         0,
   8109         0,
   8110         0,
   8111         0,
   8112         0,
   8113         // `credentialIdLength`.
   8114         0,
   8115         16,
   8116         // `credentialId`.
   8117         0,
   8118         0,
   8119         0,
   8120         0,
   8121         0,
   8122         0,
   8123         0,
   8124         0,
   8125         0,
   8126         0,
   8127         0,
   8128         0,
   8129         0,
   8130         0,
   8131         0,
   8132         0,
   8133         // ML-DSA-44 COSE key.
   8134         cbor::MAP_3,
   8135         KTY,
   8136         AKP,
   8137         ALG,
   8138         cbor::NEG_INFO_24,
   8139         MLDSA44,
   8140         // `pub`.
   8141         cbor::NEG_ONE,
   8142         cbor::BYTES_INFO_25,
   8143         5,
   8144         32,
   8145         // Encoded key.
   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         1,
   9330         1,
   9331         1,
   9332         1,
   9333         1,
   9334         1,
   9335         1,
   9336         1,
   9337         1,
   9338         1,
   9339         1,
   9340         1,
   9341         1,
   9342         1,
   9343         1,
   9344         1,
   9345         1,
   9346         1,
   9347         1,
   9348         1,
   9349         1,
   9350         1,
   9351         1,
   9352         1,
   9353         1,
   9354         1,
   9355         1,
   9356         1,
   9357         1,
   9358         1,
   9359         1,
   9360         1,
   9361         1,
   9362         1,
   9363         1,
   9364         1,
   9365         1,
   9366         1,
   9367         1,
   9368         1,
   9369         1,
   9370         1,
   9371         1,
   9372         1,
   9373         1,
   9374         1,
   9375         1,
   9376         1,
   9377         1,
   9378         1,
   9379         1,
   9380         1,
   9381         1,
   9382         1,
   9383         1,
   9384         1,
   9385         1,
   9386         1,
   9387         1,
   9388         1,
   9389         1,
   9390         1,
   9391         1,
   9392         1,
   9393         1,
   9394         1,
   9395         1,
   9396         1,
   9397         1,
   9398         1,
   9399         1,
   9400         1,
   9401         1,
   9402         1,
   9403         1,
   9404         1,
   9405         1,
   9406         1,
   9407         1,
   9408         1,
   9409         1,
   9410         1,
   9411         1,
   9412         1,
   9413         1,
   9414         1,
   9415         1,
   9416         1,
   9417         1,
   9418         1,
   9419         1,
   9420         1,
   9421         1,
   9422         1,
   9423         1,
   9424         1,
   9425         1,
   9426         1,
   9427         1,
   9428         1,
   9429         1,
   9430         1,
   9431         1,
   9432         1,
   9433         1,
   9434         1,
   9435         1,
   9436         1,
   9437         1,
   9438         1,
   9439         1,
   9440         1,
   9441         1,
   9442         1,
   9443         1,
   9444         1,
   9445         1,
   9446         1,
   9447         1,
   9448         1,
   9449         1,
   9450         1,
   9451         1,
   9452         1,
   9453         1,
   9454         1,
   9455         1,
   9456         1,
   9457         1,
   9458     ];
   9459     let pub_key = MlDsaVerKey::<MlDsa44>::decode(&[1u8; 1312].into())
   9460         .to_public_key_der()
   9461         .unwrap();
   9462     let att_obj_len = att_obj.len();
   9463     let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
   9464     let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 1393..]);
   9465     let b64_key = base64url_nopad::encode(pub_key.as_bytes());
   9466     let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
   9467     // Base case is valid.
   9468     assert!(
   9469         serde_json::from_str::<RegistrationRelaxed>(
   9470             serde_json::json!({
   9471                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9472                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9473                 "response": {
   9474                     "clientDataJSON": b64_cdata_json,
   9475                     "authenticatorData": b64_adata,
   9476                     "transports": [],
   9477                     "publicKey": b64_key,
   9478                     "publicKeyAlgorithm": -48i8,
   9479                     "attestationObject": b64_aobj,
   9480                 },
   9481                 "clientExtensionResults": {},
   9482                 "type": "public-key"
   9483             })
   9484             .to_string()
   9485             .as_str()
   9486         )
   9487         .is_ok_and(
   9488             |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
   9489                 && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
   9490                 && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
   9491                     == *Sha256::digest(c_data_json.as_bytes())
   9492                 && reg.0.response.transports.is_empty()
   9493                 && matches!(
   9494                     reg.0.authenticator_attachment,
   9495                     AuthenticatorAttachment::None
   9496                 )
   9497                 && reg.0.client_extension_results.cred_props.is_none()
   9498                 && reg.0.client_extension_results.prf.is_none()
   9499         )
   9500     );
   9501     // `publicKeyAlgorithm` mismatch.
   9502     let mut err = Error::invalid_value(
   9503         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
   9504         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa44).as_str()
   9505     )
   9506     .to_string().into_bytes();
   9507     assert_eq!(
   9508         serde_json::from_str::<RegistrationRelaxed>(
   9509             serde_json::json!({
   9510                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9511                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9512                 "response": {
   9513                     "clientDataJSON": b64_cdata_json,
   9514                     "authenticatorData": b64_adata,
   9515                     "transports": [],
   9516                     "publicKey": b64_key,
   9517                     "publicKeyAlgorithm": -8i8,
   9518                     "attestationObject": b64_aobj,
   9519                 },
   9520                 "clientExtensionResults": {},
   9521                 "type": "public-key"
   9522             })
   9523             .to_string()
   9524             .as_str()
   9525         )
   9526         .unwrap_err()
   9527         .to_string()
   9528         .into_bytes()
   9529         .get(..err.len()),
   9530         Some(err.as_slice())
   9531     );
   9532     // Missing `publicKeyAlgorithm`.
   9533     drop(
   9534         serde_json::from_str::<RegistrationRelaxed>(
   9535             serde_json::json!({
   9536                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9537                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9538                 "response": {
   9539                     "clientDataJSON": b64_cdata_json,
   9540                     "authenticatorData": b64_adata,
   9541                     "transports": [],
   9542                     "publicKey": b64_key,
   9543                     "attestationObject": b64_aobj,
   9544                 },
   9545                 "clientExtensionResults": {},
   9546                 "type": "public-key"
   9547             })
   9548             .to_string()
   9549             .as_str(),
   9550         )
   9551         .unwrap(),
   9552     );
   9553     // `null` `publicKeyAlgorithm`.
   9554     drop(
   9555         serde_json::from_str::<RegistrationRelaxed>(
   9556             serde_json::json!({
   9557                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9558                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9559                 "response": {
   9560                     "clientDataJSON": b64_cdata_json,
   9561                     "authenticatorData": b64_adata,
   9562                     "transports": [],
   9563                     "publicKey": b64_key,
   9564                     "publicKeyAlgorithm": null,
   9565                     "attestationObject": b64_aobj,
   9566                 },
   9567                 "clientExtensionResults": {},
   9568                 "type": "public-key"
   9569             })
   9570             .to_string()
   9571             .as_str(),
   9572         )
   9573         .unwrap(),
   9574     );
   9575     // `publicKey` mismatch.
   9576     let bad_pub_key = MlDsaVerKey::<MlDsa44>::decode(&[2; 1312].into());
   9577     err = Error::invalid_value(
   9578         Unexpected::Bytes([0; 32].as_slice()),
   9579         &format!(
   9580             "DER-encoded public key to match the public key within the attestation object: MlDsa44(MlDsa44PubKey({:?}))",
   9581             &[1u8; 1312]
   9582         )
   9583         .as_str(),
   9584     )
   9585     .to_string().into_bytes();
   9586     assert_eq!(serde_json::from_str::<RegistrationRelaxed>(
   9587         serde_json::json!({
   9588             "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9589             "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9590             "response": {
   9591                 "clientDataJSON": b64_cdata_json,
   9592                 "authenticatorData": b64_adata,
   9593                 "transports": [],
   9594                 "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
   9595                 "publicKeyAlgorithm": -48i8,
   9596                 "attestationObject": b64_aobj,
   9597             },
   9598             "clientExtensionResults": {},
   9599             "type": "public-key"
   9600         })
   9601         .to_string()
   9602         .as_str()
   9603         )
   9604         .unwrap_err().to_string().into_bytes().get(..err.len()),
   9605         Some(err.as_slice())
   9606     );
   9607     // Missing `publicKey` is allowed when not using EdDSA, ES256, or RS256.
   9608     assert!(
   9609         serde_json::from_str::<RegistrationRelaxed>(
   9610             serde_json::json!({
   9611                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9612                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9613                 "response": {
   9614                     "clientDataJSON": b64_cdata_json,
   9615                     "authenticatorData": b64_adata,
   9616                     "transports": [],
   9617                     "publicKeyAlgorithm": -48i8,
   9618                     "attestationObject": b64_aobj,
   9619                 },
   9620                 "clientExtensionResults": {},
   9621                 "type": "public-key"
   9622             })
   9623             .to_string()
   9624             .as_str()
   9625         )
   9626         .is_ok()
   9627     );
   9628     // `publicKeyAlgorithm` mismatch when `publicKey` does not exist.
   9629     err = Error::invalid_value(
   9630         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   9631         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa44).as_str()
   9632     )
   9633     .to_string().into_bytes();
   9634     assert_eq!(
   9635         serde_json::from_str::<RegistrationRelaxed>(
   9636             serde_json::json!({
   9637                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9638                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9639                 "response": {
   9640                     "clientDataJSON": b64_cdata_json,
   9641                     "authenticatorData": b64_adata,
   9642                     "transports": [],
   9643                     "publicKeyAlgorithm": -7i8,
   9644                     "attestationObject": b64_aobj,
   9645                 },
   9646                 "clientExtensionResults": {},
   9647                 "type": "public-key"
   9648             })
   9649             .to_string()
   9650             .as_str()
   9651         )
   9652         .unwrap_err()
   9653         .to_string()
   9654         .into_bytes()
   9655         .get(..err.len()),
   9656         Some(err.as_slice())
   9657     );
   9658     // `null` `publicKey` is allowed when not using EdDSA, ES256, or RS256.
   9659     assert!(
   9660         serde_json::from_str::<RegistrationRelaxed>(
   9661             serde_json::json!({
   9662                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9663                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9664                 "response": {
   9665                     "clientDataJSON": b64_cdata_json,
   9666                     "authenticatorData": b64_adata,
   9667                     "transports": [],
   9668                     "publicKey": null,
   9669                     "publicKeyAlgorithm": -48i8,
   9670                     "attestationObject": b64_aobj,
   9671                 },
   9672                 "clientExtensionResults": {},
   9673                 "type": "public-key"
   9674             })
   9675             .to_string()
   9676             .as_str()
   9677         )
   9678         .is_ok()
   9679     );
   9680     // `publicKeyAlgorithm` mismatch when `publicKey` is null.
   9681     err = Error::invalid_value(
   9682         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
   9683         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Mldsa44).as_str()
   9684     )
   9685     .to_string().into_bytes();
   9686     assert_eq!(
   9687         serde_json::from_str::<RegistrationRelaxed>(
   9688             serde_json::json!({
   9689                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9690                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9691                 "response": {
   9692                     "clientDataJSON": b64_cdata_json,
   9693                     "authenticatorData": b64_adata,
   9694                     "transports": [],
   9695                     "publicKey": null,
   9696                     "publicKeyAlgorithm": -7i8,
   9697                     "attestationObject": b64_aobj,
   9698                 },
   9699                 "clientExtensionResults": {},
   9700                 "type": "public-key"
   9701             })
   9702             .to_string()
   9703             .as_str()
   9704         )
   9705         .unwrap_err()
   9706         .to_string()
   9707         .into_bytes()
   9708         .get(..err.len()),
   9709         Some(err.as_slice())
   9710     );
   9711 }
   9712 #[expect(clippy::unwrap_used, reason = "OK in tests")]
   9713 #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
   9714 #[expect(clippy::too_many_lines, reason = "a lot to test")]
   9715 #[test]
   9716 fn es256_registration_deserialize_data_mismatch() {
   9717     let c_data_json = serde_json::json!({}).to_string();
   9718     let mut att_obj: [u8; 178] = [
   9719         cbor::MAP_3,
   9720         cbor::TEXT_3,
   9721         b'f',
   9722         b'm',
   9723         b't',
   9724         cbor::TEXT_4,
   9725         b'n',
   9726         b'o',
   9727         b'n',
   9728         b'e',
   9729         cbor::TEXT_7,
   9730         b'a',
   9731         b't',
   9732         b't',
   9733         b'S',
   9734         b't',
   9735         b'm',
   9736         b't',
   9737         cbor::MAP_0,
   9738         cbor::TEXT_8,
   9739         b'a',
   9740         b'u',
   9741         b't',
   9742         b'h',
   9743         b'D',
   9744         b'a',
   9745         b't',
   9746         b'a',
   9747         cbor::BYTES_INFO_24,
   9748         148,
   9749         // `rpIdHash`.
   9750         0,
   9751         0,
   9752         0,
   9753         0,
   9754         0,
   9755         0,
   9756         0,
   9757         0,
   9758         0,
   9759         0,
   9760         0,
   9761         0,
   9762         0,
   9763         0,
   9764         0,
   9765         0,
   9766         0,
   9767         0,
   9768         0,
   9769         0,
   9770         0,
   9771         0,
   9772         0,
   9773         0,
   9774         0,
   9775         0,
   9776         0,
   9777         0,
   9778         0,
   9779         0,
   9780         0,
   9781         0,
   9782         // `flags`.
   9783         0b0100_0101,
   9784         // `signCount`.
   9785         0,
   9786         0,
   9787         0,
   9788         0,
   9789         // `aaguid`.
   9790         0,
   9791         0,
   9792         0,
   9793         0,
   9794         0,
   9795         0,
   9796         0,
   9797         0,
   9798         0,
   9799         0,
   9800         0,
   9801         0,
   9802         0,
   9803         0,
   9804         0,
   9805         0,
   9806         // `credentialIdLength`.
   9807         0,
   9808         16,
   9809         // `credentialId`.
   9810         0,
   9811         0,
   9812         0,
   9813         0,
   9814         0,
   9815         0,
   9816         0,
   9817         0,
   9818         0,
   9819         0,
   9820         0,
   9821         0,
   9822         0,
   9823         0,
   9824         0,
   9825         0,
   9826         // P-256 COSE key.
   9827         cbor::MAP_5,
   9828         KTY,
   9829         EC2,
   9830         ALG,
   9831         ES256,
   9832         // `crv`.
   9833         cbor::NEG_ONE,
   9834         // `P-256`.
   9835         cbor::ONE,
   9836         // `x`.
   9837         cbor::NEG_TWO,
   9838         cbor::BYTES_INFO_24,
   9839         32,
   9840         // x-coordinate. This will be overwritten later.
   9841         0,
   9842         0,
   9843         0,
   9844         0,
   9845         0,
   9846         0,
   9847         0,
   9848         0,
   9849         0,
   9850         0,
   9851         0,
   9852         0,
   9853         0,
   9854         0,
   9855         0,
   9856         0,
   9857         0,
   9858         0,
   9859         0,
   9860         0,
   9861         0,
   9862         0,
   9863         0,
   9864         0,
   9865         0,
   9866         0,
   9867         0,
   9868         0,
   9869         0,
   9870         0,
   9871         0,
   9872         0,
   9873         // `y`.
   9874         cbor::NEG_THREE,
   9875         cbor::BYTES_INFO_24,
   9876         32,
   9877         // y-coordinate. This will be overwritten later.
   9878         0,
   9879         0,
   9880         0,
   9881         0,
   9882         0,
   9883         0,
   9884         0,
   9885         0,
   9886         0,
   9887         0,
   9888         0,
   9889         0,
   9890         0,
   9891         0,
   9892         0,
   9893         0,
   9894         0,
   9895         0,
   9896         0,
   9897         0,
   9898         0,
   9899         0,
   9900         0,
   9901         0,
   9902         0,
   9903         0,
   9904         0,
   9905         0,
   9906         0,
   9907         0,
   9908         0,
   9909         0,
   9910     ];
   9911     let key = P256Key::from_bytes(
   9912         &[
   9913             137, 133, 36, 206, 163, 47, 255, 5, 76, 144, 163, 141, 40, 109, 108, 240, 246, 115,
   9914             178, 237, 169, 68, 6, 129, 92, 21, 238, 127, 55, 158, 207, 95,
   9915         ]
   9916         .into(),
   9917     )
   9918     .unwrap()
   9919     .public_key();
   9920     let enc_key = key.to_sec1_point(false);
   9921     let pub_key = key.to_public_key_der().unwrap();
   9922     let att_obj_len = att_obj.len();
   9923     let x_start = att_obj_len - 67;
   9924     let y_meta_start = x_start + 32;
   9925     let y_start = y_meta_start + 3;
   9926     att_obj[x_start..y_meta_start].copy_from_slice(enc_key.x().unwrap());
   9927     att_obj[y_start..].copy_from_slice(enc_key.y().unwrap());
   9928     let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
   9929     let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 148..]);
   9930     let b64_key = base64url_nopad::encode(pub_key.as_bytes());
   9931     let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
   9932     // Base case is valid.
   9933     assert!(
   9934         serde_json::from_str::<RegistrationRelaxed>(
   9935             serde_json::json!({
   9936                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9937                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9938                 "response": {
   9939                     "clientDataJSON": b64_cdata_json,
   9940                     "authenticatorData": b64_adata,
   9941                     "transports": [],
   9942                     "publicKey": b64_key,
   9943                     "publicKeyAlgorithm": -7i8,
   9944                     "attestationObject": b64_aobj,
   9945                 },
   9946                 "clientExtensionResults": {},
   9947                 "type": "public-key"
   9948             })
   9949             .to_string()
   9950             .as_str()
   9951         )
   9952         .is_ok_and(
   9953             |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
   9954                 && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
   9955                 && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
   9956                     == *Sha256::digest(c_data_json.as_bytes())
   9957                 && reg.0.response.transports.is_empty()
   9958                 && matches!(
   9959                     reg.0.authenticator_attachment,
   9960                     AuthenticatorAttachment::None
   9961                 )
   9962                 && reg.0.client_extension_results.cred_props.is_none()
   9963                 && reg.0.client_extension_results.prf.is_none()
   9964         )
   9965     );
   9966     // `publicKeyAlgorithm` mismatch.
   9967     let mut err = Error::invalid_value(
   9968         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
   9969         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Es256).as_str()
   9970     )
   9971     .to_string().into_bytes();
   9972     assert_eq!(
   9973         serde_json::from_str::<RegistrationRelaxed>(
   9974             serde_json::json!({
   9975                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
   9976                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
   9977                 "response": {
   9978                     "clientDataJSON": b64_cdata_json,
   9979                     "authenticatorData": b64_adata,
   9980                     "transports": [],
   9981                     "publicKey": b64_key,
   9982                     "publicKeyAlgorithm": -8i8,
   9983                     "attestationObject": b64_aobj,
   9984                 },
   9985                 "clientExtensionResults": {},
   9986                 "type": "public-key"
   9987             })
   9988             .to_string()
   9989             .as_str()
   9990         )
   9991         .unwrap_err()
   9992         .to_string()
   9993         .into_bytes()
   9994         .get(..err.len()),
   9995         Some(err.as_slice())
   9996     );
   9997     // Missing `publicKeyAlgorithm`.
   9998     drop(
   9999         serde_json::from_str::<RegistrationRelaxed>(
  10000             serde_json::json!({
  10001                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10002                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10003                 "response": {
  10004                     "clientDataJSON": b64_cdata_json,
  10005                     "authenticatorData": b64_adata,
  10006                     "transports": [],
  10007                     "publicKey": b64_key,
  10008                     "attestationObject": b64_aobj,
  10009                 },
  10010                 "clientExtensionResults": {},
  10011                 "type": "public-key"
  10012             })
  10013             .to_string()
  10014             .as_str(),
  10015         )
  10016         .unwrap(),
  10017     );
  10018     // `null` `publicKeyAlgorithm`.
  10019     drop(
  10020         serde_json::from_str::<RegistrationRelaxed>(
  10021             serde_json::json!({
  10022                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10023                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10024                 "response": {
  10025                     "clientDataJSON": b64_cdata_json,
  10026                     "authenticatorData": b64_adata,
  10027                     "transports": [],
  10028                     "publicKey": b64_key,
  10029                     "publicKeyAlgorithm": null,
  10030                     "attestationObject": b64_aobj,
  10031                 },
  10032                 "clientExtensionResults": {},
  10033                 "type": "public-key"
  10034             })
  10035             .to_string()
  10036             .as_str(),
  10037         )
  10038         .unwrap(),
  10039     );
  10040     // `publicKey` mismatch.
  10041     let bad_pub_key = P256PubKey::from_sec1_point(&P256Pt::from_affine_coordinates(
  10042         &[
  10043             66, 71, 188, 41, 125, 2, 226, 44, 148, 62, 63, 190, 172, 64, 33, 214, 6, 37, 148, 23,
  10044             240, 235, 203, 84, 112, 219, 232, 197, 54, 182, 17, 235,
  10045         ]
  10046         .into(),
  10047         &[
  10048             22, 172, 123, 13, 170, 242, 217, 248, 193, 209, 206, 163, 92, 4, 162, 168, 113, 63, 2,
  10049             117, 16, 223, 239, 196, 109, 179, 10, 130, 43, 213, 205, 92,
  10050         ]
  10051         .into(),
  10052         false,
  10053     ))
  10054     .unwrap();
  10055     err = Error::invalid_value(
  10056         Unexpected::Bytes([0; 32].as_slice()),
  10057         &format!(
  10058             "DER-encoded public key to match the public key within the attestation object: P256(UncompressedP256PubKey({:?}, {:?}))",
  10059             &att_obj[x_start..y_meta_start],
  10060             &att_obj[y_start..],
  10061         )
  10062         .as_str(),
  10063     )
  10064     .to_string().into_bytes();
  10065     assert_eq!(serde_json::from_str::<RegistrationRelaxed>(
  10066         serde_json::json!({
  10067             "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10068             "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10069             "response": {
  10070                 "clientDataJSON": b64_cdata_json,
  10071                 "authenticatorData": b64_adata,
  10072                 "transports": [],
  10073                 "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
  10074                 "publicKeyAlgorithm": -7i8,
  10075                 "attestationObject": b64_aobj,
  10076             },
  10077             "clientExtensionResults": {},
  10078             "type": "public-key"
  10079         })
  10080         .to_string()
  10081         .as_str()
  10082         )
  10083         .unwrap_err().to_string().into_bytes().get(..err.len()),
  10084         Some(err.as_slice())
  10085     );
  10086     // Missing `publicKey`.
  10087     drop(
  10088         serde_json::from_str::<RegistrationRelaxed>(
  10089             serde_json::json!({
  10090                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10091                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10092                 "response": {
  10093                     "clientDataJSON": b64_cdata_json,
  10094                     "authenticatorData": b64_adata,
  10095                     "transports": [],
  10096                     "publicKeyAlgorithm": -7i8,
  10097                     "attestationObject": b64_aobj,
  10098                 },
  10099                 "clientExtensionResults": {},
  10100                 "type": "public-key"
  10101             })
  10102             .to_string()
  10103             .as_str(),
  10104         )
  10105         .unwrap(),
  10106     );
  10107     // `null` `publicKey`.
  10108     drop(
  10109         serde_json::from_str::<RegistrationRelaxed>(
  10110             serde_json::json!({
  10111                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10112                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10113                 "response": {
  10114                     "clientDataJSON": b64_cdata_json,
  10115                     "authenticatorData": b64_adata,
  10116                     "transports": [],
  10117                     "publicKey": null,
  10118                     "publicKeyAlgorithm": -7i8,
  10119                     "attestationObject": b64_aobj,
  10120                 },
  10121                 "clientExtensionResults": {},
  10122                 "type": "public-key"
  10123             })
  10124             .to_string()
  10125             .as_str(),
  10126         )
  10127         .unwrap(),
  10128     );
  10129     // Base case is valid.
  10130     assert!(
  10131         serde_json::from_str::<CustomRegistration>(
  10132             serde_json::json!({
  10133                 "clientDataJSON": b64_cdata_json,
  10134                 "transports": [],
  10135                 "attestationObject": b64_aobj,
  10136                 "clientExtensionResults": {},
  10137                 "type": "public-key"
  10138             })
  10139             .to_string()
  10140             .as_str()
  10141         )
  10142         .is_ok_and(
  10143             |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
  10144                 && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
  10145                 && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
  10146                     == *Sha256::digest(c_data_json.as_bytes())
  10147                 && reg.0.response.transports.is_empty()
  10148                 && matches!(
  10149                     reg.0.authenticator_attachment,
  10150                     AuthenticatorAttachment::None
  10151                 )
  10152                 && reg.0.client_extension_results.cred_props.is_none()
  10153                 && reg.0.client_extension_results.prf.is_none()
  10154         )
  10155     );
  10156 }
  10157 #[expect(clippy::unwrap_used, reason = "OK in tests")]
  10158 #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
  10159 #[expect(clippy::too_many_lines, reason = "a lot to test")]
  10160 #[test]
  10161 fn es384_registration_deserialize_data_mismatch() {
  10162     let c_data_json = serde_json::json!({}).to_string();
  10163     let mut att_obj: [u8; 211] = [
  10164         cbor::MAP_3,
  10165         cbor::TEXT_3,
  10166         b'f',
  10167         b'm',
  10168         b't',
  10169         cbor::TEXT_4,
  10170         b'n',
  10171         b'o',
  10172         b'n',
  10173         b'e',
  10174         cbor::TEXT_7,
  10175         b'a',
  10176         b't',
  10177         b't',
  10178         b'S',
  10179         b't',
  10180         b'm',
  10181         b't',
  10182         cbor::MAP_0,
  10183         cbor::TEXT_8,
  10184         b'a',
  10185         b'u',
  10186         b't',
  10187         b'h',
  10188         b'D',
  10189         b'a',
  10190         b't',
  10191         b'a',
  10192         cbor::BYTES_INFO_24,
  10193         181,
  10194         // `rpIdHash`.
  10195         0,
  10196         0,
  10197         0,
  10198         0,
  10199         0,
  10200         0,
  10201         0,
  10202         0,
  10203         0,
  10204         0,
  10205         0,
  10206         0,
  10207         0,
  10208         0,
  10209         0,
  10210         0,
  10211         0,
  10212         0,
  10213         0,
  10214         0,
  10215         0,
  10216         0,
  10217         0,
  10218         0,
  10219         0,
  10220         0,
  10221         0,
  10222         0,
  10223         0,
  10224         0,
  10225         0,
  10226         0,
  10227         // `flags`.
  10228         0b0100_0101,
  10229         // `signCount`.
  10230         0,
  10231         0,
  10232         0,
  10233         0,
  10234         // `aaguid`.
  10235         0,
  10236         0,
  10237         0,
  10238         0,
  10239         0,
  10240         0,
  10241         0,
  10242         0,
  10243         0,
  10244         0,
  10245         0,
  10246         0,
  10247         0,
  10248         0,
  10249         0,
  10250         0,
  10251         // `credentialIdLength`.
  10252         0,
  10253         16,
  10254         // `credentialId`.
  10255         0,
  10256         0,
  10257         0,
  10258         0,
  10259         0,
  10260         0,
  10261         0,
  10262         0,
  10263         0,
  10264         0,
  10265         0,
  10266         0,
  10267         0,
  10268         0,
  10269         0,
  10270         0,
  10271         // P-384 COSE key.
  10272         cbor::MAP_5,
  10273         KTY,
  10274         EC2,
  10275         ALG,
  10276         cbor::NEG_INFO_24,
  10277         ES384,
  10278         // `crv`.
  10279         cbor::NEG_ONE,
  10280         // `P-384`.
  10281         cbor::TWO,
  10282         // `x`.
  10283         cbor::NEG_TWO,
  10284         cbor::BYTES_INFO_24,
  10285         48,
  10286         // x-coordinate. This will be overwritten later.
  10287         0,
  10288         0,
  10289         0,
  10290         0,
  10291         0,
  10292         0,
  10293         0,
  10294         0,
  10295         0,
  10296         0,
  10297         0,
  10298         0,
  10299         0,
  10300         0,
  10301         0,
  10302         0,
  10303         0,
  10304         0,
  10305         0,
  10306         0,
  10307         0,
  10308         0,
  10309         0,
  10310         0,
  10311         0,
  10312         0,
  10313         0,
  10314         0,
  10315         0,
  10316         0,
  10317         0,
  10318         0,
  10319         0,
  10320         0,
  10321         0,
  10322         0,
  10323         0,
  10324         0,
  10325         0,
  10326         0,
  10327         0,
  10328         0,
  10329         0,
  10330         0,
  10331         0,
  10332         0,
  10333         0,
  10334         0,
  10335         // `y`.
  10336         cbor::NEG_THREE,
  10337         cbor::BYTES_INFO_24,
  10338         48,
  10339         // y-coordinate. This will be overwritten later.
  10340         0,
  10341         0,
  10342         0,
  10343         0,
  10344         0,
  10345         0,
  10346         0,
  10347         0,
  10348         0,
  10349         0,
  10350         0,
  10351         0,
  10352         0,
  10353         0,
  10354         0,
  10355         0,
  10356         0,
  10357         0,
  10358         0,
  10359         0,
  10360         0,
  10361         0,
  10362         0,
  10363         0,
  10364         0,
  10365         0,
  10366         0,
  10367         0,
  10368         0,
  10369         0,
  10370         0,
  10371         0,
  10372         0,
  10373         0,
  10374         0,
  10375         0,
  10376         0,
  10377         0,
  10378         0,
  10379         0,
  10380         0,
  10381         0,
  10382         0,
  10383         0,
  10384         0,
  10385         0,
  10386         0,
  10387         0,
  10388     ];
  10389     let key = P384Key::from_bytes(
  10390         &[
  10391             158, 99, 156, 49, 190, 211, 85, 167, 28, 2, 80, 57, 31, 22, 17, 38, 85, 78, 232, 42,
  10392             45, 199, 154, 243, 136, 251, 84, 34, 5, 120, 208, 91, 61, 248, 64, 144, 87, 1, 32, 86,
  10393             220, 68, 182, 11, 105, 223, 75, 70,
  10394         ]
  10395         .into(),
  10396     )
  10397     .unwrap()
  10398     .public_key();
  10399     let enc_key = key.to_sec1_point(false);
  10400     let pub_key = key.to_public_key_der().unwrap();
  10401     let att_obj_len = att_obj.len();
  10402     let x_start = att_obj_len - 99;
  10403     let y_meta_start = x_start + 48;
  10404     let y_start = y_meta_start + 3;
  10405     att_obj[x_start..y_meta_start].copy_from_slice(enc_key.x().unwrap());
  10406     att_obj[y_start..].copy_from_slice(enc_key.y().unwrap());
  10407     let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
  10408     let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 181..]);
  10409     let b64_key = base64url_nopad::encode(pub_key.as_bytes());
  10410     let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
  10411     // Base case is valid.
  10412     assert!(
  10413         serde_json::from_str::<RegistrationRelaxed>(
  10414             serde_json::json!({
  10415                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10416                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10417                 "response": {
  10418                     "clientDataJSON": b64_cdata_json,
  10419                     "authenticatorData": b64_adata,
  10420                     "transports": [],
  10421                     "publicKey": b64_key,
  10422                     "publicKeyAlgorithm": -35i8,
  10423                     "attestationObject": b64_aobj,
  10424                 },
  10425                 "clientExtensionResults": {},
  10426                 "type": "public-key"
  10427             })
  10428             .to_string()
  10429             .as_str()
  10430         )
  10431         .is_ok_and(
  10432             |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
  10433                 && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
  10434                 && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
  10435                     == *Sha256::digest(c_data_json.as_bytes())
  10436                 && reg.0.response.transports.is_empty()
  10437                 && matches!(
  10438                     reg.0.authenticator_attachment,
  10439                     AuthenticatorAttachment::None
  10440                 )
  10441                 && reg.0.client_extension_results.cred_props.is_none()
  10442                 && reg.0.client_extension_results.prf.is_none()
  10443         )
  10444     );
  10445     // `publicKeyAlgorithm` mismatch.
  10446     let mut err = Error::invalid_value(
  10447         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Es256).as_str()),
  10448         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Es384).as_str()
  10449     )
  10450     .to_string().into_bytes();
  10451     assert_eq!(
  10452         serde_json::from_str::<RegistrationRelaxed>(
  10453             serde_json::json!({
  10454                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10455                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10456                 "response": {
  10457                     "clientDataJSON": b64_cdata_json,
  10458                     "authenticatorData": b64_adata,
  10459                     "transports": [],
  10460                     "publicKey": b64_key,
  10461                     "publicKeyAlgorithm": -7i8,
  10462                     "attestationObject": b64_aobj,
  10463                 },
  10464                 "clientExtensionResults": {},
  10465                 "type": "public-key"
  10466             })
  10467             .to_string()
  10468             .as_str()
  10469         )
  10470         .unwrap_err()
  10471         .to_string()
  10472         .into_bytes()
  10473         .get(..err.len()),
  10474         Some(err.as_slice())
  10475     );
  10476     // Missing `publicKeyAlgorithm`.
  10477     drop(
  10478         serde_json::from_str::<RegistrationRelaxed>(
  10479             serde_json::json!({
  10480                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10481                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10482                 "response": {
  10483                     "clientDataJSON": b64_cdata_json,
  10484                     "authenticatorData": b64_adata,
  10485                     "transports": [],
  10486                     "publicKey": b64_key,
  10487                     "attestationObject": b64_aobj,
  10488                 },
  10489                 "clientExtensionResults": {},
  10490                 "type": "public-key"
  10491             })
  10492             .to_string()
  10493             .as_str(),
  10494         )
  10495         .unwrap(),
  10496     );
  10497     // `null` `publicKeyAlgorithm`.
  10498     drop(
  10499         serde_json::from_str::<RegistrationRelaxed>(
  10500             serde_json::json!({
  10501                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10502                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10503                 "response": {
  10504                     "clientDataJSON": b64_cdata_json,
  10505                     "authenticatorData": b64_adata,
  10506                     "transports": [],
  10507                     "publicKey": b64_key,
  10508                     "publicKeyAlgorithm": null,
  10509                     "attestationObject": b64_aobj,
  10510                 },
  10511                 "clientExtensionResults": {},
  10512                 "type": "public-key"
  10513             })
  10514             .to_string()
  10515             .as_str(),
  10516         )
  10517         .unwrap(),
  10518     );
  10519     // `publicKey` mismatch.
  10520     let bad_pub_key = P384PubKey::from_sec1_point(&P384Pt::from_affine_coordinates(
  10521         &[
  10522             192, 10, 27, 46, 66, 67, 80, 98, 33, 230, 156, 95, 1, 135, 150, 110, 64, 243, 22, 118,
  10523             5, 255, 107, 44, 234, 111, 217, 105, 125, 114, 39, 7, 126, 2, 191, 111, 48, 93, 234,
  10524             175, 18, 172, 59, 28, 97, 106, 178, 152,
  10525         ]
  10526         .into(),
  10527         &[
  10528             57, 36, 196, 12, 109, 129, 253, 115, 88, 154, 6, 43, 195, 85, 169, 5, 230, 51, 28, 205,
  10529             142, 28, 150, 35, 24, 222, 170, 253, 14, 248, 84, 151, 109, 191, 152, 111, 222, 70,
  10530             134, 247, 109, 171, 211, 33, 214, 217, 200, 111,
  10531         ]
  10532         .into(),
  10533         false,
  10534     ))
  10535     .unwrap();
  10536     err = Error::invalid_value(
  10537         Unexpected::Bytes([0; 32].as_slice()),
  10538         &format!(
  10539             "DER-encoded public key to match the public key within the attestation object: P384(UncompressedP384PubKey({:?}, {:?}))",
  10540             &att_obj[x_start..y_meta_start],
  10541             &att_obj[y_start..],
  10542         )
  10543         .as_str(),
  10544     )
  10545     .to_string().into_bytes();
  10546     assert_eq!(serde_json::from_str::<RegistrationRelaxed>(
  10547         serde_json::json!({
  10548             "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10549             "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10550             "response": {
  10551                 "clientDataJSON": b64_cdata_json,
  10552                 "authenticatorData": b64_adata,
  10553                 "transports": [],
  10554                 "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
  10555                 "publicKeyAlgorithm": -35i8,
  10556                 "attestationObject": b64_aobj,
  10557             },
  10558             "clientExtensionResults": {},
  10559             "type": "public-key"
  10560         }).to_string().as_str()
  10561     ).unwrap_err().to_string().into_bytes().get(..err.len()), Some(err.as_slice()));
  10562     // Missing `publicKey`.
  10563     drop(
  10564         serde_json::from_str::<RegistrationRelaxed>(
  10565             serde_json::json!({
  10566                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10567                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10568                 "response": {
  10569                     "clientDataJSON": b64_cdata_json,
  10570                     "authenticatorData": b64_adata,
  10571                     "transports": [],
  10572                     "publicKeyAlgorithm": -35i8,
  10573                     "attestationObject": b64_aobj,
  10574                 },
  10575                 "clientExtensionResults": {},
  10576                 "type": "public-key"
  10577             })
  10578             .to_string()
  10579             .as_str(),
  10580         )
  10581         .unwrap(),
  10582     );
  10583     // `publicKeyAlgorithm` mismatch when `publicKey` does not exist.
  10584     err = Error::invalid_value(
  10585         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
  10586         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Es384).as_str()
  10587     )
  10588     .to_string().into_bytes();
  10589     assert_eq!(
  10590         serde_json::from_str::<RegistrationRelaxed>(
  10591             serde_json::json!({
  10592                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10593                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10594                 "response": {
  10595                     "clientDataJSON": b64_cdata_json,
  10596                     "authenticatorData": b64_adata,
  10597                     "transports": [],
  10598                     "publicKeyAlgorithm": -8i8,
  10599                     "attestationObject": b64_aobj,
  10600                 },
  10601                 "clientExtensionResults": {},
  10602                 "type": "public-key"
  10603             })
  10604             .to_string()
  10605             .as_str()
  10606         )
  10607         .unwrap_err()
  10608         .to_string()
  10609         .into_bytes()
  10610         .get(..err.len()),
  10611         Some(err.as_slice())
  10612     );
  10613     // `null` `publicKey`.
  10614     drop(
  10615         serde_json::from_str::<RegistrationRelaxed>(
  10616             serde_json::json!({
  10617                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10618                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10619                 "response": {
  10620                     "clientDataJSON": b64_cdata_json,
  10621                     "authenticatorData": b64_adata,
  10622                     "transports": [],
  10623                     "publicKey": null,
  10624                     "publicKeyAlgorithm": -35i8,
  10625                     "attestationObject": b64_aobj,
  10626                 },
  10627                 "clientExtensionResults": {},
  10628                 "type": "public-key"
  10629             })
  10630             .to_string()
  10631             .as_str(),
  10632         )
  10633         .unwrap(),
  10634     );
  10635     // `publicKeyAlgorithm` mismatch when `publicKey` is null.
  10636     err = Error::invalid_value(
  10637         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
  10638         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Es384).as_str()
  10639     )
  10640     .to_string().into_bytes();
  10641     assert_eq!(
  10642         serde_json::from_str::<RegistrationRelaxed>(
  10643             serde_json::json!({
  10644                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  10645                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  10646                 "response": {
  10647                     "clientDataJSON": b64_cdata_json,
  10648                     "authenticatorData": b64_adata,
  10649                     "transports": [],
  10650                     "publicKey": null,
  10651                     "publicKeyAlgorithm": -8i8,
  10652                     "attestationObject": b64_aobj,
  10653                 },
  10654                 "clientExtensionResults": {},
  10655                 "type": "public-key"
  10656             })
  10657             .to_string()
  10658             .as_str()
  10659         )
  10660         .unwrap_err()
  10661         .to_string()
  10662         .into_bytes()
  10663         .get(..err.len()),
  10664         Some(err.as_slice())
  10665     );
  10666     // Base case is valid.
  10667     assert!(
  10668         serde_json::from_str::<CustomRegistration>(
  10669             serde_json::json!({
  10670                 "clientDataJSON": b64_cdata_json,
  10671                 "transports": [],
  10672                 "attestationObject": b64_aobj,
  10673                 "clientExtensionResults": {},
  10674                 "type": "public-key"
  10675             })
  10676             .to_string()
  10677             .as_str()
  10678         )
  10679         .is_ok_and(
  10680             |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
  10681                 && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
  10682                 && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
  10683                     == *Sha256::digest(c_data_json.as_bytes())
  10684                 && reg.0.response.transports.is_empty()
  10685                 && matches!(
  10686                     reg.0.authenticator_attachment,
  10687                     AuthenticatorAttachment::None
  10688                 )
  10689                 && reg.0.client_extension_results.cred_props.is_none()
  10690                 && reg.0.client_extension_results.prf.is_none()
  10691         )
  10692     );
  10693 }
  10694 #[expect(clippy::unwrap_used, reason = "OK in tests")]
  10695 #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
  10696 #[expect(clippy::too_many_lines, reason = "a lot to test")]
  10697 #[test]
  10698 fn rs256_registration_deserialize_data_mismatch() {
  10699     let c_data_json = serde_json::json!({}).to_string();
  10700     let mut att_obj: [u8; 374] = [
  10701         cbor::MAP_3,
  10702         cbor::TEXT_3,
  10703         b'f',
  10704         b'm',
  10705         b't',
  10706         cbor::TEXT_4,
  10707         b'n',
  10708         b'o',
  10709         b'n',
  10710         b'e',
  10711         cbor::TEXT_7,
  10712         b'a',
  10713         b't',
  10714         b't',
  10715         b'S',
  10716         b't',
  10717         b'm',
  10718         b't',
  10719         cbor::MAP_0,
  10720         cbor::TEXT_8,
  10721         b'a',
  10722         b'u',
  10723         b't',
  10724         b'h',
  10725         b'D',
  10726         b'a',
  10727         b't',
  10728         b'a',
  10729         cbor::BYTES_INFO_25,
  10730         1,
  10731         87,
  10732         // `rpIdHash`.
  10733         0,
  10734         0,
  10735         0,
  10736         0,
  10737         0,
  10738         0,
  10739         0,
  10740         0,
  10741         0,
  10742         0,
  10743         0,
  10744         0,
  10745         0,
  10746         0,
  10747         0,
  10748         0,
  10749         0,
  10750         0,
  10751         0,
  10752         0,
  10753         0,
  10754         0,
  10755         0,
  10756         0,
  10757         0,
  10758         0,
  10759         0,
  10760         0,
  10761         0,
  10762         0,
  10763         0,
  10764         0,
  10765         // `flags`.
  10766         0b0100_0101,
  10767         // `signCount`.
  10768         0,
  10769         0,
  10770         0,
  10771         0,
  10772         // `aaguid`.
  10773         0,
  10774         0,
  10775         0,
  10776         0,
  10777         0,
  10778         0,
  10779         0,
  10780         0,
  10781         0,
  10782         0,
  10783         0,
  10784         0,
  10785         0,
  10786         0,
  10787         0,
  10788         0,
  10789         // `credentialIdLength`.
  10790         0,
  10791         16,
  10792         // `credentialId`.
  10793         0,
  10794         0,
  10795         0,
  10796         0,
  10797         0,
  10798         0,
  10799         0,
  10800         0,
  10801         0,
  10802         0,
  10803         0,
  10804         0,
  10805         0,
  10806         0,
  10807         0,
  10808         0,
  10809         // RSA COSE key.
  10810         cbor::MAP_4,
  10811         KTY,
  10812         RSA,
  10813         ALG,
  10814         cbor::NEG_INFO_25,
  10815         // RS256.
  10816         1,
  10817         0,
  10818         // `n`.
  10819         cbor::NEG_ONE,
  10820         cbor::BYTES_INFO_25,
  10821         1,
  10822         0,
  10823         // n. This will be overwritten later.
  10824         0,
  10825         0,
  10826         0,
  10827         0,
  10828         0,
  10829         0,
  10830         0,
  10831         0,
  10832         0,
  10833         0,
  10834         0,
  10835         0,
  10836         0,
  10837         0,
  10838         0,
  10839         0,
  10840         0,
  10841         0,
  10842         0,
  10843         0,
  10844         0,
  10845         0,
  10846         0,
  10847         0,
  10848         0,
  10849         0,
  10850         0,
  10851         0,
  10852         0,
  10853         0,
  10854         0,
  10855         0,
  10856         0,
  10857         0,
  10858         0,
  10859         0,
  10860         0,
  10861         0,
  10862         0,
  10863         0,
  10864         0,
  10865         0,
  10866         0,
  10867         0,
  10868         0,
  10869         0,
  10870         0,
  10871         0,
  10872         0,
  10873         0,
  10874         0,
  10875         0,
  10876         0,
  10877         0,
  10878         0,
  10879         0,
  10880         0,
  10881         0,
  10882         0,
  10883         0,
  10884         0,
  10885         0,
  10886         0,
  10887         0,
  10888         0,
  10889         0,
  10890         0,
  10891         0,
  10892         0,
  10893         0,
  10894         0,
  10895         0,
  10896         0,
  10897         0,
  10898         0,
  10899         0,
  10900         0,
  10901         0,
  10902         0,
  10903         0,
  10904         0,
  10905         0,
  10906         0,
  10907         0,
  10908         0,
  10909         0,
  10910         0,
  10911         0,
  10912         0,
  10913         0,
  10914         0,
  10915         0,
  10916         0,
  10917         0,
  10918         0,
  10919         0,
  10920         0,
  10921         0,
  10922         0,
  10923         0,
  10924         0,
  10925         0,
  10926         0,
  10927         0,
  10928         0,
  10929         0,
  10930         0,
  10931         0,
  10932         0,
  10933         0,
  10934         0,
  10935         0,
  10936         0,
  10937         0,
  10938         0,
  10939         0,
  10940         0,
  10941         0,
  10942         0,
  10943         0,
  10944         0,
  10945         0,
  10946         0,
  10947         0,
  10948         0,
  10949         0,
  10950         0,
  10951         0,
  10952         0,
  10953         0,
  10954         0,
  10955         0,
  10956         0,
  10957         0,
  10958         0,
  10959         0,
  10960         0,
  10961         0,
  10962         0,
  10963         0,
  10964         0,
  10965         0,
  10966         0,
  10967         0,
  10968         0,
  10969         0,
  10970         0,
  10971         0,
  10972         0,
  10973         0,
  10974         0,
  10975         0,
  10976         0,
  10977         0,
  10978         0,
  10979         0,
  10980         0,
  10981         0,
  10982         0,
  10983         0,
  10984         0,
  10985         0,
  10986         0,
  10987         0,
  10988         0,
  10989         0,
  10990         0,
  10991         0,
  10992         0,
  10993         0,
  10994         0,
  10995         0,
  10996         0,
  10997         0,
  10998         0,
  10999         0,
  11000         0,
  11001         0,
  11002         0,
  11003         0,
  11004         0,
  11005         0,
  11006         0,
  11007         0,
  11008         0,
  11009         0,
  11010         0,
  11011         0,
  11012         0,
  11013         0,
  11014         0,
  11015         0,
  11016         0,
  11017         0,
  11018         0,
  11019         0,
  11020         0,
  11021         0,
  11022         0,
  11023         0,
  11024         0,
  11025         0,
  11026         0,
  11027         0,
  11028         0,
  11029         0,
  11030         0,
  11031         0,
  11032         0,
  11033         0,
  11034         0,
  11035         0,
  11036         0,
  11037         0,
  11038         0,
  11039         0,
  11040         0,
  11041         0,
  11042         0,
  11043         0,
  11044         0,
  11045         0,
  11046         0,
  11047         0,
  11048         0,
  11049         0,
  11050         0,
  11051         0,
  11052         0,
  11053         0,
  11054         0,
  11055         0,
  11056         0,
  11057         0,
  11058         0,
  11059         0,
  11060         0,
  11061         0,
  11062         0,
  11063         0,
  11064         0,
  11065         0,
  11066         0,
  11067         0,
  11068         0,
  11069         0,
  11070         0,
  11071         0,
  11072         0,
  11073         0,
  11074         0,
  11075         0,
  11076         0,
  11077         0,
  11078         0,
  11079         0,
  11080         // `e`.
  11081         cbor::NEG_TWO,
  11082         cbor::BYTES | 3,
  11083         // e.
  11084         1,
  11085         0,
  11086         1,
  11087     ];
  11088     let n = [
  11089         111, 183, 124, 133, 38, 167, 70, 148, 44, 50, 30, 60, 121, 14, 38, 37, 96, 114, 107, 195,
  11090         248, 64, 79, 36, 237, 140, 43, 27, 94, 74, 102, 152, 135, 102, 184, 150, 186, 206, 185, 19,
  11091         165, 209, 48, 98, 98, 9, 3, 205, 208, 82, 250, 105, 132, 201, 73, 62, 60, 165, 100, 128,
  11092         153, 9, 41, 118, 66, 95, 236, 214, 73, 135, 197, 68, 184, 10, 27, 116, 204, 145, 50, 174,
  11093         58, 42, 183, 181, 119, 232, 126, 252, 217, 96, 162, 190, 103, 122, 64, 87, 145, 45, 32,
  11094         207, 17, 239, 223, 3, 35, 14, 112, 119, 124, 141, 123, 208, 239, 105, 81, 217, 151, 162,
  11095         190, 17, 88, 182, 176, 158, 81, 200, 42, 166, 133, 48, 23, 236, 55, 117, 248, 233, 151,
  11096         203, 122, 155, 231, 46, 177, 20, 20, 151, 64, 222, 239, 226, 7, 21, 254, 81, 202, 64, 232,
  11097         161, 235, 22, 51, 246, 207, 213, 0, 229, 138, 46, 222, 205, 157, 108, 139, 253, 230, 80,
  11098         50, 2, 122, 212, 163, 100, 180, 114, 12, 113, 52, 56, 99, 188, 42, 198, 212, 23, 182, 222,
  11099         56, 221, 200, 79, 96, 239, 221, 135, 10, 17, 106, 183, 56, 104, 68, 94, 198, 196, 35, 200,
  11100         83, 204, 26, 185, 204, 212, 31, 183, 19, 111, 233, 13, 72, 93, 53, 65, 111, 59, 242, 122,
  11101         160, 244, 162, 126, 38, 235, 156, 47, 88, 39, 132, 153, 79, 0, 133, 78, 7, 218, 165, 241,
  11102     ];
  11103     let e = 0x0001_0001u32;
  11104     let d = [
  11105         145, 79, 21, 97, 233, 3, 192, 194, 177, 68, 181, 80, 120, 197, 23, 44, 185, 74, 144, 0,
  11106         132, 149, 139, 11, 16, 224, 4, 112, 236, 94, 238, 97, 121, 124, 213, 145, 24, 253, 168, 35,
  11107         190, 205, 132, 115, 33, 201, 38, 253, 246, 180, 66, 155, 165, 46, 3, 254, 68, 108, 154,
  11108         247, 246, 45, 187, 0, 204, 96, 185, 157, 249, 174, 158, 38, 62, 244, 183, 76, 102, 6, 219,
  11109         92, 212, 138, 59, 147, 163, 219, 111, 39, 105, 21, 236, 196, 38, 255, 114, 247, 82, 104,
  11110         113, 204, 29, 152, 209, 219, 48, 239, 74, 129, 19, 247, 33, 239, 119, 166, 216, 152, 94,
  11111         138, 238, 164, 242, 129, 50, 150, 57, 20, 53, 224, 56, 241, 138, 97, 111, 215, 107, 212,
  11112         195, 146, 108, 143, 0, 229, 181, 171, 73, 152, 105, 146, 25, 243, 242, 140, 252, 248, 162,
  11113         247, 63, 168, 180, 20, 153, 120, 10, 248, 211, 1, 71, 127, 212, 249, 237, 203, 202, 48, 26,
  11114         216, 226, 228, 186, 13, 204, 70, 255, 240, 89, 255, 59, 83, 31, 253, 55, 43, 158, 90, 248,
  11115         83, 32, 159, 105, 57, 134, 34, 96, 18, 255, 245, 153, 162, 60, 91, 99, 220, 51, 44, 85,
  11116         114, 67, 125, 202, 65, 217, 245, 40, 8, 81, 165, 142, 24, 245, 127, 122, 247, 152, 212, 75,
  11117         45, 59, 90, 184, 234, 31, 147, 36, 8, 212, 45, 50, 23, 3, 25, 253, 87, 227, 79, 119, 161,
  11118     ];
  11119     let p = BoxedUint::from_le_slice_vartime(
  11120         [
  11121             215, 166, 5, 21, 11, 179, 41, 77, 198, 92, 165, 48, 77, 162, 42, 41, 206, 141, 60, 69,
  11122             47, 164, 19, 92, 46, 72, 100, 238, 100, 53, 214, 197, 163, 185, 6, 140, 229, 250, 195,
  11123             77, 8, 12, 5, 236, 178, 173, 86, 201, 43, 213, 165, 51, 108, 101, 161, 99, 76, 240, 14,
  11124             234, 76, 197, 137, 53, 198, 168, 135, 205, 212, 198, 120, 29, 16, 82, 98, 233, 236,
  11125             177, 12, 171, 141, 100, 107, 146, 33, 176, 125, 202, 172, 79, 147, 179, 30, 62, 247,
  11126             206, 169, 19, 168, 114, 26, 73, 108, 178, 105, 84, 89, 191, 168, 253, 228, 214, 54, 16,
  11127             212, 199, 111, 72, 3, 41, 247, 227, 165, 244, 32, 188, 24, 247,
  11128         ]
  11129         .as_slice(),
  11130     );
  11131     let p_2 = BoxedUint::from_le_slice_vartime(
  11132         [
  11133             41, 25, 198, 240, 134, 206, 121, 57, 11, 5, 134, 192, 212, 77, 229, 197, 14, 78, 85,
  11134             212, 190, 114, 179, 188, 21, 171, 174, 12, 104, 74, 15, 164, 136, 173, 62, 177, 141,
  11135             213, 93, 102, 147, 83, 59, 124, 146, 59, 175, 213, 55, 27, 25, 248, 154, 29, 39, 85,
  11136             50, 235, 134, 60, 203, 106, 186, 195, 190, 185, 71, 169, 142, 236, 92, 11, 250, 187,
  11137             198, 8, 201, 184, 120, 178, 227, 87, 63, 243, 89, 227, 234, 184, 28, 252, 112, 211,
  11138             193, 69, 23, 92, 5, 72, 93, 53, 69, 159, 73, 160, 105, 244, 249, 94, 214, 173, 9, 236,
  11139             4, 255, 129, 11, 224, 140, 252, 168, 57, 143, 176, 241, 60, 219, 90, 250,
  11140         ]
  11141         .as_slice(),
  11142     );
  11143     let key = RsaPrivateKey::from_components(
  11144         BoxedUint::from_le_slice_vartime(n.as_slice()),
  11145         e.into(),
  11146         BoxedUint::from_le_slice_vartime(d.as_slice()),
  11147         vec![p, p_2],
  11148     )
  11149     .unwrap()
  11150     .to_public_key();
  11151     let pub_key = key.to_public_key_der().unwrap();
  11152     let att_obj_len = att_obj.len();
  11153     let n_start = att_obj_len - 261;
  11154     let e_start = n_start + 256;
  11155     att_obj[n_start..e_start].copy_from_slice(key.n().to_be_bytes().as_ref());
  11156     let b64_cdata_json = base64url_nopad::encode(c_data_json.as_bytes());
  11157     let b64_adata = base64url_nopad::encode(&att_obj[att_obj_len - 343..]);
  11158     let b64_key = base64url_nopad::encode(pub_key.as_bytes());
  11159     let b64_aobj = base64url_nopad::encode(att_obj.as_slice());
  11160     // Base case is valid.
  11161     assert!(
  11162         serde_json::from_str::<RegistrationRelaxed>(
  11163             serde_json::json!({
  11164                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11165                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11166                 "response": {
  11167                     "clientDataJSON": b64_cdata_json,
  11168                     "authenticatorData": b64_adata,
  11169                     "transports": [],
  11170                     "publicKey": b64_key,
  11171                     "publicKeyAlgorithm": -257i16,
  11172                     "attestationObject": b64_aobj,
  11173                 },
  11174                 "clientExtensionResults": {},
  11175                 "type": "public-key"
  11176             })
  11177             .to_string()
  11178             .as_str()
  11179         )
  11180         .is_ok_and(
  11181             |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
  11182                 && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
  11183                 && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
  11184                     == *Sha256::digest(c_data_json.as_bytes())
  11185                 && reg.0.response.transports.is_empty()
  11186                 && matches!(
  11187                     reg.0.authenticator_attachment,
  11188                     AuthenticatorAttachment::None
  11189                 )
  11190                 && reg.0.client_extension_results.cred_props.is_none()
  11191                 && reg.0.client_extension_results.prf.is_none()
  11192         )
  11193     );
  11194     // `publicKeyAlgorithm` mismatch.
  11195     let mut err = Error::invalid_value(
  11196         Unexpected::Other(format!("{:?}", CoseAlgorithmIdentifier::Eddsa).as_str()),
  11197         &format!("public key algorithm to match the algorithm associated with the public key within the attestation object: {:?}", CoseAlgorithmIdentifier::Rs256).as_str()
  11198     )
  11199     .to_string().into_bytes();
  11200     assert_eq!(
  11201         serde_json::from_str::<RegistrationRelaxed>(
  11202             serde_json::json!({
  11203                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11204                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11205                 "response": {
  11206                     "clientDataJSON": b64_cdata_json,
  11207                     "authenticatorData": b64_adata,
  11208                     "transports": [],
  11209                     "publicKey": b64_key,
  11210                     "publicKeyAlgorithm": -8i8,
  11211                     "attestationObject": b64_aobj,
  11212                 },
  11213                 "clientExtensionResults": {},
  11214                 "type": "public-key"
  11215             })
  11216             .to_string()
  11217             .as_str()
  11218         )
  11219         .unwrap_err()
  11220         .to_string()
  11221         .into_bytes()
  11222         .get(..err.len()),
  11223         Some(err.as_slice())
  11224     );
  11225     // Missing `publicKeyAlgorithm`.
  11226     drop(
  11227         serde_json::from_str::<RegistrationRelaxed>(
  11228             serde_json::json!({
  11229                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11230                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11231                 "response": {
  11232                     "clientDataJSON": b64_cdata_json,
  11233                     "authenticatorData": b64_adata,
  11234                     "transports": [],
  11235                     "publicKey": b64_key,
  11236                     "attestationObject": b64_aobj,
  11237                 },
  11238                 "clientExtensionResults": {},
  11239                 "type": "public-key"
  11240             })
  11241             .to_string()
  11242             .as_str(),
  11243         )
  11244         .unwrap(),
  11245     );
  11246     // `null` `publicKeyAlgorithm`.
  11247     drop(
  11248         serde_json::from_str::<RegistrationRelaxed>(
  11249             serde_json::json!({
  11250                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11251                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11252                 "response": {
  11253                     "clientDataJSON": b64_cdata_json,
  11254                     "authenticatorData": b64_adata,
  11255                     "transports": [],
  11256                     "publicKey": b64_key,
  11257                     "publicKeyAlgorithm": null,
  11258                     "attestationObject": b64_aobj,
  11259                 },
  11260                 "clientExtensionResults": {},
  11261                 "type": "public-key"
  11262             })
  11263             .to_string()
  11264             .as_str(),
  11265         )
  11266         .unwrap(),
  11267     );
  11268     // `publicKey` mismatch.
  11269     let bad_pub_key = RsaPrivateKey::from_components(
  11270         BoxedUint::from_le_slice_vartime(
  11271             [
  11272                 175, 161, 161, 75, 52, 244, 72, 168, 29, 119, 33, 120, 3, 222, 231, 152, 222, 119,
  11273                 112, 83, 221, 237, 74, 174, 79, 216, 147, 251, 245, 94, 234, 114, 254, 21, 17, 254,
  11274                 8, 115, 75, 127, 150, 87, 59, 109, 230, 116, 85, 90, 11, 160, 63, 217, 9, 38, 187,
  11275                 250, 226, 183, 38, 164, 182, 218, 22, 19, 58, 189, 83, 219, 11, 144, 15, 99, 151,
  11276                 166, 46, 57, 17, 111, 189, 131, 142, 113, 85, 122, 188, 238, 52, 21, 116, 125, 102,
  11277                 195, 182, 165, 29, 156, 213, 182, 125, 156, 88, 56, 221, 2, 98, 43, 210, 115, 32,
  11278                 4, 105, 88, 181, 158, 207, 236, 162, 250, 253, 240, 72, 8, 253, 50, 220, 247, 76,
  11279                 170, 143, 68, 225, 231, 113, 64, 244, 17, 138, 162, 233, 33, 2, 67, 11, 223, 188,
  11280                 232, 152, 193, 20, 32, 243, 52, 64, 43, 2, 243, 8, 77, 150, 232, 109, 148, 95, 127,
  11281                 55, 71, 162, 34, 54, 83, 135, 52, 172, 191, 32, 42, 106, 43, 211, 206, 100, 104,
  11282                 110, 232, 5, 43, 120, 180, 166, 40, 144, 233, 239, 103, 134, 103, 255, 224, 138,
  11283                 184, 208, 137, 127, 36, 189, 143, 248, 201, 2, 218, 51, 232, 96, 30, 83, 124, 109,
  11284                 241, 23, 179, 247, 151, 238, 212, 204, 44, 43, 223, 148, 241, 172, 10, 235, 155,
  11285                 94, 68, 116, 24, 116, 191, 86, 53, 127, 35, 133, 198, 204, 59, 76, 110, 16, 1, 15,
  11286                 148, 135, 157,
  11287             ]
  11288             .as_slice(),
  11289         ),
  11290         0x0001_0001u32.into(),
  11291         BoxedUint::from_le_slice_vartime(
  11292             [
  11293                 129, 93, 123, 251, 104, 29, 84, 203, 116, 100, 75, 237, 111, 160, 12, 100, 172, 76,
  11294                 57, 178, 144, 235, 81, 61, 115, 243, 28, 40, 183, 22, 56, 150, 68, 38, 220, 62,
  11295                 233, 110, 48, 174, 35, 197, 244, 109, 148, 109, 36, 69, 69, 82, 225, 113, 175, 6,
  11296                 239, 27, 193, 101, 50, 239, 122, 102, 7, 46, 98, 79, 195, 116, 155, 158, 138, 147,
  11297                 51, 93, 24, 237, 246, 82, 14, 109, 144, 250, 239, 93, 63, 214, 96, 130, 226, 134,
  11298                 198, 145, 161, 11, 231, 97, 214, 180, 255, 95, 158, 88, 108, 254, 243, 177, 133,
  11299                 184, 92, 95, 148, 88, 55, 124, 245, 244, 84, 86, 4, 121, 44, 231, 97, 176, 190, 29,
  11300                 155, 40, 57, 69, 165, 80, 168, 9, 56, 43, 233, 6, 14, 157, 112, 223, 64, 88, 141,
  11301                 7, 65, 23, 64, 208, 6, 83, 61, 8, 182, 248, 126, 84, 179, 163, 80, 238, 90, 133, 4,
  11302                 14, 71, 177, 175, 27, 29, 151, 211, 108, 162, 195, 7, 157, 167, 86, 169, 3, 87,
  11303                 235, 89, 158, 237, 216, 31, 243, 197, 62, 5, 84, 131, 230, 186, 248, 49, 12, 93,
  11304                 244, 61, 135, 180, 17, 162, 241, 13, 115, 241, 138, 219, 98, 155, 166, 191, 63, 12,
  11305                 37, 1, 165, 178, 84, 200, 72, 80, 41, 77, 136, 217, 141, 246, 209, 31, 243, 159,
  11306                 71, 43, 246, 159, 182, 171, 116, 12, 3, 142, 235, 218, 164, 70, 90, 147, 238, 42,
  11307                 75,
  11308             ]
  11309             .as_slice(),
  11310         ),
  11311         vec![
  11312             BoxedUint::from_le_slice_vartime(
  11313                 [
  11314                     215, 199, 110, 28, 64, 16, 16, 109, 106, 152, 150, 124, 52, 166, 121, 92, 242,
  11315                     13, 0, 69, 7, 152, 72, 172, 118, 63, 156, 180, 140, 39, 53, 29, 197, 224, 177,
  11316                     48, 41, 221, 102, 65, 17, 185, 55, 62, 219, 152, 227, 7, 78, 219, 14, 139, 71,
  11317                     204, 144, 152, 14, 39, 247, 244, 165, 224, 234, 60, 213, 74, 237, 30, 102, 177,
  11318                     242, 138, 168, 31, 122, 47, 206, 155, 225, 113, 103, 175, 152, 244, 27, 233,
  11319                     112, 223, 248, 38, 215, 178, 20, 244, 8, 121, 26, 11, 70, 122, 16, 85, 167, 87,
  11320                     64, 216, 228, 227, 173, 57, 250, 8, 221, 38, 12, 203, 212, 1, 112, 43, 72, 91,
  11321                     225, 97, 228, 57, 154, 193,
  11322                 ]
  11323                 .as_slice(),
  11324             ),
  11325             BoxedUint::from_le_slice_vartime(
  11326                 [
  11327                     233, 89, 204, 152, 31, 242, 8, 110, 38, 190, 111, 159, 105, 105, 45, 85, 15,
  11328                     244, 30, 250, 174, 226, 219, 111, 107, 191, 196, 135, 17, 123, 186, 167, 85,
  11329                     13, 120, 197, 159, 129, 78, 237, 152, 31, 230, 26, 229, 253, 197, 211, 105,
  11330                     204, 126, 142, 250, 55, 26, 172, 65, 160, 45, 6, 99, 86, 66, 238, 107, 6, 98,
  11331                     171, 93, 224, 201, 160, 31, 204, 82, 120, 228, 158, 238, 6, 190, 12, 150, 153,
  11332                     239, 95, 57, 71, 100, 239, 235, 155, 73, 200, 5, 225, 127, 185, 46, 48, 243,
  11333                     84, 33, 142, 17, 19, 20, 23, 215, 16, 114, 58, 211, 14, 73, 148, 168, 252, 159,
  11334                     252, 125, 57, 101, 211, 188, 12, 77, 208,
  11335                 ]
  11336                 .as_slice(),
  11337             ),
  11338         ],
  11339     )
  11340     .unwrap()
  11341     .to_public_key();
  11342     err = Error::invalid_value(
  11343         Unexpected::Bytes([0; 32].as_slice()),
  11344         &format!(
  11345             "DER-encoded public key to match the public key within the attestation object: Rsa(RsaPubKey({:?}, 65537))",
  11346             &att_obj[n_start..e_start],
  11347         )
  11348         .as_str(),
  11349     )
  11350     .to_string().into_bytes();
  11351     assert_eq!(serde_json::from_str::<RegistrationRelaxed>(
  11352         serde_json::json!({
  11353             "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11354             "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11355             "response": {
  11356                 "clientDataJSON": b64_cdata_json,
  11357                 "authenticatorData": b64_adata,
  11358                 "transports": [],
  11359                 "publicKey": base64url_nopad::encode(bad_pub_key.to_public_key_der().unwrap().as_bytes()),
  11360                 "publicKeyAlgorithm": -257i16,
  11361                 "attestationObject": b64_aobj,
  11362             },
  11363             "clientExtensionResults": {},
  11364             "type": "public-key"
  11365         })
  11366         .to_string()
  11367         .as_str()
  11368         )
  11369        .unwrap_err().to_string().into_bytes().get(..err.len()),
  11370         Some(err.as_slice())
  11371     );
  11372     // Missing `publicKey`.
  11373     drop(
  11374         serde_json::from_str::<RegistrationRelaxed>(
  11375             serde_json::json!({
  11376                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11377                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11378                 "response": {
  11379                     "clientDataJSON": b64_cdata_json,
  11380                     "authenticatorData": b64_adata,
  11381                     "transports": [],
  11382                     "publicKeyAlgorithm": -257i16,
  11383                     "attestationObject": b64_aobj,
  11384                 },
  11385                 "clientExtensionResults": {},
  11386                 "type": "public-key"
  11387             })
  11388             .to_string()
  11389             .as_str(),
  11390         )
  11391         .unwrap(),
  11392     );
  11393     // `null` `publicKey`.
  11394     drop(
  11395         serde_json::from_str::<RegistrationRelaxed>(
  11396             serde_json::json!({
  11397                 "id": "AAAAAAAAAAAAAAAAAAAAAA",
  11398                 "rawId": "AAAAAAAAAAAAAAAAAAAAAA",
  11399                 "response": {
  11400                     "clientDataJSON": b64_cdata_json,
  11401                     "authenticatorData": b64_adata,
  11402                     "transports": [],
  11403                     "publicKey": null,
  11404                     "publicKeyAlgorithm": -257i16,
  11405                     "attestationObject": b64_aobj,
  11406                 },
  11407                 "clientExtensionResults": {},
  11408                 "type": "public-key"
  11409             })
  11410             .to_string()
  11411             .as_str(),
  11412         )
  11413         .unwrap(),
  11414     );
  11415     // Base case is valid.
  11416     assert!(
  11417         serde_json::from_str::<CustomRegistration>(
  11418             serde_json::json!({
  11419                 "clientDataJSON": b64_cdata_json,
  11420                 "transports": [],
  11421                 "attestationObject": b64_aobj,
  11422                 "clientExtensionResults": {},
  11423                 "type": "public-key"
  11424             })
  11425             .to_string()
  11426             .as_str()
  11427         )
  11428         .is_ok_and(
  11429             |reg| reg.0.response.client_data_json == c_data_json.as_bytes()
  11430                 && reg.0.response.attestation_object_and_c_data_hash[..att_obj_len] == att_obj
  11431                 && reg.0.response.attestation_object_and_c_data_hash[att_obj_len..]
  11432                     == *Sha256::digest(c_data_json.as_bytes())
  11433                 && reg.0.response.transports.is_empty()
  11434                 && matches!(
  11435                     reg.0.authenticator_attachment,
  11436                     AuthenticatorAttachment::None
  11437                 )
  11438                 && reg.0.client_extension_results.cred_props.is_none()
  11439                 && reg.0.client_extension_results.prf.is_none()
  11440         )
  11441     );
  11442 }