diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0d738c57..62be1e6d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,16 +48,6 @@ jobs: - run: cargo test --release --features getrandom - run: cargo test --release --features serde - doc: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: RustCrypto/actions/cargo-cache@master - - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - - run: cargo doc --all-features - minimal-versions: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml new file mode 100644 index 00000000..c67ebc50 --- /dev/null +++ b/.github/workflows/workspace.yml @@ -0,0 +1,47 @@ +name: Workspace + +on: + pull_request: + paths-ignore: + - README.md + push: + branches: master + paths-ignore: + - README.md + +jobs: + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: RustCrypto/actions/cargo-cache@master + - uses: dtolnay/rust-toolchain@master + with: + toolchain: 1.79.0 + components: clippy + - run: cargo clippy --all -- -D warnings + + fmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: RustCrypto/actions/cargo-cache@master + - uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + components: rustfmt + - run: cargo fmt --all -- --check + + doc: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: RustCrypto/actions/cargo-cache@master + - uses: dtolnay/rust-toolchain@master + with: + # We need Nightly for doc_auto_cfg + toolchain: nightly-2024-06-25 + - uses: Swatinem/rust-cache@v2 + - env: + RUSTDOCFLAGS: "-Dwarnings --cfg docsrs" + run: cargo doc --no-deps --features std,pem,serde,hazmat,sha2 diff --git a/Cargo.lock b/Cargo.lock index 3957220e..6ecd643e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "base16ct" @@ -121,9 +121,9 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.6.0-pre.12" +version = "0.6.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1943d7beadd9ce2b25f3bae73b9e9336fccc1edf38bdec1ed58d3aa183989e11" +checksum = "cf4d6fbc60a5516ff886af2c5994fb2bdfa6fbe2168468100bd87e6c09caf08c" dependencies = [ "num-traits", "rand_core", @@ -198,9 +198,9 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys", @@ -208,9 +208,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fnv" @@ -230,9 +230,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -290,9 +290,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libm" @@ -302,15 +302,15 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -381,9 +381,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -416,9 +416,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -464,9 +464,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "rsa" @@ -487,6 +487,7 @@ dependencies = [ "rand_xorshift", "serde", "serde_test", + "serdect", "sha1", "sha2 0.11.0-pre.3", "sha3", @@ -498,9 +499,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags", "errno", @@ -543,18 +544,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.197" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", @@ -651,9 +652,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "2.0.53" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -722,13 +723,14 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -737,48 +739,54 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/Cargo.toml b/Cargo.toml index 914c201e..9e950619 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ crypto-primes = { version = "0.6.0-pre.0" } # optional dependencies sha1 = { version = "=0.11.0-pre.3", optional = true, default-features = false, features = ["oid"] } +serdect = { version = "0.2.0", optional = true } sha2 = { version = "=0.11.0-pre.3", optional = true, default-features = false, features = ["oid"] } serde = { version = "1.0.184", optional = true, default-features = false, features = ["derive"] } @@ -50,7 +51,7 @@ name = "key" default = ["std", "pem"] hazmat = [] getrandom = ["rand_core/getrandom"] -serde = ["dep:serde", "crypto-bigint/serde"] +serde = ["dep:serde", "dep:serdect", "crypto-bigint/serde"] pem = ["pkcs1/pem", "pkcs8/pem"] pkcs5 = ["pkcs8/encryption"] std = ["digest/std", "pkcs1/std", "pkcs8/std", "rand_core/std", "signature/std"] diff --git a/benches/key.rs b/benches/key.rs index 39260388..bc1e4bca 100644 --- a/benches/key.rs +++ b/benches/key.rs @@ -10,19 +10,67 @@ use rsa::{Pkcs1v15Encrypt, Pkcs1v15Sign, RsaPrivateKey}; use sha2::{Digest, Sha256}; use test::Bencher; -const DECRYPT_VAL: &'static str = - "XW4qfrpQDarEMBfPyIYE9UvuOFkbBi0tiGYbIOJPLMNe/LWuPD0BQ7ceqlOlPPcKLinYz0DlnqW3It/V7ae59zw9afA3YIWdq0Ut2BnYL+aJixnqaP+PjsQNcHg6axCF11iNQ4jpXrZDiQcI+q9EEzZDTMsiMxtjfgBQUd8LHT87YoQXDWaFPCVpliACMc8aUk442kH1tc4jEuXwjEjFErvAM/J7VizCdU/dnKrlq2mBDzvZ6hxY9TYHFB/zY6DZPJAgEMUxYWCR9xPJ7X256DV1Kt0Ht33DWoFcgh/pPLM1q9pK0HVxCdclXfZOeCqlrLgZ5Gxv5DM4BtV7Z4m85w=="; +const DECRYPT_VAL: &str = "\ + XW4qfrpQDarEMBfPyIYE9UvuOFkbBi0tiGYbIOJPLMNe/LWuPD0BQ7ceqlOlPPcK\ + LinYz0DlnqW3It/V7ae59zw9afA3YIWdq0Ut2BnYL+aJixnqaP+PjsQNcHg6axCF\ + 11iNQ4jpXrZDiQcI+q9EEzZDTMsiMxtjfgBQUd8LHT87YoQXDWaFPCVpliACMc8a\ + Uk442kH1tc4jEuXwjEjFErvAM/J7VizCdU/dnKrlq2mBDzvZ6hxY9TYHFB/zY6DZ\ + PJAgEMUxYWCR9xPJ7X256DV1Kt0Ht33DWoFcgh/pPLM1q9pK0HVxCdclXfZOeCql\ + rLgZ5Gxv5DM4BtV7Z4m85w=="; fn get_key() -> RsaPrivateKey { RsaPrivateKey::from_components( - BigUint::from_str_radix("14314132931241006650998084889274020608918049032671858325988396851334124245188214251956198731333464217832226406088020736932173064754214329009979944037640912127943488972644697423190955557435910767690712778463524983667852819010259499695177313115447116110358524558307947613422897787329221478860907963827160223559690523660574329011927531289655711860504630573766609239332569210831325633840174683944553667352219670930408593321661375473885147973879086994006440025257225431977751512374815915392249179976902953721486040787792801849818254465486633791826766873076617116727073077821584676715609985777563958286637185868165868520557", 10).unwrap(), + BigUint::from_str_radix( + "1431413293124100665099808488927402060891804903267185832598839685\ + 1334124245188214251956198731333464217832226406088020736932173064\ + 7542143290099799440376409121279434889726446974231909555574359107\ + 6769071277846352498366785281901025949969517731311544711611035852\ + 4558307947613422897787329221478860907963827160223559690523660574\ + 3290119275312896557118605046305737666092393325692108313256338401\ + 7468394455366735221967093040859332166137547388514797387908699400\ + 6440025257225431977751512374815915392249179976902953721486040787\ + 7928018498182544654866337918267668730766171167270730778215846767\ + 15609985777563958286637185868165868520557", + 10, + ) + .unwrap(), BigUint::from_u32(3).unwrap(), - BigUint::from_str_radix("9542755287494004433998723259516013739278699355114572217325597900889416163458809501304132487555642811888150937392013824621448709836142886006653296025093941418628992648429798282127303704957273845127141852309016655778568546006839666463451542076964744073572349705538631742281931858219480985907271975884773482372966847639853897890615456605598071088189838676728836833012254065983259638538107719766738032720239892094196108713378822882383694456030043492571063441943847195939549773271694647657549658603365629458610273821292232646334717612674519997533901052790334279661754176490593041941863932308687197618671528035670452762731", 10).unwrap(), + BigUint::from_str_radix( + "9542755287494004433998723259516013739278699355114572217325597900\ + 8894161634588095013041324875556428118881509373920138246214487098\ + 3614288600665329602509394141862899264842979828212730370495727384\ + 5127141852309016655778568546006839666463451542076964744073572349\ + 7055386317422819318582194809859072719758847734823729668476398538\ + 9789061545660559807108818983867672883683301225406598325963853810\ + 7719766738032720239892094196108713378822882383694456030043492571\ + 0634419438471959395497732716946476575496586033656294586102738212\ + 9223264633471761267451999753390105279033427966175417649059304194\ + 1863932308687197618671528035670452762731", + 10, + ) + .unwrap(), vec![ - BigUint::from_str_radix("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433",10).unwrap(), - BigUint::from_str_radix("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029", 10).unwrap() + BigUint::from_str_radix( + "1309032551829967224267716136060777552955833291350673401529471728\ + 6841580902753737630619317962429887421560827080205434760983677647\ + 3930072411958753044562214537013874103802006369634761074377213995\ + 9838767887180338501537194216954687042766949830326444169308790939\ + 14927146648402139231293035971427838068945045019075433", + 10, + ) + .unwrap(), + BigUint::from_str_radix( + "1093489456104854535775747676525274729242892295382866496612409389\ + 8802036700547572798825343864756095857350615944953879354047282981\ + 5903949343191091817779240101054552748665267574271163617694640513\ + 5496938413378206027265967563510061495188309322612466987663553478\ + 98158548465400674856021497190430791824869615170301029", + 10, + ) + .unwrap(), ], - ).unwrap() + ) + .unwrap() } #[bench] diff --git a/src/algorithms/mgf.rs b/src/algorithms/mgf.rs index 5dc6eff9..009a5030 100644 --- a/src/algorithms/mgf.rs +++ b/src/algorithms/mgf.rs @@ -9,7 +9,7 @@ pub(crate) fn mgf1_xor(out: &mut [u8], digest: &mut dyn DynDigest, seed: &[u8]) let mut counter = [0u8; 4]; let mut i = 0; - const MAX_LEN: u64 = core::u32::MAX as u64 + 1; + const MAX_LEN: u64 = u32::MAX as u64 + 1; assert!(out.len() as u64 <= MAX_LEN); while i < out.len() { @@ -43,7 +43,7 @@ where let mut counter = [0u8; 4]; let mut i = 0; - const MAX_LEN: u64 = core::u32::MAX as u64 + 1; + const MAX_LEN: u64 = u32::MAX as u64 + 1; assert!(out.len() as u64 <= MAX_LEN); while i < out.len() { diff --git a/src/algorithms/oaep.rs b/src/algorithms/oaep.rs index 0ba2de9d..37bfaa3e 100644 --- a/src/algorithms/oaep.rs +++ b/src/algorithms/oaep.rs @@ -11,9 +11,12 @@ use zeroize::Zeroizing; use super::mgf::{mgf1_xor, mgf1_xor_digest}; use crate::errors::{Error, Result}; -// 2**61 -1 (pow is not const yet) -// TODO: This is the maximum for SHA-1, unclear from the RFC what the values are for other hashing functions. -const MAX_LABEL_LEN: u64 = 2_305_843_009_213_693_951; +/// Maximum label size (2^64 bits) for SHA-1 and SHA-256 hash functions. +/// +/// In theory, other hash functions (e.g. SHA-512 and SHA-3) can process longer labels, +/// but such huge inputs are practically impossible on one machine, so we use this limit +/// for all hash functions. +const MAX_LABEL_LEN: u64 = 1 << 61; #[inline] fn encrypt_internal( @@ -65,7 +68,7 @@ pub(crate) fn oaep_encrypt( let h_size = digest.output_size(); let label = label.unwrap_or_default(); - if label.len() as u64 > MAX_LABEL_LEN { + if label.len() as u64 >= MAX_LABEL_LEN { return Err(Error::LabelTooLong); } @@ -99,7 +102,7 @@ pub(crate) fn oaep_encrypt_digest< let h_size = ::output_size(); let label = label.unwrap_or_default(); - if label.len() as u64 > MAX_LABEL_LEN { + if label.len() as u64 >= MAX_LABEL_LEN { return Err(Error::LabelTooLong); } @@ -133,7 +136,7 @@ pub(crate) fn oaep_decrypt( let h_size = digest.output_size(); let label = label.unwrap_or_default(); - if label.len() as u64 > MAX_LABEL_LEN { + if label.len() as u64 >= MAX_LABEL_LEN { return Err(Error::Decryption); } @@ -173,7 +176,7 @@ pub(crate) fn oaep_decrypt_digest( let h_size = ::output_size(); let label = label.unwrap_or_default(); - if label.len() as u64 > MAX_LABEL_LEN { + if label.len() as u64 >= MAX_LABEL_LEN { return Err(Error::LabelTooLong); } diff --git a/src/encoding.rs b/src/encoding.rs index 5ecf6517..cb4ff1d4 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -9,16 +9,31 @@ use crate::{ }; use core::convert::{TryFrom, TryInto}; use crypto_bigint::{BoxedUint, NonZero, Odd}; -use pkcs8::{der::Encode, Document, EncodePrivateKey, EncodePublicKey, SecretDocument}; +use pkcs8::{ + der::Encode, Document, EncodePrivateKey, EncodePublicKey, ObjectIdentifier, SecretDocument, +}; use zeroize::Zeroizing; -/// Verify that the `AlgorithmIdentifier` for a key is correct. -fn verify_algorithm_id(algorithm: &pkcs8::AlgorithmIdentifierRef) -> pkcs8::spki::Result<()> { - algorithm.assert_algorithm_oid(pkcs1::ALGORITHM_OID)?; +/// ObjectID for the RSA PSS keys +pub const ID_RSASSA_PSS: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10"); - if algorithm.parameters_any()? != pkcs8::der::asn1::Null.into() { - return Err(pkcs8::spki::Error::KeyMalformed); - } +/// Verify that the `AlgorithmIdentifier` for a key is correct. +pub(crate) fn verify_algorithm_id( + algorithm: &pkcs8::AlgorithmIdentifierRef, +) -> pkcs8::spki::Result<()> { + match algorithm.oid { + pkcs1::ALGORITHM_OID => { + if algorithm.parameters_any()? != pkcs8::der::asn1::Null.into() { + return Err(pkcs8::spki::Error::KeyMalformed); + } + } + ID_RSASSA_PSS => { + if algorithm.parameters.is_some() { + return Err(pkcs8::spki::Error::KeyMalformed); + } + } + _ => return Err(pkcs8::spki::Error::OidUnknown { oid: algorithm.oid }), + }; Ok(()) } diff --git a/src/key.rs b/src/key.rs index 97b4e6bd..28aac6f4 100644 --- a/src/key.rs +++ b/src/key.rs @@ -4,9 +4,13 @@ use core::hash::{Hash, Hasher}; use crypto_bigint::modular::{BoxedMontyForm, BoxedMontyParams}; use crypto_bigint::{BoxedUint, Integer, InvMod, NonZero, Odd}; use rand_core::CryptoRngCore; -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use zeroize::{Zeroize, ZeroizeOnDrop}; +#[cfg(feature = "serde")] +use { + pkcs8::{DecodePrivateKey, EncodePrivateKey}, + serdect::serde::{de, ser, Deserialize, Serialize}, + spki::{DecodePublicKey, EncodePublicKey}, +}; use crate::algorithms::generate::generate_multi_prime_key_with_exp; use crate::algorithms::rsa::{ @@ -21,7 +25,6 @@ use crate::traits::{PaddingScheme, SignatureScheme}; /// Represents the public part of an RSA key. #[derive(Debug, Clone)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct RsaPublicKey { /// Modulus: product of prime numbers `p` and `q` n: NonZero, @@ -54,7 +57,6 @@ impl Hash for RsaPublicKey { /// Represents a whole RSA key, public and private parts. #[derive(Debug, Clone)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct RsaPrivateKey { /// Public components of the private key. pubkey_components: RsaPublicKey, @@ -63,7 +65,6 @@ pub struct RsaPrivateKey { /// Prime factors of N, contains >= 2 elements. pub(crate) primes: Vec, /// precomputed values to speed up private operations - #[cfg_attr(feature = "serde", serde(skip))] pub(crate) precomputed: Option, } @@ -582,6 +583,50 @@ pub(crate) fn reduce(n: &BoxedUint, p: BoxedMontyParams) -> BoxedMontyForm { BoxedMontyForm::new(n_reduced, p) } +#[cfg(feature = "serde")] +impl Serialize for RsaPublicKey { + fn serialize(&self, serializer: S) -> core::prelude::v1::Result + where + S: serdect::serde::Serializer, + { + let der = self.to_public_key_der().map_err(ser::Error::custom)?; + serdect::slice::serialize_hex_lower_or_bin(&der, serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for RsaPublicKey { + fn deserialize(deserializer: D) -> core::prelude::v1::Result + where + D: serdect::serde::Deserializer<'de>, + { + let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; + Self::from_public_key_der(&der_bytes).map_err(de::Error::custom) + } +} + +#[cfg(feature = "serde")] +impl Serialize for RsaPrivateKey { + fn serialize(&self, serializer: S) -> core::prelude::v1::Result + where + S: ser::Serializer, + { + let der = self.to_pkcs8_der().map_err(ser::Error::custom)?; + serdect::slice::serialize_hex_lower_or_bin(&der.as_bytes(), serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for RsaPrivateKey { + fn deserialize(deserializer: D) -> core::prelude::v1::Result + where + D: de::Deserializer<'de>, + { + let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; + Self::from_pkcs8_der(&der_bytes).map_err(de::Error::custom) + } +} + #[cfg(test)] mod tests { use super::*; @@ -708,81 +753,106 @@ mod tests { #[cfg(feature = "serde")] fn test_serde() { use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; - use serde_test::{assert_tokens, Token}; + use serde_test::{assert_tokens, Configure, Token}; let mut rng = ChaCha8Rng::from_seed([42; 32]); let priv_key = RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"); - let priv_tokens = [ - Token::Struct { - name: "RsaPrivateKey", - len: 3, - }, - Token::Str("pubkey_components"), - Token::Struct { - name: "RsaPublicKey", - len: 2, - }, - Token::Str("n"), - Token::Seq { len: Some(2) }, - Token::U32(3814409919), - Token::U32(3429654832), - Token::SeqEnd, - Token::Str("e"), - Token::Seq { len: Some(1) }, - Token::U32(65537), - Token::SeqEnd, - Token::StructEnd, - Token::Str("d"), - Token::Seq { len: Some(2) }, - Token::U32(1482162201), - Token::U32(1675500232), - Token::SeqEnd, - Token::Str("primes"), - Token::Seq { len: Some(2) }, - Token::Seq { len: Some(1) }, - Token::U32(4133289821), - Token::SeqEnd, - Token::Seq { len: Some(1) }, - Token::U32(3563808971), - Token::SeqEnd, - Token::SeqEnd, - Token::StructEnd, - ]; - assert_tokens(&priv_key, &priv_tokens); - - let priv_tokens = [ - Token::Struct { - name: "RsaPublicKey", - len: 2, - }, - Token::Str("n"), - Token::Seq { len: Some(2) }, - Token::U32(3814409919), - Token::U32(3429654832), - Token::SeqEnd, - Token::Str("e"), - Token::Seq { len: Some(1) }, - Token::U32(65537), - Token::SeqEnd, - Token::StructEnd, - ]; - assert_tokens(&RsaPublicKey::from(priv_key), &priv_tokens); + let priv_tokens = [Token::Str( + "3054020100300d06092a864886f70d01010105000440303e020100020900cc6c\ + 6130e35b46bf0203010001020863de1ac858580019020500f65cff5d020500d4\ + 6b68cb02046d9a09f102047b4e3a4f020500f45065cc", + )]; + assert_tokens(&priv_key.clone().readable(), &priv_tokens); + + let priv_tokens = [Token::Str( + "3024300d06092a864886f70d01010105000313003010020900cc6c6130e35b46bf0203010001", + )]; + assert_tokens( + &RsaPublicKey::from(priv_key.clone()).readable(), + &priv_tokens, + ); } #[test] fn invalid_coeff_private_key_regression() { use base64ct::{Base64, Encoding}; - let n = Base64::decode_vec("wC8GyQvTCZOK+iiBR5fGQCmzRCTWX9TQ3aRG5gGFk0wB6EFoLMAyEEqeG3gS8xhAm2rSWYx9kKufvNat3iWlbSRVqkcbpVAYlj2vTrpqDpJl+6u+zxFYoUEBevlJJkAhl8EuCccOA30fVpcfRvXPTtvRd3yFT9E9EwZljtgSI02w7gZwg7VIxaGeajh5Euz6ZVQZ+qNRKgXrRC7gPRqVyI6Dt0Jc+Su5KBGNn0QcPDzOahWha1ieaeMkFisZ9mdpsJoZ4tw5eicLaUomKzALHXQVt+/rcZSrCd6/7uUo11B/CYBM4UfSpwXaL88J9AE6A5++no9hmJzaF2LLp+Qwx4yY3j9TDutxSAjsraxxJOGZ3XyA9nG++Ybt3cxZ5fP7ROjxCfROBmVv5dYn0O9OBIqYeCH6QraNpZMadlLNIhyMv8Y+P3r5l/PaK4VJaEi5pPosnEPawp0W0yZDzmjk2z1LthaRx0aZVrAjlH0Rb/6goLUQ9qu1xsDtQVVpN4A89ZUmtTWORnnJr0+595eHHxssd2gpzqf4bPjNITdAEuOCCtpvyi4ls23zwuzryUYjcUOEnsXNQ+DrZpLKxdtsD/qNV/j1hfeyBoPllC3cV+6bcGOFcVGbjYqb+Kw1b0+jL69RSKQqgmS+qYqr8c48nDRxyq3QXhR8qtzUwBFSLVk=").unwrap(); + let n = Base64::decode_vec( + "wC8GyQvTCZOK+iiBR5fGQCmzRCTWX9TQ3aRG5gGFk0wB6EFoLMAyEEqeG3gS8xhA\ + m2rSWYx9kKufvNat3iWlbSRVqkcbpVAYlj2vTrpqDpJl+6u+zxFYoUEBevlJJkAh\ + l8EuCccOA30fVpcfRvXPTtvRd3yFT9E9EwZljtgSI02w7gZwg7VIxaGeajh5Euz6\ + ZVQZ+qNRKgXrRC7gPRqVyI6Dt0Jc+Su5KBGNn0QcPDzOahWha1ieaeMkFisZ9mdp\ + sJoZ4tw5eicLaUomKzALHXQVt+/rcZSrCd6/7uUo11B/CYBM4UfSpwXaL88J9AE6\ + A5++no9hmJzaF2LLp+Qwx4yY3j9TDutxSAjsraxxJOGZ3XyA9nG++Ybt3cxZ5fP7\ + ROjxCfROBmVv5dYn0O9OBIqYeCH6QraNpZMadlLNIhyMv8Y+P3r5l/PaK4VJaEi5\ + pPosnEPawp0W0yZDzmjk2z1LthaRx0aZVrAjlH0Rb/6goLUQ9qu1xsDtQVVpN4A8\ + 9ZUmtTWORnnJr0+595eHHxssd2gpzqf4bPjNITdAEuOCCtpvyi4ls23zwuzryUYj\ + cUOEnsXNQ+DrZpLKxdtsD/qNV/j1hfeyBoPllC3cV+6bcGOFcVGbjYqb+Kw1b0+j\ + L69RSKQqgmS+qYqr8c48nDRxyq3QXhR8qtzUwBFSLVk=", + ) + .unwrap(); let e = Base64::decode_vec("AQAB").unwrap(); - let d = Base64::decode_vec("qQazSQ+FRN7nVK1bRsROMRB8AmsDwLVEHivlz1V3Td2Dr+oW3YUMgxedhztML1IdQJPq/ad6qErJ6yRFNySVIjDaxzBTOEoB1eHa1btOnBJWb8rVvvjaorixvJ6Tn3i4EuhsvVy9DoR1k4rGj3qSIiFjUVvLRDAbLyhpGgEfsr0Z577yJmTC5E8JLRMOKX8Tmxsk3jPVpsgd65Hu1s8S/ZmabwuHCf9SkdMeY/1bd/9i7BqqJeeDLE4B5x1xcC3z3scqDUTzqGO+vZPhjgprPDRlBamVwgenhr7KwCn8iaLamFinRVwOAag8BeBqOJj7lURiOsKQa9FIX1kdFUS1QMQxgtPycLjkbvCJjriqT7zWKsmJ7l8YLs6Wmm9/+QJRwNCEVdMTXKfCP1cJjudaiskEQThfUldtgu8gUDNYbQ/Filb2eKfiX4h1TiMxZqUZHVZyb9nShbQoXJ3vj/MGVF0QM8TxhXM8r2Lv9gDYU5t9nQlUMLhs0jVjai48jHABbFNyH3sEcOmJOIwJrCXw1dzG7AotwyaEVUHOmL04TffmwCFfnyrLjbFgnyOeoyIIBYjcY7QFRm/9nupXMTH5hZ2qrHfCJIp0KK4tNBdQqmnHapFl5l6Le1s4qBS5bEIzjitobLvAFm9abPlDGfxmY6mlrMK4+nytwF9Ct7wc1AE=").unwrap(); - let primes = vec![ - Base64::decode_vec("9kQWEAzsbzOcdPa+s5wFfw4XDd7bB1q9foZ31b1+TNjGNxbSBCFlDF1q98vwpV6nM8bWDh/wtbNoETSQDgpEnYOQ26LWEw6YY1+q1Q2GGEFceYUf+Myk8/vTc8TN6Zw0bKZBWy10Qo8h7xk4JpzuI7NcxvjJYTkS9aErFxi3vVH0aiZC0tmfaCqr8a2rJxyVwqreRpOjwAWrotMsf2wGsF4ofx5ScoFy5GB5fJkkdOrW1LyTvZAUCX3cstPr19+TNC5zZOk7WzZatnCkN5H5WzalWtZuu0oVL205KPOa3R8V2yv5e6fm0v5fTmqSuvjmaMJLXCN4QJkmIzojO99ckQ==").unwrap(), - Base64::decode_vec("x8exdMjVA2CiI+Thx7loHtVcevoeE2sZ7btRVAvmBqo+lkHwxb7FHRnWvuj6eJSlD2f0T50EewIhhiW3R9BmktCk7hXjbSCnC1u9Oxc1IAUm/7azRqyfCMx43XhLxpD+xkBCpWkKDLxGczsRwTuaP3lKS3bSdBrNlGmdblubvVBIq4YZ2vXVlnYtza0cS+dgCK7BGTqUsrCUd/ZbIvwcwZkZtpkhj1KQfto9X/0OMurBzAqbkeq1cyRHXHkOfN/qbUIIRqr9Ii7Eswf9Vk8xp2O1Nt8nzcYS9PFD12M5eyaeFEkEYfpNMNGuTzp/31oqVjbpoCxS6vuWAZyADxhISQ==").unwrap(), - Base64::decode_vec("is7d0LY4HoXszlC2NO7gejkq7XqL4p1W6hZJPYTNx+r37t1CC2n3Vvzg6kNdpRixDhIpXVTLjN9O7UO/XuqSumYKJIKoP52eb4Tg+a3hw5Iz2Zsb5lUTNSLgkQSBPAf71LHxbL82JL4g1nBUog8ae60BwnVArThKY4EwlJguGNw09BAU4lwf6csDl/nX2vfVwiAloYpeZkHL+L8m+bueGZM5KE2jEz+7ztZCI+T+E5i69rZEYDjx0lfLKlEhQlCW3HbCPELqXgNJJkRfi6MP9kXa9lSfnZmoT081RMvqonB/FUa4HOcKyCrw9XZEtnbNCIdbitfDVEX+pSSD7596wQ==").unwrap(), - Base64::decode_vec("GPs0injugfycacaeIP5jMa/WX55VEnKLDHom4k6WlfDF4L4gIGoJdekcPEUfxOI5faKvHyFwRP1wObkPoRBDM0qZxRfBl4zEtpvjHrd5MibSyJkM8+J0BIKk/nSjbRIGeb3hV5O56PvGB3S0dKhCUnuVObiC+ne7izplsD4OTG70l1Yud33UFntyoMxrxGYLUSqhBMmZfHquJg4NOWOzKNY/K+EcHDLj1Kjvkcgv9Vf7ocsVxvpFdD9uGPceQ6kwRDdEl6mb+6FDgWuXVyqR9+904oanEIkbJ7vfkthagLbEf57dyG6nJlqh5FBZWxGIR72YGypPuAh7qnnqXXjY2Q==").unwrap(), - Base64::decode_vec("CUWC+hRWOT421kwRllgVjy6FYv6jQUcgDNHeAiYZnf5HjS9iK2ki7v8G5dL/0f+Yf+NhE/4q8w4m8go51hACrVpP1p8GJDjiT09+RsOzITsHwl+ceEKoe56ZW6iDHBLlrNw5/MtcYhKpjNU9KJ2udm5J/c9iislcjgckrZG2IB8ADgXHMEByZ5DgaMl4AKZ1Gx8/q6KftTvmOT5rNTMLi76VN5KWQcDWK/DqXiOiZHM7Nr4dX4me3XeRgABJyNR8Fqxj3N1+HrYLe/zs7LOaK0++F9Ul3tLelhrhsvLxei3oCZkF9A/foD3on3luYA+1cRcxWpSY3h2J4/22+yo4+Q==").unwrap(), + let d = Base64::decode_vec( + "qQazSQ+FRN7nVK1bRsROMRB8AmsDwLVEHivlz1V3Td2Dr+oW3YUMgxedhztML1Id\ + QJPq/ad6qErJ6yRFNySVIjDaxzBTOEoB1eHa1btOnBJWb8rVvvjaorixvJ6Tn3i4\ + EuhsvVy9DoR1k4rGj3qSIiFjUVvLRDAbLyhpGgEfsr0Z577yJmTC5E8JLRMOKX8T\ + mxsk3jPVpsgd65Hu1s8S/ZmabwuHCf9SkdMeY/1bd/9i7BqqJeeDLE4B5x1xcC3z\ + 3scqDUTzqGO+vZPhjgprPDRlBamVwgenhr7KwCn8iaLamFinRVwOAag8BeBqOJj7\ + lURiOsKQa9FIX1kdFUS1QMQxgtPycLjkbvCJjriqT7zWKsmJ7l8YLs6Wmm9/+QJR\ + wNCEVdMTXKfCP1cJjudaiskEQThfUldtgu8gUDNYbQ/Filb2eKfiX4h1TiMxZqUZ\ + HVZyb9nShbQoXJ3vj/MGVF0QM8TxhXM8r2Lv9gDYU5t9nQlUMLhs0jVjai48jHAB\ + bFNyH3sEcOmJOIwJrCXw1dzG7AotwyaEVUHOmL04TffmwCFfnyrLjbFgnyOeoyII\ + BYjcY7QFRm/9nupXMTH5hZ2qrHfCJIp0KK4tNBdQqmnHapFl5l6Le1s4qBS5bEIz\ + jitobLvAFm9abPlDGfxmY6mlrMK4+nytwF9Ct7wc1AE=", + ) + .unwrap(); + let primes = [ + Base64::decode_vec( + "9kQWEAzsbzOcdPa+s5wFfw4XDd7bB1q9foZ31b1+TNjGNxbSBCFlDF1q98vwpV6n\ + M8bWDh/wtbNoETSQDgpEnYOQ26LWEw6YY1+q1Q2GGEFceYUf+Myk8/vTc8TN6Zw0\ + bKZBWy10Qo8h7xk4JpzuI7NcxvjJYTkS9aErFxi3vVH0aiZC0tmfaCqr8a2rJxyV\ + wqreRpOjwAWrotMsf2wGsF4ofx5ScoFy5GB5fJkkdOrW1LyTvZAUCX3cstPr19+T\ + NC5zZOk7WzZatnCkN5H5WzalWtZuu0oVL205KPOa3R8V2yv5e6fm0v5fTmqSuvjm\ + aMJLXCN4QJkmIzojO99ckQ==", + ) + .unwrap(), + Base64::decode_vec( + "x8exdMjVA2CiI+Thx7loHtVcevoeE2sZ7btRVAvmBqo+lkHwxb7FHRnWvuj6eJSl\ + D2f0T50EewIhhiW3R9BmktCk7hXjbSCnC1u9Oxc1IAUm/7azRqyfCMx43XhLxpD+\ + xkBCpWkKDLxGczsRwTuaP3lKS3bSdBrNlGmdblubvVBIq4YZ2vXVlnYtza0cS+dg\ + CK7BGTqUsrCUd/ZbIvwcwZkZtpkhj1KQfto9X/0OMurBzAqbkeq1cyRHXHkOfN/q\ + bUIIRqr9Ii7Eswf9Vk8xp2O1Nt8nzcYS9PFD12M5eyaeFEkEYfpNMNGuTzp/31oq\ + VjbpoCxS6vuWAZyADxhISQ==", + ) + .unwrap(), + Base64::decode_vec( + "is7d0LY4HoXszlC2NO7gejkq7XqL4p1W6hZJPYTNx+r37t1CC2n3Vvzg6kNdpRix\ + DhIpXVTLjN9O7UO/XuqSumYKJIKoP52eb4Tg+a3hw5Iz2Zsb5lUTNSLgkQSBPAf7\ + 1LHxbL82JL4g1nBUog8ae60BwnVArThKY4EwlJguGNw09BAU4lwf6csDl/nX2vfV\ + wiAloYpeZkHL+L8m+bueGZM5KE2jEz+7ztZCI+T+E5i69rZEYDjx0lfLKlEhQlCW\ + 3HbCPELqXgNJJkRfi6MP9kXa9lSfnZmoT081RMvqonB/FUa4HOcKyCrw9XZEtnbN\ + CIdbitfDVEX+pSSD7596wQ==", + ) + .unwrap(), + Base64::decode_vec( + "GPs0injugfycacaeIP5jMa/WX55VEnKLDHom4k6WlfDF4L4gIGoJdekcPEUfxOI5\ + faKvHyFwRP1wObkPoRBDM0qZxRfBl4zEtpvjHrd5MibSyJkM8+J0BIKk/nSjbRIG\ + eb3hV5O56PvGB3S0dKhCUnuVObiC+ne7izplsD4OTG70l1Yud33UFntyoMxrxGYL\ + USqhBMmZfHquJg4NOWOzKNY/K+EcHDLj1Kjvkcgv9Vf7ocsVxvpFdD9uGPceQ6kw\ + RDdEl6mb+6FDgWuXVyqR9+904oanEIkbJ7vfkthagLbEf57dyG6nJlqh5FBZWxGI\ + R72YGypPuAh7qnnqXXjY2Q==", + ) + .unwrap(), + Base64::decode_vec( + "CUWC+hRWOT421kwRllgVjy6FYv6jQUcgDNHeAiYZnf5HjS9iK2ki7v8G5dL/0f+Y\ + f+NhE/4q8w4m8go51hACrVpP1p8GJDjiT09+RsOzITsHwl+ceEKoe56ZW6iDHBLl\ + rNw5/MtcYhKpjNU9KJ2udm5J/c9iislcjgckrZG2IB8ADgXHMEByZ5DgaMl4AKZ1\ + Gx8/q6KftTvmOT5rNTMLi76VN5KWQcDWK/DqXiOiZHM7Nr4dX4me3XeRgABJyNR8\ + Fqxj3N1+HrYLe/zs7LOaK0++F9Ul3tLelhrhsvLxei3oCZkF9A/foD3on3luYA+1\ + cRcxWpSY3h2J4/22+yo4+Q==", + ) + .unwrap(), ]; let mut e_raw = [0u8; 8]; diff --git a/src/oaep/decrypting_key.rs b/src/oaep/decrypting_key.rs index eacff38e..83ab2824 100644 --- a/src/oaep/decrypting_key.rs +++ b/src/oaep/decrypting_key.rs @@ -11,12 +11,15 @@ use alloc::{ use core::marker::PhantomData; use digest::{Digest, FixedOutputReset}; use rand_core::CryptoRngCore; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; use zeroize::ZeroizeOnDrop; /// Decryption key for PKCS#1 v1.5 decryption as described in [RFC8017 § 7.1]. /// /// [RFC8017 § 7.1]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1 #[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct DecryptingKey where D: Digest, @@ -94,3 +97,44 @@ where MGD: Digest + FixedOutputReset, { } + +impl PartialEq for DecryptingKey +where + D: Digest, + MGD: Digest + FixedOutputReset, +{ + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner && self.label == other.label + } +} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "serde")] + fn test_serde() { + use super::*; + use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; + use serde_test::{assert_tokens, Configure, Token}; + use sha2::Sha256; + + let mut rng = ChaCha8Rng::from_seed([42; 32]); + let decrypting_key = DecryptingKey::::new( + RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"), + ); + + let tokens = [ + Token::Struct { name: "DecryptingKey", len: 4 }, + Token::Str("inner"), + Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900cc6c6130e35b46bf0203010001020863de1ac858580019020500f65cff5d020500d46b68cb02046d9a09f102047b4e3a4f020500f45065cc"), + Token::Str("label"), + Token::None, + Token::Str("phantom"), + Token::UnitStruct { name: "PhantomData", }, + Token::Str("mg_phantom"), + Token::UnitStruct { name: "PhantomData", }, + Token::StructEnd, + ]; + assert_tokens(&decrypting_key.readable(), &tokens); + } +} diff --git a/src/oaep/encrypting_key.rs b/src/oaep/encrypting_key.rs index 0951e652..9a9ae290 100644 --- a/src/oaep/encrypting_key.rs +++ b/src/oaep/encrypting_key.rs @@ -7,11 +7,14 @@ use alloc::{ use core::marker::PhantomData; use digest::{Digest, FixedOutputReset}; use rand_core::CryptoRngCore; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; /// Encryption key for PKCS#1 v1.5 encryption as described in [RFC8017 § 7.1]. /// /// [RFC8017 § 7.1]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1 #[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct EncryptingKey where D: Digest, @@ -62,3 +65,52 @@ where encrypt_digest::<_, D, MGD>(rng, &self.inner, msg, self.label.as_ref().cloned()) } } + +impl PartialEq for EncryptingKey +where + D: Digest, + MGD: Digest + FixedOutputReset, +{ + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner && self.label == other.label + } +} + +#[cfg(test)] +mod tests { + + #[test] + #[cfg(feature = "serde")] + fn test_serde() { + use super::*; + use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; + use serde_test::{assert_tokens, Configure, Token}; + + let mut rng = ChaCha8Rng::from_seed([42; 32]); + let priv_key = crate::RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"); + let encrypting_key = EncryptingKey::::new(priv_key.to_public_key()); + + let tokens = [ + Token::Struct { + name: "EncryptingKey", + len: 4, + }, + Token::Str("inner"), + Token::Str( + "3024300d06092a864886f70d01010105000313003010020900cc6c6130e35b46bf0203010001", + ), + Token::Str("label"), + Token::None, + Token::Str("phantom"), + Token::UnitStruct { + name: "PhantomData", + }, + Token::Str("mg_phantom"), + Token::UnitStruct { + name: "PhantomData", + }, + Token::StructEnd, + ]; + assert_tokens(&encrypting_key.readable(), &tokens); + } +} diff --git a/src/pkcs1v15/decrypting_key.rs b/src/pkcs1v15/decrypting_key.rs index 0bd6dc89..78aee178 100644 --- a/src/pkcs1v15/decrypting_key.rs +++ b/src/pkcs1v15/decrypting_key.rs @@ -6,12 +6,15 @@ use crate::{ }; use alloc::vec::Vec; use rand_core::CryptoRngCore; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; use zeroize::ZeroizeOnDrop; /// Decryption key for PKCS#1 v1.5 decryption as described in [RFC8017 § 7.2]. /// /// [RFC8017 § 7.2]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.2 -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct DecryptingKey { inner: RsaPrivateKey, } @@ -49,3 +52,26 @@ impl EncryptingKeypair for DecryptingKey { } impl ZeroizeOnDrop for DecryptingKey {} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "serde")] + fn test_serde() { + use super::*; + use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; + use serde_test::{assert_tokens, Configure, Token}; + + let mut rng = ChaCha8Rng::from_seed([42; 32]); + let decrypting_key = + DecryptingKey::new(RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key")); + + let tokens = [ + Token::Struct { name: "DecryptingKey", len: 1 }, + Token::Str("inner"), + Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900cc6c6130e35b46bf0203010001020863de1ac858580019020500f65cff5d020500d46b68cb02046d9a09f102047b4e3a4f020500f45065cc"), + Token::StructEnd, + ]; + assert_tokens(&decrypting_key.readable(), &tokens); + } +} diff --git a/src/pkcs1v15/encrypting_key.rs b/src/pkcs1v15/encrypting_key.rs index 80db0f60..2850f79d 100644 --- a/src/pkcs1v15/encrypting_key.rs +++ b/src/pkcs1v15/encrypting_key.rs @@ -2,11 +2,14 @@ use super::encrypt; use crate::{traits::RandomizedEncryptor, Result, RsaPublicKey}; use alloc::vec::Vec; use rand_core::CryptoRngCore; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; /// Encryption key for PKCS#1 v1.5 encryption as described in [RFC8017 § 7.2]. /// /// [RFC8017 § 7.2]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.2 -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct EncryptingKey { pub(super) inner: RsaPublicKey, } @@ -27,3 +30,31 @@ impl RandomizedEncryptor for EncryptingKey { encrypt(rng, &self.inner, msg) } } + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "serde")] + fn test_serde() { + use super::*; + use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; + use serde_test::{assert_tokens, Configure, Token}; + + let mut rng = ChaCha8Rng::from_seed([42; 32]); + let priv_key = crate::RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"); + let encrypting_key = EncryptingKey::new(priv_key.to_public_key()); + + let tokens = [ + Token::Struct { + name: "EncryptingKey", + len: 1, + }, + Token::Str("inner"), + Token::Str( + "3024300d06092a864886f70d01010105000313003010020900cc6c6130e35b46bf0203010001", + ), + Token::StructEnd, + ]; + assert_tokens(&encrypting_key.clone().readable(), &tokens); + } +} diff --git a/src/pkcs1v15/signature.rs b/src/pkcs1v15/signature.rs index a7e520c4..3209ba30 100644 --- a/src/pkcs1v15/signature.rs +++ b/src/pkcs1v15/signature.rs @@ -6,6 +6,8 @@ use alloc::{boxed::Box, string::ToString}; use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex}; use crypto_bigint::BoxedUint; +#[cfg(feature = "serde")] +use serdect::serde::{de, Deserialize, Serialize}; use spki::{ der::{asn1::BitString, Result as DerResult}, SignatureBitStringEncoding, @@ -82,3 +84,43 @@ impl Display for Signature { write!(f, "{:X}", self) } } + +#[cfg(feature = "serde")] +impl Serialize for Signature { + fn serialize(&self, serializer: S) -> core::result::Result + where + S: serdect::serde::Serializer, + { + serdect::slice::serialize_hex_lower_or_bin(&self.to_bytes(), serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for Signature { + fn deserialize(deserializer: D) -> core::result::Result + where + D: serdect::serde::Deserializer<'de>, + { + serdect::slice::deserialize_hex_or_bin_vec(deserializer)? + .as_slice() + .try_into() + .map_err(de::Error::custom) + } +} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "serde")] + fn test_serde() { + use super::*; + use serde_test::{assert_tokens, Configure, Token}; + let signature = Signature { + inner: BigUint::new(Vec::from([42])), + len: 1, + }; + + let tokens = [Token::Str("2a")]; + assert_tokens(&signature.readable(), &tokens); + } +} diff --git a/src/pkcs1v15/signing_key.rs b/src/pkcs1v15/signing_key.rs index da3bd6b8..912cc657 100644 --- a/src/pkcs1v15/signing_key.rs +++ b/src/pkcs1v15/signing_key.rs @@ -11,6 +11,12 @@ use pkcs8::{ AssociatedOid, EncodePrivateKey, SecretDocument, }; use rand_core::CryptoRngCore; +#[cfg(feature = "serde")] +use { + pkcs8::DecodePrivateKey, + serdect::serde::{de, ser, Deserialize, Serialize}, +}; + use signature::{ hazmat::PrehashSigner, DigestSigner, Keypair, RandomizedDigestSigner, RandomizedSigner, Signer, }; @@ -242,8 +248,70 @@ where type Error = pkcs8::Error; fn try_from(private_key_info: pkcs8::PrivateKeyInfo<'_>) -> pkcs8::Result { + private_key_info + .algorithm + .assert_algorithm_oid(pkcs1::ALGORITHM_OID)?; RsaPrivateKey::try_from(private_key_info).map(Self::new) } } impl ZeroizeOnDrop for SigningKey where D: Digest {} + +impl PartialEq for SigningKey +where + D: Digest, +{ + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner && self.prefix == other.prefix + } +} + +#[cfg(feature = "serde")] +impl Serialize for SigningKey +where + D: Digest, +{ + fn serialize(&self, serializer: S) -> core::result::Result + where + S: serdect::serde::Serializer, + { + let der = self.to_pkcs8_der().map_err(ser::Error::custom)?; + serdect::slice::serialize_hex_lower_or_bin(&der.as_bytes(), serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, D> Deserialize<'de> for SigningKey +where + D: Digest + AssociatedOid, +{ + fn deserialize(deserializer: De) -> core::result::Result + where + De: serdect::serde::Deserializer<'de>, + { + let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; + Self::from_pkcs8_der(&der_bytes).map_err(de::Error::custom) + } +} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "serde")] + fn test_serde() { + use super::*; + use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; + use serde_test::{assert_tokens, Configure, Token}; + use sha2::Sha256; + + let mut rng = ChaCha8Rng::from_seed([42; 32]); + let priv_key = crate::RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"); + let signing_key = SigningKey::::new(priv_key); + + let tokens = [ + Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900cc6c6130e35b46bf0203010001020863de1ac858580019020500f65cff5d020500d46b68cb02046d9a09f102047b4e3a4f020500f45065cc") + ]; + + assert_tokens(&signing_key.readable(), &tokens); + } +} diff --git a/src/pkcs1v15/verifying_key.rs b/src/pkcs1v15/verifying_key.rs index fafb4a4d..fa23e8f7 100644 --- a/src/pkcs1v15/verifying_key.rs +++ b/src/pkcs1v15/verifying_key.rs @@ -8,9 +8,17 @@ use pkcs8::{ der::AnyRef, AlgorithmIdentifierRef, AssociatedAlgorithmIdentifier, SignatureAlgorithmIdentifier, }, - AssociatedOid, Document, EncodePublicKey, + AssociatedOid, }; + +#[cfg(feature = "serde")] +use { + serdect::serde::{de, ser, Deserialize, Serialize}, + spki::DecodePublicKey, +}; + use signature::{hazmat::PrehashVerifier, DigestVerifier, Verifier}; +use spki::{Document, EncodePublicKey}; /// Verifying key for `RSASSA-PKCS1-v1_5` signatures as described in [RFC8017 § 8.2]. /// @@ -198,6 +206,68 @@ where type Error = pkcs8::spki::Error; fn try_from(spki: pkcs8::SubjectPublicKeyInfoRef<'_>) -> pkcs8::spki::Result { + spki.algorithm.assert_algorithm_oid(pkcs1::ALGORITHM_OID)?; + RsaPublicKey::try_from(spki).map(Self::new) } } + +impl PartialEq for VerifyingKey +where + D: Digest, +{ + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner && self.prefix == other.prefix + } +} + +#[cfg(feature = "serde")] +impl Serialize for VerifyingKey +where + D: Digest, +{ + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let der = self.to_public_key_der().map_err(ser::Error::custom)?; + serdect::slice::serialize_hex_lower_or_bin(&der, serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, D> Deserialize<'de> for VerifyingKey +where + D: Digest + AssociatedOid, +{ + fn deserialize(deserializer: De) -> Result + where + De: serde::Deserializer<'de>, + { + let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; + Self::from_public_key_der(&der_bytes).map_err(de::Error::custom) + } +} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "serde")] + fn test_serde() { + use super::*; + use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; + use serde_test::{assert_tokens, Configure, Token}; + use sha2::Sha256; + + let mut rng = ChaCha8Rng::from_seed([42; 32]); + let priv_key = crate::RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"); + let pub_key = priv_key.to_public_key(); + let verifying_key = VerifyingKey::::new(pub_key); + + let tokens = [Token::Str( + "3024300d06092a864886f70d01010105000313003010020900cc6c6130e35b46bf0203010001", + )]; + + assert_tokens(&verifying_key.readable(), &tokens); + } +} diff --git a/src/pss.rs b/src/pss.rs index 021bf8d9..1d79e02d 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -23,7 +23,7 @@ use alloc::{boxed::Box, vec::Vec}; use core::fmt::{self, Debug}; use crypto_bigint::BoxedUint; -use const_oid::{AssociatedOid, ObjectIdentifier}; +use const_oid::AssociatedOid; use digest::{Digest, DynDigest, FixedOutputReset}; use pkcs1::RsaPssParams; use pkcs8::spki::{der::Any, AlgorithmIdentifierOwned}; @@ -32,6 +32,7 @@ use rand_core::CryptoRngCore; use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad}; use crate::algorithms::pss::*; use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt}; +use crate::encoding::ID_RSASSA_PSS; use crate::errors::{Error, Result}; use crate::traits::PublicKeyParts; use crate::traits::SignatureScheme; @@ -249,8 +250,6 @@ fn get_pss_signature_algo_id(salt_len: u8) -> pkcs8::spki::Result(salt_len); Ok(AlgorithmIdentifierOwned { @@ -292,7 +291,8 @@ mod test { BoxedUint::from_be_hex("98920366548084643601728869055592650835572950932266967461790948584315647051443",bits).unwrap(), BoxedUint::from_be_hex("94560208308847015747498523884063394671606671904944666360068158221458669711639", bits).unwrap() ], - ).unwrap() + ) + .unwrap() } #[test] @@ -575,10 +575,10 @@ mod test { for test in &tests { let sig = signing_key - .sign_prehash_with_rng(&mut rng, &test) + .sign_prehash_with_rng(&mut rng, test) .expect("failed to sign"); verifying_key - .verify_prehash(&test, &sig) + .verify_prehash(test, &sig) .expect("failed to verify"); } } @@ -594,10 +594,10 @@ mod test { for test in &tests { let sig = signing_key - .sign_prehash_with_rng(&mut rng, &test) + .sign_prehash_with_rng(&mut rng, test) .expect("failed to sign"); verifying_key - .verify_prehash(&test, &sig) + .verify_prehash(test, &sig) .expect("failed to verify"); } } diff --git a/src/pss/blinded_signing_key.rs b/src/pss/blinded_signing_key.rs index c40e4bdc..4d9eba22 100644 --- a/src/pss/blinded_signing_key.rs +++ b/src/pss/blinded_signing_key.rs @@ -15,7 +15,11 @@ use signature::{ hazmat::RandomizedPrehashSigner, Keypair, RandomizedDigestSigner, RandomizedSigner, }; use zeroize::ZeroizeOnDrop; - +#[cfg(feature = "serde")] +use { + pkcs8::DecodePrivateKey, + serdect::serde::{de, ser, Deserialize, Serialize}, +}; /// Signing key for producing "blinded" RSASSA-PSS signatures as described in /// [draft-irtf-cfrg-rsa-blind-signatures](https://datatracker.ietf.org/doc/draft-irtf-cfrg-rsa-blind-signatures/). #[derive(Debug, Clone)] @@ -197,4 +201,74 @@ where } } +impl TryFrom> for BlindedSigningKey +where + D: Digest + AssociatedOid, +{ + type Error = pkcs8::Error; + + fn try_from(private_key_info: pkcs8::PrivateKeyInfo<'_>) -> pkcs8::Result { + RsaPrivateKey::try_from(private_key_info).map(Self::new) + } +} + impl ZeroizeOnDrop for BlindedSigningKey where D: Digest {} + +impl PartialEq for BlindedSigningKey +where + D: Digest, +{ + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner && self.salt_len == other.salt_len + } +} + +#[cfg(feature = "serde")] +impl Serialize for BlindedSigningKey +where + D: Digest, +{ + fn serialize(&self, serializer: S) -> core::result::Result + where + S: serde::Serializer, + { + let der = self.to_pkcs8_der().map_err(ser::Error::custom)?; + serdect::slice::serialize_hex_lower_or_bin(&der.as_bytes(), serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, D> Deserialize<'de> for BlindedSigningKey +where + D: Digest + AssociatedOid, +{ + fn deserialize(deserializer: De) -> core::result::Result + where + De: serde::Deserializer<'de>, + { + let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; + Self::from_pkcs8_der(&der_bytes).map_err(de::Error::custom) + } +} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "serde")] + fn test_serde() { + use super::*; + use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; + use serde_test::{assert_tokens, Configure, Token}; + use sha2::Sha256; + + let mut rng = ChaCha8Rng::from_seed([42; 32]); + let signing_key = BlindedSigningKey::::new( + RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"), + ); + + let tokens = [ + Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900cc6c6130e35b46bf0203010001020863de1ac858580019020500f65cff5d020500d46b68cb02046d9a09f102047b4e3a4f020500f45065cc") + ]; + assert_tokens(&signing_key.readable(), &tokens); + } +} diff --git a/src/pss/signature.rs b/src/pss/signature.rs index bbd347af..e7aee64f 100644 --- a/src/pss/signature.rs +++ b/src/pss/signature.rs @@ -6,6 +6,8 @@ use alloc::{boxed::Box, string::ToString}; use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex}; use crypto_bigint::BoxedUint; +#[cfg(feature = "serde")] +use serdect::serde::{de, Deserialize, Serialize}; use spki::{ der::{asn1::BitString, Result as DerResult}, SignatureBitStringEncoding, @@ -76,3 +78,43 @@ impl Display for Signature { write!(f, "{:X}", self) } } + +#[cfg(feature = "serde")] +impl Serialize for Signature { + fn serialize(&self, serializer: S) -> core::result::Result + where + S: serdect::serde::Serializer, + { + serdect::slice::serialize_hex_lower_or_bin(&self.to_bytes(), serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for Signature { + fn deserialize(deserializer: D) -> core::result::Result + where + D: serdect::serde::Deserializer<'de>, + { + serdect::slice::deserialize_hex_or_bin_vec(deserializer)? + .as_slice() + .try_into() + .map_err(de::Error::custom) + } +} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "serde")] + fn test_serde() { + use super::*; + use serde_test::{assert_tokens, Configure, Token}; + let signature = Signature { + inner: BigUint::new(Vec::from([42])), + len: 1, + }; + + let tokens = [Token::Str("2a")]; + assert_tokens(&signature.readable(), &tokens); + } +} diff --git a/src/pss/signing_key.rs b/src/pss/signing_key.rs index b6811f0b..574d30ed 100644 --- a/src/pss/signing_key.rs +++ b/src/pss/signing_key.rs @@ -1,4 +1,5 @@ use super::{get_pss_signature_algo_id, sign_digest, Signature, VerifyingKey}; +use crate::encoding::verify_algorithm_id; use crate::{Result, RsaPrivateKey}; use const_oid::AssociatedOid; use core::marker::PhantomData; @@ -15,6 +16,11 @@ use signature::{ hazmat::RandomizedPrehashSigner, Keypair, RandomizedDigestSigner, RandomizedSigner, }; use zeroize::ZeroizeOnDrop; +#[cfg(feature = "serde")] +use { + pkcs8::DecodePrivateKey, + serdect::serde::{de, ser, Deserialize, Serialize}, +}; #[cfg(feature = "getrandom")] use { @@ -219,4 +225,75 @@ where } } +impl TryFrom> for SigningKey +where + D: Digest + AssociatedOid, +{ + type Error = pkcs8::Error; + + fn try_from(private_key_info: pkcs8::PrivateKeyInfo<'_>) -> pkcs8::Result { + verify_algorithm_id(&private_key_info.algorithm)?; + RsaPrivateKey::try_from(private_key_info).map(Self::new) + } +} + impl ZeroizeOnDrop for SigningKey where D: Digest {} + +impl PartialEq for SigningKey +where + D: Digest, +{ + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner && self.salt_len == other.salt_len + } +} + +#[cfg(feature = "serde")] +impl Serialize for SigningKey +where + D: Digest, +{ + fn serialize(&self, serializer: S) -> core::result::Result + where + S: serdect::serde::Serializer, + { + let der = self.to_pkcs8_der().map_err(ser::Error::custom)?; + serdect::slice::serialize_hex_lower_or_bin(&der.as_bytes(), serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, D> Deserialize<'de> for SigningKey +where + D: Digest + AssociatedOid, +{ + fn deserialize(deserializer: De) -> core::result::Result + where + De: serdect::serde::Deserializer<'de>, + { + let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; + Self::from_pkcs8_der(&der_bytes).map_err(de::Error::custom) + } +} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "serde")] + fn test_serde() { + use super::*; + use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; + use serde_test::{assert_tokens, Configure, Token}; + use sha2::Sha256; + + let mut rng = ChaCha8Rng::from_seed([42; 32]); + let priv_key = crate::RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"); + let signing_key = SigningKey::::new(priv_key); + + let tokens = [ + Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900cc6c6130e35b46bf0203010001020863de1ac858580019020500f65cff5d020500d46b68cb02046d9a09f102047b4e3a4f020500f45065cc") + ]; + + assert_tokens(&signing_key.readable(), &tokens); + } +} diff --git a/src/pss/verifying_key.rs b/src/pss/verifying_key.rs index ed065492..2fd62d37 100644 --- a/src/pss/verifying_key.rs +++ b/src/pss/verifying_key.rs @@ -1,12 +1,18 @@ use super::{verify_digest, Signature}; +use crate::encoding::ID_RSASSA_PSS; use crate::RsaPublicKey; use core::marker::PhantomData; use digest::{Digest, FixedOutputReset}; use pkcs8::{ spki::{der::AnyRef, AlgorithmIdentifierRef, AssociatedAlgorithmIdentifier}, - Document, EncodePublicKey, + AssociatedOid, Document, EncodePublicKey, }; use signature::{hazmat::PrehashVerifier, DigestVerifier, Verifier}; +#[cfg(feature = "serde")] +use { + serdect::serde::{de, ser, Deserialize, Serialize}, + spki::DecodePublicKey, +}; /// Verifying key for checking the validity of RSASSA-PSS signatures as /// described in [RFC8017 § 8.1]. @@ -156,3 +162,83 @@ where key.inner } } + +impl TryFrom> for VerifyingKey +where + D: Digest + AssociatedOid, +{ + type Error = pkcs8::spki::Error; + + fn try_from(spki: pkcs8::SubjectPublicKeyInfoRef<'_>) -> pkcs8::spki::Result { + match spki.algorithm.oid { + ID_RSASSA_PSS | pkcs1::ALGORITHM_OID => (), + _ => { + return Err(spki::Error::OidUnknown { + oid: spki.algorithm.oid, + }); + } + } + + RsaPublicKey::try_from(spki).map(Self::new) + } +} + +impl PartialEq for VerifyingKey +where + D: Digest, +{ + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner && self.salt_len == other.salt_len + } +} + +#[cfg(feature = "serde")] +impl Serialize for VerifyingKey +where + D: Digest, +{ + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let der = self.to_public_key_der().map_err(ser::Error::custom)?; + serdect::slice::serialize_hex_lower_or_bin(&der, serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, D> Deserialize<'de> for VerifyingKey +where + D: Digest + AssociatedOid, +{ + fn deserialize(deserializer: De) -> Result + where + De: serde::Deserializer<'de>, + { + let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; + Self::from_public_key_der(&der_bytes).map_err(de::Error::custom) + } +} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "serde")] + fn test_serde() { + use super::*; + use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; + use serde_test::{assert_tokens, Configure, Token}; + use sha2::Sha256; + + let mut rng = ChaCha8Rng::from_seed([42; 32]); + let priv_key = crate::RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"); + let pub_key = priv_key.to_public_key(); + let verifying_key = VerifyingKey::::new(pub_key); + + let tokens = [Token::Str( + "3024300d06092a864886f70d01010105000313003010020900cc6c6130e35b46bf0203010001", + )]; + + assert_tokens(&verifying_key.readable(), &tokens); + } +} diff --git a/tests/examples/pkcs8/rsa2048-rfc9421-priv.der b/tests/examples/pkcs8/rsa2048-rfc9421-priv.der new file mode 100644 index 00000000..4585234d Binary files /dev/null and b/tests/examples/pkcs8/rsa2048-rfc9421-priv.der differ diff --git a/tests/examples/pkcs8/rsa2048-rfc9421-pub.der b/tests/examples/pkcs8/rsa2048-rfc9421-pub.der new file mode 100644 index 00000000..923fa695 Binary files /dev/null and b/tests/examples/pkcs8/rsa2048-rfc9421-pub.der differ diff --git a/tests/pkcs1.rs b/tests/pkcs1.rs index c7db566a..9bc2c2d8 100644 --- a/tests/pkcs1.rs +++ b/tests/pkcs1.rs @@ -50,11 +50,51 @@ fn decode_rsa2048_priv_der() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa2048-priv.pem - assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!( + &key.n().to_be_bytes()[..], + &hex!( + "B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36" + "E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C" + "76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F" + "599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332" + "266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C" + "575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEA" + "C89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC" + "90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F" + ) + ); assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); - assert_eq!(&key.d().to_be_bytes()[..], &hex!("7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1")); - assert_eq!(&key.primes()[0].to_be_bytes()[..], &hex!("DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67")); - assert_eq!(&key.primes()[1].to_be_bytes()[..], &hex!("D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9")); + assert_eq!( + &key.d().to_be_bytes()[..], + &hex!( + "7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BD" + "CFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B7" + "58A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455" + "DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A691" + "0C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5C" + "C27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F" + "76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DB" + "ABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1" + ) + ); + assert_eq!( + &key.primes()[0].to_be_bytes()[..], + &hex!( + "DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225" + "EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422" + "ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBE" + "B143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67" + ) + ); + assert_eq!( + &key.primes()[1].to_be_bytes()[..], + &hex!( + "D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FD" + "E65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E422" + "8DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B" + "02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9" + ) + ); } #[test] @@ -63,11 +103,75 @@ fn decode_rsa4096_priv_der() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa4096-priv.pem - assert_eq!(&key.n().to_be_bytes()[..], &hex!("A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1EBDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E026B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368FEE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E25540EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7ED5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D975D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551")); + assert_eq!( + &key.n().to_be_bytes()[..], + &hex!( + "A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0" + "BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375" + "852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1E" + "BDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E02" + "6B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E" + "365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F" + "6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C" + "52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919" + "D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368F" + "EE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E2554" + "0EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7E" + "D5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875" + "506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D97" + "5D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73" + "E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4" + "F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551" + ) + ); assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); - assert_eq!(&key.d().to_be_bytes()[..], &hex!("9FE3097B2322B90FAB6606C017A095EBE640C39C100BCEE02F238FA14DAFF38E9E57568F1127ED4436126B904631B127EC395BB3EE127EB82C88D2562A7FB55FED8D1450B7E4E2D2F37F5742636FCC6F289963522D5B5706082CADFA01C0EE99B4D0E9274D3A992E06974CBE01694686356962AC1959FD9BD447E5B9968C0543DF1BF134742AF345CDB2FA1F9371B0D4CF61C68D16D653D8E999D4FD3A16CF978A35AA40E860CDCE09655DD8B4CF19D4141B1E92AD5E51A8E4A5C27FA745611D90E49D0E9282222AB6F126643E1C77578816FCE3B98F321D2549F294A470DF8453446BF36F985DF25ED8FDE9FDF3073FB27727DF48E9E1FC7056BC78965090B7850126406462C8253051EF84E34EE3C3CEB8F96C658C38BE45558D2F64E29D223350555FC1EFA28EC1F4AFB5BA4080F09A86CDC3538C1AD7C972E6D7A3612E6845BA9AFBDF19F09060D1A779DE9635E2D2F8E0C510BA24C6C44B30C9BDFAF85BE917AEC5D43AFAB1AA3ADD33CC83DA93CAC69218F6A36EB47F199D5424C95FD9ED7B1E8BE2AEAA6433B227241316C20EE792650CEB48BFD634446B19D286B4EA1722498DA1A36973210EC3824751A5808D9AAEF59C449E19A5077CFECA126BD9A8DD4996561D4E27B3609FF82C5B1B21E627845D44961B33B875D5C4FA9FF357EF6BE3364969E1337C91B29A07B9A913CDE40CE2D5530C900E73751685E65431")); - assert_eq!(&key.primes()[0].to_be_bytes()[..], &hex!("D0213A79425B665B719118448893EC3275600F63DBF85B77F4E8E99EF302F6E82596048F6DCA772DE6BBF1124DB84B0AFE61B03A8604AB0079ED53F3304797AD01B38C44FE27A5A45E378483A804B56A4A967F48F01A866E721E67E4C9A1048AF68927FAA43D6A85D93E7BF7074DBA797563FCABE12309B76653C6DB614DC231CC556D9F25AC4841A02D31CDF3015B212307F9D0C79FEB5D3956CE53CC8FA1651BE60761F19F74672489EAF9F215409F39956E77A82183F1F72BB2FEDDF1B9FBFC4AD89EA445809DDBD5BD595277990C0BE9366FBB2ECF7B057CC1C3DC8FB77BF8456D07BBC95B3C1815F48E62B81468C3D4D9D96C0F48DAB04993BE8D91EDE5")); - assert_eq!(&key.primes()[1].to_be_bytes()[..], &hex!("CE36C6810522ABE5D6465F36EB137DA3B9EA4A5F1D27C6614729EB8E5E2E5CB88E3EF1A473A21944B66557B3DC2CE462E4BF3446CB4990037E5672B1705CBAE81B65BAF967A266DC18EFE80F4DBBFE1A59063205CE2943CADF421CCE74AF7063FD1A83AF3C39AF84525F59BDC1FF54815F52AFD1E8D4862B2C3654F6CFA83DC08E2A9D52B9F833C646AF7694467DFC5F7D7AD7B441895FCB7FFBED526324B0154A15823F5107C89548EDDCB61DA5308C6CC834D4A0C16DFA6CA1D67B61A65677EB1719CD125D0EF0DB8802FB76CFC17577BCB2510AE294E1BF8A9173A2B85C16A6B508C98F2D770B7F3DE48D9E720C53E263680B57E7109410015745570652FD")); + assert_eq!( + &key.d().to_be_bytes()[..], + &hex!( + "9FE3097B2322B90FAB6606C017A095EBE640C39C100BCEE02F238FA14DAFF38E" + "9E57568F1127ED4436126B904631B127EC395BB3EE127EB82C88D2562A7FB55F" + "ED8D1450B7E4E2D2F37F5742636FCC6F289963522D5B5706082CADFA01C0EE99" + "B4D0E9274D3A992E06974CBE01694686356962AC1959FD9BD447E5B9968C0543" + "DF1BF134742AF345CDB2FA1F9371B0D4CF61C68D16D653D8E999D4FD3A16CF97" + "8A35AA40E860CDCE09655DD8B4CF19D4141B1E92AD5E51A8E4A5C27FA745611D" + "90E49D0E9282222AB6F126643E1C77578816FCE3B98F321D2549F294A470DF84" + "53446BF36F985DF25ED8FDE9FDF3073FB27727DF48E9E1FC7056BC78965090B7" + "850126406462C8253051EF84E34EE3C3CEB8F96C658C38BE45558D2F64E29D22" + "3350555FC1EFA28EC1F4AFB5BA4080F09A86CDC3538C1AD7C972E6D7A3612E68" + "45BA9AFBDF19F09060D1A779DE9635E2D2F8E0C510BA24C6C44B30C9BDFAF85B" + "E917AEC5D43AFAB1AA3ADD33CC83DA93CAC69218F6A36EB47F199D5424C95FD9" + "ED7B1E8BE2AEAA6433B227241316C20EE792650CEB48BFD634446B19D286B4EA" + "1722498DA1A36973210EC3824751A5808D9AAEF59C449E19A5077CFECA126BD9" + "A8DD4996561D4E27B3609FF82C5B1B21E627845D44961B33B875D5C4FA9FF357" + "EF6BE3364969E1337C91B29A07B9A913CDE40CE2D5530C900E73751685E65431" + ) + ); + assert_eq!( + &key.primes()[0].to_be_bytes()[..], + &hex!( + "D0213A79425B665B719118448893EC3275600F63DBF85B77F4E8E99EF302F6E8" + "2596048F6DCA772DE6BBF1124DB84B0AFE61B03A8604AB0079ED53F3304797AD" + "01B38C44FE27A5A45E378483A804B56A4A967F48F01A866E721E67E4C9A1048A" + "F68927FAA43D6A85D93E7BF7074DBA797563FCABE12309B76653C6DB614DC231" + "CC556D9F25AC4841A02D31CDF3015B212307F9D0C79FEB5D3956CE53CC8FA165" + "1BE60761F19F74672489EAF9F215409F39956E77A82183F1F72BB2FEDDF1B9FB" + "FC4AD89EA445809DDBD5BD595277990C0BE9366FBB2ECF7B057CC1C3DC8FB77B" + "F8456D07BBC95B3C1815F48E62B81468C3D4D9D96C0F48DAB04993BE8D91EDE5" + ) + ); + assert_eq!( + &key.primes()[1].to_be_bytes()[..], + &hex!( + "CE36C6810522ABE5D6465F36EB137DA3B9EA4A5F1D27C6614729EB8E5E2E5CB8" + "8E3EF1A473A21944B66557B3DC2CE462E4BF3446CB4990037E5672B1705CBAE8" + "1B65BAF967A266DC18EFE80F4DBBFE1A59063205CE2943CADF421CCE74AF7063" + "FD1A83AF3C39AF84525F59BDC1FF54815F52AFD1E8D4862B2C3654F6CFA83DC0" + "8E2A9D52B9F833C646AF7694467DFC5F7D7AD7B441895FCB7FFBED526324B015" + "4A15823F5107C89548EDDCB61DA5308C6CC834D4A0C16DFA6CA1D67B61A65677" + "EB1719CD125D0EF0DB8802FB76CFC17577BCB2510AE294E1BF8A9173A2B85C16" + "A6B508C98F2D770B7F3DE48D9E720C53E263680B57E7109410015745570652FD" + ) + ); } #[test] @@ -76,7 +180,20 @@ fn decode_rsa2048_pub_der() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa2048-pub.pem - assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!( + &key.n().to_be_bytes()[..], + &hex!( + "B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36" + "E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C" + "76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F" + "599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332" + "266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C" + "575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEA" + "C89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC" + "90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F" + + ) + ); assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); } @@ -86,7 +203,27 @@ fn decode_rsa4096_pub_der() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa4096-pub.pem - assert_eq!(&key.n().to_be_bytes()[..], &hex!("A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1EBDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E026B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368FEE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E25540EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7ED5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D975D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551")); + assert_eq!( + &key.n().to_be_bytes()[..], + &hex!( + "A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0" + "BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375" + "852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1E" + "BDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E02" + "6B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E" + "365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F" + "6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C" + "52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919" + "D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368F" + "EE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E2554" + "0EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7E" + "D5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875" + "506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D97" + "5D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73" + "E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4" + "F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551" + ) + ); assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); } @@ -125,11 +262,53 @@ fn decode_rsa2048_priv_pem() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa2048-priv.pem - assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!( + &key.n().to_be_bytes()[..], + &hex!( + "B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36" + "E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C" + "76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F" + "599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332" + "266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C" + "575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEA" + "C89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC" + "90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F" + ) + ); assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); - assert_eq!(&key.d().to_be_bytes()[..], &hex!("7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1")); - assert_eq!(&key.primes()[0].to_be_bytes()[..], &hex!("DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67")); - assert_eq!(&key.primes()[1].to_be_bytes()[..], &hex!("D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9")); + assert_eq!( + &key.d().to_be_bytes()[..], + &hex!( + "7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BD" + "CFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B7" + "58A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455" + "DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A691" + "0C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5C" + "C27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F" + "76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DB" + "ABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1" + ) + ); + assert_eq!( + &key.primes()[0].to_be_bytes()[..], + &hex!( + "DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225" + "EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422" + "ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBE" + "B143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67" + + ) + ); + assert_eq!( + &key.primes()[1].to_be_bytes()[..], + &hex!( + "D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FD" + "E65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E422" + "8DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B" + "02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9" + + ) + ); } #[test] @@ -139,11 +318,76 @@ fn decode_rsa4096_priv_pem() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa4096-priv.pem - assert_eq!(&key.n().to_be_bytes()[..], &hex!("A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1EBDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E026B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368FEE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E25540EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7ED5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D975D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551")); + assert_eq!( + &key.n().to_be_bytes()[..], + &hex!( + "A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0" + "BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375" + "852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1E" + "BDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E02" + "6B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E" + "365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F" + "6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C" + "52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919" + "D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368F" + "EE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E2554" + "0EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7E" + "D5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875" + "506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D97" + "5D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73" + "E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4" + "F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551" + + ) + ); assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); - assert_eq!(&key.d().to_be_bytes()[..], &hex!("9FE3097B2322B90FAB6606C017A095EBE640C39C100BCEE02F238FA14DAFF38E9E57568F1127ED4436126B904631B127EC395BB3EE127EB82C88D2562A7FB55FED8D1450B7E4E2D2F37F5742636FCC6F289963522D5B5706082CADFA01C0EE99B4D0E9274D3A992E06974CBE01694686356962AC1959FD9BD447E5B9968C0543DF1BF134742AF345CDB2FA1F9371B0D4CF61C68D16D653D8E999D4FD3A16CF978A35AA40E860CDCE09655DD8B4CF19D4141B1E92AD5E51A8E4A5C27FA745611D90E49D0E9282222AB6F126643E1C77578816FCE3B98F321D2549F294A470DF8453446BF36F985DF25ED8FDE9FDF3073FB27727DF48E9E1FC7056BC78965090B7850126406462C8253051EF84E34EE3C3CEB8F96C658C38BE45558D2F64E29D223350555FC1EFA28EC1F4AFB5BA4080F09A86CDC3538C1AD7C972E6D7A3612E6845BA9AFBDF19F09060D1A779DE9635E2D2F8E0C510BA24C6C44B30C9BDFAF85BE917AEC5D43AFAB1AA3ADD33CC83DA93CAC69218F6A36EB47F199D5424C95FD9ED7B1E8BE2AEAA6433B227241316C20EE792650CEB48BFD634446B19D286B4EA1722498DA1A36973210EC3824751A5808D9AAEF59C449E19A5077CFECA126BD9A8DD4996561D4E27B3609FF82C5B1B21E627845D44961B33B875D5C4FA9FF357EF6BE3364969E1337C91B29A07B9A913CDE40CE2D5530C900E73751685E65431")); - assert_eq!(&key.primes()[0].to_be_bytes()[..], &hex!("D0213A79425B665B719118448893EC3275600F63DBF85B77F4E8E99EF302F6E82596048F6DCA772DE6BBF1124DB84B0AFE61B03A8604AB0079ED53F3304797AD01B38C44FE27A5A45E378483A804B56A4A967F48F01A866E721E67E4C9A1048AF68927FAA43D6A85D93E7BF7074DBA797563FCABE12309B76653C6DB614DC231CC556D9F25AC4841A02D31CDF3015B212307F9D0C79FEB5D3956CE53CC8FA1651BE60761F19F74672489EAF9F215409F39956E77A82183F1F72BB2FEDDF1B9FBFC4AD89EA445809DDBD5BD595277990C0BE9366FBB2ECF7B057CC1C3DC8FB77BF8456D07BBC95B3C1815F48E62B81468C3D4D9D96C0F48DAB04993BE8D91EDE5")); - assert_eq!(&key.primes()[1].to_be_bytes()[..], &hex!("CE36C6810522ABE5D6465F36EB137DA3B9EA4A5F1D27C6614729EB8E5E2E5CB88E3EF1A473A21944B66557B3DC2CE462E4BF3446CB4990037E5672B1705CBAE81B65BAF967A266DC18EFE80F4DBBFE1A59063205CE2943CADF421CCE74AF7063FD1A83AF3C39AF84525F59BDC1FF54815F52AFD1E8D4862B2C3654F6CFA83DC08E2A9D52B9F833C646AF7694467DFC5F7D7AD7B441895FCB7FFBED526324B0154A15823F5107C89548EDDCB61DA5308C6CC834D4A0C16DFA6CA1D67B61A65677EB1719CD125D0EF0DB8802FB76CFC17577BCB2510AE294E1BF8A9173A2B85C16A6B508C98F2D770B7F3DE48D9E720C53E263680B57E7109410015745570652FD")); + assert_eq!( + &key.d().to_be_bytes()[..], + &hex!( + "9FE3097B2322B90FAB6606C017A095EBE640C39C100BCEE02F238FA14DAFF38E" + "9E57568F1127ED4436126B904631B127EC395BB3EE127EB82C88D2562A7FB55F" + "ED8D1450B7E4E2D2F37F5742636FCC6F289963522D5B5706082CADFA01C0EE99" + "B4D0E9274D3A992E06974CBE01694686356962AC1959FD9BD447E5B9968C0543" + "DF1BF134742AF345CDB2FA1F9371B0D4CF61C68D16D653D8E999D4FD3A16CF97" + "8A35AA40E860CDCE09655DD8B4CF19D4141B1E92AD5E51A8E4A5C27FA745611D" + "90E49D0E9282222AB6F126643E1C77578816FCE3B98F321D2549F294A470DF84" + "53446BF36F985DF25ED8FDE9FDF3073FB27727DF48E9E1FC7056BC78965090B7" + "850126406462C8253051EF84E34EE3C3CEB8F96C658C38BE45558D2F64E29D22" + "3350555FC1EFA28EC1F4AFB5BA4080F09A86CDC3538C1AD7C972E6D7A3612E68" + "45BA9AFBDF19F09060D1A779DE9635E2D2F8E0C510BA24C6C44B30C9BDFAF85B" + "E917AEC5D43AFAB1AA3ADD33CC83DA93CAC69218F6A36EB47F199D5424C95FD9" + "ED7B1E8BE2AEAA6433B227241316C20EE792650CEB48BFD634446B19D286B4EA" + "1722498DA1A36973210EC3824751A5808D9AAEF59C449E19A5077CFECA126BD9" + "A8DD4996561D4E27B3609FF82C5B1B21E627845D44961B33B875D5C4FA9FF357" + "EF6BE3364969E1337C91B29A07B9A913CDE40CE2D5530C900E73751685E65431" + ) + ); + assert_eq!( + &key.primes()[0].to_be_bytes()[..], + &hex!( + "D0213A79425B665B719118448893EC3275600F63DBF85B77F4E8E99EF302F6E8" + "2596048F6DCA772DE6BBF1124DB84B0AFE61B03A8604AB0079ED53F3304797AD" + "01B38C44FE27A5A45E378483A804B56A4A967F48F01A866E721E67E4C9A1048A" + "F68927FAA43D6A85D93E7BF7074DBA797563FCABE12309B76653C6DB614DC231" + "CC556D9F25AC4841A02D31CDF3015B212307F9D0C79FEB5D3956CE53CC8FA165" + "1BE60761F19F74672489EAF9F215409F39956E77A82183F1F72BB2FEDDF1B9FB" + "FC4AD89EA445809DDBD5BD595277990C0BE9366FBB2ECF7B057CC1C3DC8FB77B" + "F8456D07BBC95B3C1815F48E62B81468C3D4D9D96C0F48DAB04993BE8D91EDE5" + ) + ); + assert_eq!( + &key.primes()[1].to_be_bytes()[..], + &hex!( + "CE36C6810522ABE5D6465F36EB137DA3B9EA4A5F1D27C6614729EB8E5E2E5CB8" + "8E3EF1A473A21944B66557B3DC2CE462E4BF3446CB4990037E5672B1705CBAE8" + "1B65BAF967A266DC18EFE80F4DBBFE1A59063205CE2943CADF421CCE74AF7063" + "FD1A83AF3C39AF84525F59BDC1FF54815F52AFD1E8D4862B2C3654F6CFA83DC0" + "8E2A9D52B9F833C646AF7694467DFC5F7D7AD7B441895FCB7FFBED526324B015" + "4A15823F5107C89548EDDCB61DA5308C6CC834D4A0C16DFA6CA1D67B61A65677" + "EB1719CD125D0EF0DB8802FB76CFC17577BCB2510AE294E1BF8A9173A2B85C16" + "A6B508C98F2D770B7F3DE48D9E720C53E263680B57E7109410015745570652FD" + ) + ); } #[test] @@ -153,7 +397,19 @@ fn decode_rsa2048_pub_pem() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa2048-pub.pem - assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!( + &key.n().to_be_bytes()[..], + &hex!( + "B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36" + "E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C" + "76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F" + "599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332" + "266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C" + "575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEA" + "C89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC" + "90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F" + ) + ); assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); } @@ -164,7 +420,27 @@ fn decode_rsa4096_pub_pem() { // Extracted using: // $ openssl asn1parse -in tests/examples/pkcs1/rsa4096-pub.pem - assert_eq!(&key.n().to_be_bytes()[..], &hex!("A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1EBDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E026B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368FEE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E25540EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7ED5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D975D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551")); + assert_eq!( + &key.n().to_be_bytes()[..], + &hex!( + "A7A74572811EA2617E49E85BD730DDE30F103F7D88EE3F765E540D3DD993BBB0" + "BA140002859D0B40897436637F58B828EA74DF8321634077F99D4AA2D54CA375" + "852EF597661D3713CE1EF3B4FD6A8E220238E467668A2C7EE3861D2212AE6A1E" + "BDDFA88B62DF10F6BCF79EFF4AC298FB2563DF1B8764381AF9B1FB0CCD085E02" + "6B0AD9F6721A235177D0396B48754AD4A75242250A873BF2F6E7EE3C75DD613E" + "365BA4F3210A6CC66B90A2FA3F762CA6884087B6BF8161EB144819F0F572F21F" + "6C8E273E70D45A365B8B2819CE734613CC23B01329A17901F17078403861F54C" + "52A051E2A58C75C2D9D80091BB9808A106C1F7ECB4034E15058BEEC725C5F919" + "D62EAA234B62628D346C60BB919E70851DAB38571E6F0ED7634129F994EA368F" + "EE7373DFDEC04445EBCA47FA20ED1540A860C948BABC98DA591CA1DE2E2E2554" + "0EF9B7CB353F60213B814A45D359EFA9B811EEFF08C65993BF8A85C2BFEAAA7E" + "D5E6B43E18AE604464CE5F96150136E7D09F8B24FAD43D7870118CFA7BC24875" + "506EBBC321B977E0861AEA50128620121F0B394A9CDD0A42411A1350C0770D97" + "5D71B00A90436240C967A0C3A5C20A0F6DE77F3F2CAFDA94ED0143C1F6E34F73" + "E0CAC279EEEB7C637723A2B026C82802E1A4AEBAA8846DF98E7919498773E0D4" + "F319956F4DE3AAD00EFB9A147D66B3AC1A01D35B2CFB48D400B0E7A80DC97551" + ) + ); assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); } diff --git a/tests/pkcs8.rs b/tests/pkcs8.rs index d8c97b32..2140bd3b 100644 --- a/tests/pkcs8.rs +++ b/tests/pkcs8.rs @@ -14,10 +14,17 @@ const RSA_2048_PRIV_PEM: &str = include_str!("examples/pkcs8/rsa2048-priv.pem"); #[cfg(feature = "pem")] const RSA_2048_PUB_PEM: &str = include_str!("examples/pkcs8/rsa2048-pub.pem"); +/// RSA-2048 PSS PKCS#8 private key encoded as DER +const RSA_2048_PSS_PRIV_DER: &[u8] = include_bytes!("examples/pkcs8/rsa2048-rfc9421-priv.der"); + +/// RSA-2048 PSS PKCS#8 public key encoded as DER +const RSA_2048_PSS_PUB_DER: &[u8] = include_bytes!("examples/pkcs8/rsa2048-rfc9421-pub.der"); + use hex_literal::hex; use rsa::{ pkcs1v15, pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePrivateKey, EncodePublicKey}, + pss, traits::{PrivateKeyParts, PublicKeyParts}, RsaPrivateKey, RsaPublicKey, }; @@ -31,11 +38,51 @@ fn decode_rsa2048_priv_der() { let key = RsaPrivateKey::from_pkcs8_der(RSA_2048_PRIV_DER).unwrap(); // Note: matches PKCS#1 test vectors - assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!( + &key.n().to_be_bytes()[..], + &hex!( + "B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36" + "E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C" + "76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F" + "599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332" + "266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C" + "575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEA" + "C89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC" + "90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F" + ) + ); assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); - assert_eq!(&key.d().to_be_bytes()[..], &hex!("7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1")); - assert_eq!(&key.primes()[0].to_be_bytes()[..], &hex!("DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67")); - assert_eq!(&key.primes()[1].to_be_bytes()[..], &hex!("D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9")); + assert_eq!( + &key.d().to_be_bytes()[..], + &hex!( + "7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BD" + "CFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B7" + "58A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455" + "DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A691" + "0C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5C" + "C27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F" + "76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DB" + "ABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1" + ) + ); + assert_eq!( + &key.primes()[0].to_be_bytes()[..], + &hex!( + "DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225" + "EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422" + "ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBE" + "B143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67" + ) + ); + assert_eq!( + &key.primes()[1].to_be_bytes()[..], + &hex!( + "D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FD" + "E65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E422" + "8DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B" + "02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9" + ) + ); let _ = pkcs1v15::SigningKey::::from_pkcs8_der(RSA_2048_PRIV_DER).unwrap(); } @@ -45,12 +92,101 @@ fn decode_rsa2048_pub_der() { let key = RsaPublicKey::from_public_key_der(RSA_2048_PUB_DER).unwrap(); // Note: matches PKCS#1 test vectors - assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!( + &key.n().to_be_bytes()[..], + &hex!( + "B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36" + "E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C" + "76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F" + "599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332" + "266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C" + "575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEA" + "C89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC" + "90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F" + ) + ); assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); let _ = pkcs1v15::VerifyingKey::::from_public_key_der(RSA_2048_PUB_DER).unwrap(); } +#[test] +fn decode_rsa2048_pss_priv_der() { + let key = RsaPrivateKey::from_pkcs8_der(RSA_2048_PSS_PRIV_DER).unwrap(); + + assert_eq!( + &key.n().to_be_bytes()[..], + &hex!( + "AF8B669B7AF6D1677F3DBAAF3F5B36F9012DBE9B91695F18AB8D208D447CCB64" + "63C5AE9DA46D865C76CF7EF32CF1CB7E2E1D461F8E71DBC470DD1CB9DE69BEA0" + "05E3C90F3A3A70E467937C9586E0803E0EDF0E8CEA902F2E4864F79027753AE2" + "7DB2053CD53C3CF30EECECAB1401EA803B339E33C59933AD08470DD99D45A568" + "1C870B982CF2FE5A892A96D775D67AAACE2F9B27D72F48A00361D50000DE5652" + "DCDDA62CBA2DB4E04B13FBA1C894E139F483923A683649EC0F0BCE8D0A4B2658" + "A00E3CE66A9C3B419501D570F65AB868E4FDBFA77E9DBE1B9CD91056494B4377" + "D502F266FB17433A9F4B08D08DE3C576A670CE90557AF94F67579A3273A5C8DB" + + ) + ); + assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); + assert_eq!( + &key.d().to_be_bytes()[..], + &hex!( + "9407C8A9FA426289954A17C02A7C1FDA50FD234C0A8E41EC0AD64289FE24025C" + "10AAA5BA37EB482F76DD391F9559FD10D590480EDA4EF7552B1BBA5A9ECCAB3C" + "445B36B44994F8981323D31E4093D670FE9768ACBA2C862CD04D9C5A0A7C1800" + "E0A01B3C96506AD14857D0A7DF82521E7A4DE7ED9E86B7860581ED9301C5B659" + "B3785DF2BB96EA45CA8E871F25918981CC3004505CB25E3927539F968C04FD0F" + "3B86D0CA4E4E4714D449E39C88F254164B501E4BC66F29BB2ABC847F01FC4E4B" + "342FB5A1CF23FAD0F2F7C52F4534E262F66FB3CEDC1821718342E28CD860EC21" + "3783DA6236A07A0F332003D30748EC1C12556D7CA7587E8E07DCE1D95EC4A611" + ) + ); + assert_eq!( + &key.primes()[0].to_be_bytes()[..], + &hex!( + "E55FBA212239C846821579BE7E4D44336C700167A478F542032BEBF506D39453" + "82670B7D5B08D48E1B4A46EB22E54ABE21867FB6AD96444E00B386FF14710CB6" + "9D80111E3721CBE65CFA8A141A1492D5434BB7538481EBB27462D54EDD1EA55D" + "C2230431EE63C4A3609EC28BA67ABEE0DCA1A12E8E796BB5485A331BD27DC509" + + ) + ); + assert_eq!( + &key.primes()[1].to_be_bytes()[..], + &hex!( + "C3EC0875ED7B5B96340A9869DD9674B8CF0E52AD4092B57620A6AEA981DA0F10" + "13DF610CE1C8B630C111DA7214128E20FF8DA55B4CD8A2E145A8E370BF4F87C8" + "EB203E9752A8A442E562E09F455769B8DA35CCBA2A134F5DE274020B6A7620F0" + "3DE276FCBFDE2B0356438DD17DD40152AB80C1277B4849A643CB158AA07ADBC3" + ) + ); + + let _ = pss::SigningKey::::from_pkcs8_der(RSA_2048_PSS_PRIV_DER).unwrap(); +} + +#[test] +fn decode_rsa2048_pss_pub_der() { + let key = RsaPublicKey::from_public_key_der(RSA_2048_PSS_PUB_DER).unwrap(); + + assert_eq!( + &key.n().to_be_bytes()[..], + &hex!( + "AF8B669B7AF6D1677F3DBAAF3F5B36F9012DBE9B91695F18AB8D208D447CCB64" + "63C5AE9DA46D865C76CF7EF32CF1CB7E2E1D461F8E71DBC470DD1CB9DE69BEA0" + "05E3C90F3A3A70E467937C9586E0803E0EDF0E8CEA902F2E4864F79027753AE2" + "7DB2053CD53C3CF30EECECAB1401EA803B339E33C59933AD08470DD99D45A568" + "1C870B982CF2FE5A892A96D775D67AAACE2F9B27D72F48A00361D50000DE5652" + "DCDDA62CBA2DB4E04B13FBA1C894E139F483923A683649EC0F0BCE8D0A4B2658" + "A00E3CE66A9C3B419501D570F65AB868E4FDBFA77E9DBE1B9CD91056494B4377" + "D502F266FB17433A9F4B08D08DE3C576A670CE90557AF94F67579A3273A5C8DB" + ) + ); + assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); + + let _ = pss::VerifyingKey::::from_public_key_der(RSA_2048_PSS_PUB_DER).unwrap(); +} + #[test] fn encode_rsa2048_priv_der() { let key = RsaPrivateKey::from_pkcs8_der(RSA_2048_PRIV_DER).unwrap(); @@ -80,11 +216,51 @@ fn decode_rsa2048_priv_pem() { let key = RsaPrivateKey::from_pkcs8_pem(RSA_2048_PRIV_PEM).unwrap(); // Note: matches PKCS#1 test vectors - assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!( + &key.n().to_be_bytes()[..], + &hex!( + "B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36" + "E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C" + "76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F" + "599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332" + "266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C" + "575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEA" + "C89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC" + "90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F" + ) + ); assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); - assert_eq!(&key.d().to_be_bytes()[..], &hex!("7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1")); - assert_eq!(&key.primes()[0].to_be_bytes()[..], &hex!("DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67")); - assert_eq!(&key.primes()[1].to_be_bytes()[..], &hex!("D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9")); + assert_eq!( + &key.d().to_be_bytes()[..], + &hex!( + "7ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BD" + "CFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B7" + "58A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455" + "DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A691" + "0C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5C" + "C27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F" + "76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DB" + "ABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C1" + ) + ); + assert_eq!( + &key.primes()[0].to_be_bytes()[..], + &hex!( + "DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225" + "EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422" + "ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBE" + "B143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D67" + ) + ); + assert_eq!( + &key.primes()[1].to_be_bytes()[..], + &hex!( + "D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FD" + "E65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E422" + "8DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B" + "02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F9" + ) + ); let _ = pkcs1v15::SigningKey::::from_pkcs8_pem(RSA_2048_PRIV_PEM).unwrap(); } @@ -95,7 +271,19 @@ fn decode_rsa2048_pub_pem() { let key = RsaPublicKey::from_public_key_pem(RSA_2048_PUB_PEM).unwrap(); // Note: matches PKCS#1 test vectors - assert_eq!(&key.n().to_be_bytes()[..], &hex!("B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F")); + assert_eq!( + &key.n().to_be_bytes()[..], + &hex!( + "B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36" + "E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C" + "76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F" + "599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332" + "266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C" + "575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEA" + "C89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC" + "90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F" + ) + ); assert_eq!(&key.e().to_be_bytes()[..], &hex!("010001")); let _ = pkcs1v15::VerifyingKey::::from_public_key_pem(RSA_2048_PUB_PEM).unwrap();