//! Published RSA test keys, as the age-assurance corpus carries them (WAI //! `wai/live-conformance/age/`): RFC 7517 Appendix A.2's RSA key (the threshold 13 here), RFC //! 9500 §2.1's `testRSA2048` (16) and RFC 9578 Appendix A.2's issuer key (18). Their private //! exponents are published with them; they sign the tests' tokens directly, the signature the //! blind protocol of RFC 9578 §6 would also yield. They are test keys and nothing else. //! //! Shared by the unit tests of `src/age.rs` and `tests/age_admission.rs`; under `tests/common/`, //! so that cargo makes no test target of it. #![allow(dead_code)] pub const N_7517: &str = "d2fc7b6a0a1e6c67104aeb8f88b257669b4df679ddad099b5c4a6cd9a88015b5a133bf0b856c7871b6df000b554fceb3c2ed512bb68f145c6e8434752fab52a1cfc124408f79b58a4578c16428855789f7a249e384cb2d9fae2d67fd96fb926c198e077399fdc815c0af097dde5aadeff44de70e827f4878432439bfeeb96068d0474fc50d6d90bf3a98dfaf1040c89c02d692ab3b3c2896609d86fd73b774ce0740647ceeeaa310bd12f985a8eb9f59fdd426cea5b2120f4f2a34bcab764b7e6c54d6840238bcc40587a59e66ed1f33894577635c470af75cf92c20d1da43e1bfc419e222a6f0d0bb358c5e38f9cb050aeafe904814f1ac1aa49cca9ea0ca83"; pub const D_7517: &str = "5f8713b5e258fe09f81583ec5c1f2b7578b1e6fc2c83514b37913711a1ba449a151fe1cb2ca0fd33b771e68a3b1944649dc867ad1c1e5240bb853e5f24b33459b14028d2d6636befec1e8da974b352fc53d3f6127ea8a3c29dd14f3941682c56a78768164e4dda8f06cbf9c734aae8003224278ea9454a21b17cb06d178075868cc05b3db6ff1dfdc3d56378b4edadedf0c37a4cdc26d1d49ac26f6fe3b5220a5dd29396621bbc688cf2eee2c6e0d54da3c782014cd0739db252cc51caeba8d3f1b824baab24d068ec903264d7d678ab08f06ec9e7e23d960628b744bf94b3694656463c7e417399ed73d076c891fcf463a9aa9ce62da9cd17e237dc2a8002f1"; pub const N_9500: &str = "b0f9e81943a7ae9892aade17ca7c40f8744fed2f8148e6c8eaa27b7d001548fb5192ab28b56c5060b118ccd131e594874c6ca989b56c27296f09fb93a034df32e97c6ff0998cfd8e6f42dda58acd1fa97986f144f3d154d67650175e6854b3a952003bc06887b8455ac2b19f7b2f76504ebc98ec945571b07892150ddc6a74ca0fbcd35497ce81534daf9418844b13aea31f9d5a6b9557bbdf619efd4e887f2d42b8dd8bc987eae1bf89cab85ee21e356305df6c07a8838e3ef41c595dcce43dafc49123ef4d8abba93d3905e4028d7ba91484a27596e07b4b6ed992f077b524d3dcfe7ddd5549be7cce8da035cfa0b3fb8f9e46f732b2a86b460165c08f5313"; pub const D_9500: &str = "41188b20cfdbdbc2cf1ffe752dcbaa723906352e2615d49dce80597fcf0a05403bef00fa065182f72decfb596f4b0ce8ff5970baf07a89a519ecc816b2f4ffac5069af1b06bfef7bf6bcd79e4e81c8c5a3a7d9130dc3cfbadae5f6d288f9aee3f6ff92fae0f81af597bec96ae9fab9402cd5fe41f705bebdb47bb736d3fe6c5a51e0e20732a97b5e46c1cbdb26d74854c6b6604aed463735ff9076046557caf949bf448895c20432c1e09c014ea75660434f1a0f3be294babc5d530e6a10213f53b60375fc84a7573f2af1215584f5b4bda6d4e8f9e17a78d97e77b86da4a1846475318a7a10a561014effa23a81ec56e9e4109def8cb3f797223f7d8d0d4351"; pub const D_9578: &str = "2f309b7738b58cf779f0c915f822dfc9f490dbeadf1e7adfac578ffd5703c6bba2da9d5a49725889b7ba112f8c6ff30551d9473e000bc35c50e167ab7fa73a0c2b21965c4b59257c1ac06cbdcf28e863f6718ea8c29043c1c6da84629490fd0491bf52d172c959c1921b96949c725747b8a7c7871995fa0b9eb1107ba854c6c32a6f4747c5d1c304c7467d55b080aa233a3a52ffdf26114cbb541ffa6b696b7a096f8dcff69ca08ab58efb0fb753aa5185c73001696bbce8c099e3f435dcbbfe05e7dbaad23db2a659c23add521407f150b1af2d9054c4164229d6840b7a32a4f8481493ae8959cf0aea8def0c3c9f75b9a34c75718b7072c8dbab17cefeca49"; /// One key: its modulus, its private exponent and its SubjectPublicKeyInfo (RFC 9578 §6.5). pub struct TestKey { pub n: Vec, pub d: Vec, pub spki: Vec, } fn der(tag: u8, content: &[u8]) -> Vec { let mut o = vec![tag]; match content.len() { n if n < 0x80 => o.push(n as u8), n if n < 0x100 => o.extend_from_slice(&[0x81, n as u8]), n => o.extend_from_slice(&[0x82, (n >> 8) as u8, n as u8]), } o.extend_from_slice(content); o } fn der_uint(x: &[u8]) -> Vec { let x = &x[x.iter().position(|&b| b != 0).unwrap_or(x.len() - 1)..]; let mut c = if x[0] & 0x80 != 0 { vec![0] } else { vec![] }; c.extend_from_slice(x); der(0x02, &c) } fn spki_of(n: &[u8]) -> Vec { let rsa_key = der(0x30, &[der_uint(n), der_uint(&[1, 0, 1])].concat()); der(0x30, &[wai::age_assurance::PSS_ALGORITHM.to_vec(), der(0x03, &[&[0u8][..], &rsa_key].concat())].concat()) } fn key(n: &str, d: &str) -> TestKey { let n = hex::decode(n).unwrap(); TestKey { spki: spki_of(&n), n, d: hex::decode(d).unwrap() } } pub fn k13() -> TestKey { key(N_7517, D_7517) } pub fn k16() -> TestKey { key(N_9500, D_9500) } pub fn k18() -> TestKey { let spki = hex::decode(wai::live_ads::presentation_corpus::RFC9578_PKI).unwrap(); let (n, _) = wai::live_ads::presentation::rsa_public_key(&spki).unwrap(); let mut n = n.to_bytes_be(); while n.len() < 256 { n.insert(0, 0); } assert_eq!(spki_of(&n), spki, "RFC 9578 A.2's key, written as §6.5 has it"); TestKey { n, d: hex::decode(D_9578).unwrap(), spki } } /// A token of type 0x0002 for `challenge` under `k` (RFC 9577 §2.2.1, RFC 9578 §6), its nonce /// and its PSS salt drawn from `seed`. pub fn mint(k: &TestKey, challenge: &[u8], seed: u8) -> Vec { use sha2::{Digest, Sha256}; let mut t = vec![0, 2]; t.extend_from_slice(&Sha256::digest([b"nonce".as_slice(), &[seed]].concat())); t.extend_from_slice(&Sha256::digest(challenge)); t.extend_from_slice(&Sha256::digest(&k.spki)); let salt: [u8; 48] = [Sha256::digest([b"salt-a".as_slice(), &[seed]].concat()).to_vec(), Sha256::digest([b"salt-b".as_slice(), &[seed]].concat())[..16].to_vec()].concat().try_into().unwrap(); let sig = wai::live_ads::presentation::pss_sign(&k.n, &k.d, &t, &salt); t.extend_from_slice(&sig); t }