From 1c5c8a4e148a60a12e16d2758e229f01ac7fae96 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Thu, 12 Nov 2026 09:45:31 -0500 Subject: [PATCH] Add craft-pkcs7: DER, X.509, CMS SignedData, PKCS #12, RFC 3161 and revocation from PdfCraft * Add craft-pkcs7: DER, X.509, CMS SignedData, PKCS #12, RFC 3161 and revocation from PdfCraft Moved from PdfCraft's crates/sign at 1d7a9f9f: der, x509, cms, pkcs12, timestamp, revocation, keys, rsa_pad and ec512, with their unit tests, the integration tests that need no PDF, and the test keys. x509 no longer returns PdfCraft's worded sentences: signing_problem gives a SigningProblem and build_chain_noted a Refused (reason and the two certificates). The checks behind them are unchanged. Error is SignError without its PDF variants. * craft-pkcs7: write the certificate serial verbatim in SignerInfo and ESSCertIDv2 A serial with its high bit set and no leading zero was written with one added, so the signer identifier and the signing-certificate attribute named a different number than the certificate has. Ported from storytold/pdfcraft#6868. The test uses a certificate that really has such a serial and also checks that the signer's certificate is found. * craft-pkcs7: note why RIPEMD-160 is supported --------- Co-authored-by: jonathanwxh-cell --- ATTRIBUTION.md | 1 + Cargo.lock | 643 +++++++++++++++--- Cargo.toml | 1 + README.md | 4 + crates/pkcs7/Cargo.toml | 53 ++ crates/pkcs7/README.md | 44 ++ crates/pkcs7/src/cms.rs | 595 +++++++++++++++++ crates/pkcs7/src/der.rs | 663 ++++++++++++++++++ crates/pkcs7/src/ec512.rs | 180 +++++ crates/pkcs7/src/keys.rs | 767 +++++++++++++++++++++ crates/pkcs7/src/lib.rs | 56 ++ crates/pkcs7/src/pkcs12.rs | 561 ++++++++++++++++ crates/pkcs7/src/revocation.rs | 309 +++++++++ crates/pkcs7/src/rsa_pad.rs | 147 ++++ crates/pkcs7/src/timestamp.rs | 253 +++++++ crates/pkcs7/src/x509.rs | 704 ++++++++++++++++++++ crates/pkcs7/tests/data/README.md | 62 ++ crates/pkcs7/tests/data/ca.crt.pem | 12 + crates/pkcs7/tests/data/chain-legacy.p12 | Bin 0 -> 2878 bytes crates/pkcs7/tests/data/chain.p12 | Bin 0 -> 3044 bytes crates/pkcs7/tests/data/ec-legacy.p12 | Bin 0 -> 1047 bytes crates/pkcs7/tests/data/ec-p256.p12 | Bin 0 -> 1112 bytes crates/pkcs7/tests/data/ec-p384.p12 | Bin 0 -> 1162 bytes crates/pkcs7/tests/data/rsa-aes.p12 | Bin 0 -> 2714 bytes crates/pkcs7/tests/data/rsa-legacy.p12 | Bin 0 -> 2556 bytes crates/pkcs7/tests/data/rsa.crt.pem | 20 + crates/pkcs7/tests/it/algorithms.rs | 140 ++++ crates/pkcs7/tests/it/ber.rs | 76 +++ crates/pkcs7/tests/it/chain.rs | 312 +++++++++ crates/pkcs7/tests/it/cms.rs | 130 ++++ crates/pkcs7/tests/it/crypto.rs | 812 +++++++++++++++++++++++ crates/pkcs7/tests/it/main.rs | 8 + crates/pkcs7/tests/it/store_keys.rs | 89 +++ 33 files changed, 6554 insertions(+), 88 deletions(-) create mode 100644 crates/pkcs7/Cargo.toml create mode 100644 crates/pkcs7/README.md create mode 100644 crates/pkcs7/src/cms.rs create mode 100644 crates/pkcs7/src/der.rs create mode 100644 crates/pkcs7/src/ec512.rs create mode 100644 crates/pkcs7/src/keys.rs create mode 100644 crates/pkcs7/src/lib.rs create mode 100644 crates/pkcs7/src/pkcs12.rs create mode 100644 crates/pkcs7/src/revocation.rs create mode 100644 crates/pkcs7/src/rsa_pad.rs create mode 100644 crates/pkcs7/src/timestamp.rs create mode 100644 crates/pkcs7/src/x509.rs create mode 100644 crates/pkcs7/tests/data/README.md create mode 100644 crates/pkcs7/tests/data/ca.crt.pem create mode 100644 crates/pkcs7/tests/data/chain-legacy.p12 create mode 100644 crates/pkcs7/tests/data/chain.p12 create mode 100644 crates/pkcs7/tests/data/ec-legacy.p12 create mode 100644 crates/pkcs7/tests/data/ec-p256.p12 create mode 100644 crates/pkcs7/tests/data/ec-p384.p12 create mode 100644 crates/pkcs7/tests/data/rsa-aes.p12 create mode 100644 crates/pkcs7/tests/data/rsa-legacy.p12 create mode 100644 crates/pkcs7/tests/data/rsa.crt.pem create mode 100644 crates/pkcs7/tests/it/algorithms.rs create mode 100644 crates/pkcs7/tests/it/ber.rs create mode 100644 crates/pkcs7/tests/it/chain.rs create mode 100644 crates/pkcs7/tests/it/cms.rs create mode 100644 crates/pkcs7/tests/it/crypto.rs create mode 100644 crates/pkcs7/tests/it/main.rs create mode 100644 crates/pkcs7/tests/it/store_keys.rs diff --git a/ATTRIBUTION.md b/ATTRIBUTION.md index 27e9ca01b..965b348e4 100644 --- a/ATTRIBUTION.md +++ b/ATTRIBUTION.md @@ -85,6 +85,7 @@ and the exact transfer revision are recorded in each vendored crate's SOURCE.jso | `crates/raster-codecs/src/xpm/x11_colors.rs` | X.Org Foundation and X11 contributors (X11 `rgb.txt` colour names and values, normalised into a lookup table) | , via [PhotoCraft `crates/codecs`](https://github.com/storytold/photocraft/tree/63b641b55e54bf8f5c83efd977fdb16a2c255431/crates/codecs/src/codecs/xpm) | MIT (X.Org app/rgb) | | `crates/psd/tests/fixtures/atn/*.atn` (seven synthetic action sets, encoded field by field; `crates/psd/tests/fixtures/atn/README.md`) | PhotoCraft contributors | [PhotoCraft `crates/psd/tests/fixtures/atn`](https://github.com/storytold/photocraft/tree/63b641b55e54bf8f5c83efd977fdb16a2c255431/crates/psd/tests/fixtures/atn) | MIT OR Apache-2.0 | | `crates/lottie/tests/fixtures/` | EffectCraft contributors (original work: four hand-written Lottie JSON documents, written from the public Lottie format description; not exported from any Adobe product or third-party file) | [EffectCraft `crates/lottie/tests/fixtures`](https://github.com/storytold/effectcraft/tree/e18f48fb/crates/lottie/tests/fixtures) | MIT OR Apache-2.0 | +| `crates/pkcs7/tests/data/` | PdfCraft contributors (original work: throw-away test keys and certificates made with OpenSSL 3 for these tests, as seven PKCS #12 files with the password `test` and two PEM certificates; they protect nothing; commands in `crates/pkcs7/tests/data/README.md`) | [PdfCraft `crates/sign/tests/data`](https://github.com/storytold/pdfcraft/tree/1d7a9f9f/crates/sign/tests/data) | MIT OR Apache-2.0 | | `crates/affinity/tests/support/corpus.tsv`, `crates/affinity/tests/support/affinity3-signatures.txt` (manifest and measured signatures only; the 51 documents are not bundled, `scripts/fetch-affinity-corpus.sh` downloads them outside the checkout) | The authors of each document: samuel-etver (vector-art), Seth A. Robinson (Patchy fixtures), Nick Beeuwsaert (AFDesignLoad), Jeremy Cantu (Branding), eviltwo (AssetStoreTemplate), Square (leakcanary) | each file's pinned upstream URL and SHA-256 in the manifest; list carried over from [VectorCraft `xtask/src/affinity_corpus.rs`](https://github.com/storytold/vectorcraft/blob/6e873b806c9d5b3f2b55f651df57bd97933b579a/xtask/src/affinity_corpus.rs) | CC0-1.0, MIT or Apache-2.0 (per file, in the manifest) | | `crates/raw/docs/coverage/adobe-cameras.tsv` | Facts (maker, model, extension, profile, minimum Camera Raw version) parsed by LightCraft contributors from Adobe's published list | [Adobe Camera Raw supported cameras](https://helpx.adobe.com/camera-raw/desktop/dng-and-file-formats/camera-raw-plug-supported-cameras.html), Wayback capture 20261003133011; moved from [LightCraft `docs/raw`](https://github.com/storytold/lightcraft/tree/5ff567a4a2e067bef1b6bce152c11e7f727ccbaf/docs/raw) | Facts, not copyrightable expression; the file is MIT OR Apache-2.0 | | `crates/raw/docs/coverage/{coverage,coverage-sweep,evidence,usage-weights}.tsv`, `coverage.py` | LightCraft contributors | [LightCraft `docs/raw`](https://github.com/storytold/lightcraft/tree/5ff567a4a2e067bef1b6bce152c11e7f727ccbaf/docs/raw) | MIT OR Apache-2.0 | diff --git a/Cargo.lock b/Cargo.lock index 285897052..2dac6e3ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -396,6 +396,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base16ct" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" + [[package]] name = "base64" version = "0.22.1" @@ -548,6 +554,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-padding" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710f1dd022ef4e93f8a438b4ba958de7f64308434fa6a87104481645cc30068b" +dependencies = [ + "hybrid-array", +] + [[package]] name = "block2" version = "0.5.1" @@ -613,6 +628,30 @@ dependencies = [ "syn 3.0.6", ] +[[package]] +name = "bp256" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46f98c2d9e8e0796b24f84b7ae14159b91ae6ae4b85f74f7655a678a56ad5e1e" +dependencies = [ + "ecdsa 0.17.0", + "elliptic-curve 0.14.3", + "primefield", + "primeorder 0.14.0", +] + +[[package]] +name = "bp384" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc61f3a96b44a33fbb971e9917b81f4207d6dae9a6b0715845c785a48e73d9c2" +dependencies = [ + "ecdsa 0.17.0", + "elliptic-curve 0.14.3", + "primefield", + "primeorder 0.14.0", +] + [[package]] name = "brotli" version = "8.0.4" @@ -765,6 +804,15 @@ dependencies = [ "cipher 0.4.4", ] +[[package]] +name = "cbc" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2dc9ee5f88d11e0beb842c88b33c8a5cf0d1329c4b19494af42b07dbfe8896" +dependencies = [ + "cipher 0.5.2", +] + [[package]] name = "cc" version = "1.6.0" @@ -907,8 +955,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "961b955a666e25ee5a1091d219128d6e6401e3dab84efb1a2bf6b4035d797b39" dependencies = [ "crmf", - "der", - "spki", + "der 0.7.10", + "spki 0.7.3", "x509-cert", ] @@ -919,8 +967,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b77c319abfd5219629c45c34c89ba945ed3c5e49fcde9d16b6c3885f118a730" dependencies = [ "const-oid 0.9.6", - "der", - "spki", + "der 0.7.10", + "spki 0.7.3", "x509-cert", ] @@ -1806,14 +1854,14 @@ dependencies = [ name = "craft-openpgp" version = "0.1.0" dependencies = [ - "ed25519-dalek", + "ed25519-dalek 2.2.0", "pgp", "proptest", "rand 0.8.8", - "rsa", + "rsa 0.9.10", "sha1 0.10.7", "sha2 0.10.9", - "sha3", + "sha3 0.10.9", "thiserror 2.0.21", ] @@ -1884,6 +1932,37 @@ dependencies = [ "zip", ] +[[package]] +name = "craft-pkcs7" +version = "0.1.0" +dependencies = [ + "aes 0.9.4", + "aws-lc-rs", + "base64 0.23.1", + "bp256", + "bp384", + "cbc", + "chrono", + "crypto-bigint 0.7.11", + "des 0.9.0", + "ecdsa 0.17.0", + "ed25519-dalek 3.0.0", + "getrandom 0.4.3", + "hmac 0.13.0", + "p256 0.14.0", + "p384 0.14.0", + "p521 0.14.0", + "pbkdf2", + "rc2", + "ripemd 0.2.0", + "rsa 0.10.0-rc.18", + "sha1 0.11.0", + "sha2 0.11.1", + "sha3 0.12.0", + "thiserror 2.0.21", + "zeroize", +] + [[package]] name = "craft-plate-test" version = "0.1.0" @@ -2403,8 +2482,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36fe21b96d5b87f5de4b5b7202ec41c00110ac817ce6728fe75fb2fe5962ed92" dependencies = [ "cms", - "der", - "spki", + "der 0.7.10", + "spki 0.7.3", "x509-cert", ] @@ -2460,6 +2539,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "crypto-bigint" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914c195c4d7fbc5ed7f88d14cbf85914d5c664967658d43404b263913a477e82" +dependencies = [ + "cpubits", + "ctutils", + "getrandom 0.4.3", + "hybrid-array", + "num-traits", + "rand_core 0.10.1", + "serdect 0.4.3", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.7" @@ -2477,7 +2573,19 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ + "getrandom 0.4.3", "hybrid-array", + "rand_core 0.10.1", +] + +[[package]] +name = "crypto-primes" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3633a51a39c69ebbaa4feaa694bd83d241e4093901c84a0963b19d9bb3f0cf8f" +dependencies = [ + "crypto-bigint 0.7.11", + "rand_core 0.10.1", ] [[package]] @@ -2496,6 +2604,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "261af4dc7a06ea8a527a8717d8cbba3417530d6ea14e1edb3de6b67806be474f" dependencies = [ "cmov", + "subtle", ] [[package]] @@ -2514,7 +2623,23 @@ dependencies = [ "cpufeatures 0.2.17", "curve25519-dalek-derive", "digest 0.10.7", - "fiat-crypto", + "fiat-crypto 0.2.9", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5eed333089e2e1c1ac8c6c0398e5e2497b4c9926ca6d0365ed1e099afa5bc23" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", + "curve25519-dalek-derive", + "digest 0.11.3", + "fiat-crypto 0.3.0", "rustc_version", "subtle", "zeroize", @@ -2537,13 +2662,13 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c0cf476284b03eb6c10e78787b21c7abb7d7d43cb2f02532ba6b831ed892fa" dependencies = [ - "crypto-bigint", - "elliptic-curve", - "pkcs8", + "crypto-bigint 0.5.5", + "elliptic-curve 0.13.8", + "pkcs8 0.10.2", "rand_core 0.6.4", "serdect 0.3.0", - "sha3", - "signature", + "sha3 0.10.9", + "signature 2.2.0", "subtle", "zeroize", ] @@ -2607,7 +2732,18 @@ dependencies = [ "const-oid 0.9.6", "der_derive", "flagset", - "pem-rfc7468", + "pem-rfc7468 0.7.0", + "zeroize", +] + +[[package]] +name = "der" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a996a108feb8b427a6e12fcf6af4aa83409b79d72c15337d7741368131ee004" +dependencies = [ + "const-oid 0.10.3", + "pem-rfc7468 1.0.0", "zeroize", ] @@ -2691,6 +2827,15 @@ dependencies = [ "cipher 0.4.4", ] +[[package]] +name = "des" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916a94e407b54f9034d71dd748234cd1e516ced6284009906ae246f177eafe5a" +dependencies = [ + "cipher 0.5.2", +] + [[package]] name = "dify" version = "0.8.0" @@ -2817,10 +2962,10 @@ dependencies = [ "digest 0.10.7", "num-bigint-dig", "num-traits", - "pkcs8", - "rfc6979", + "pkcs8 0.10.2", + "rfc6979 0.4.0", "sha2 0.10.9", - "signature", + "signature 2.2.0", "zeroize", ] @@ -2849,12 +2994,27 @@ version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der", + "der 0.7.10", "digest 0.10.7", - "elliptic-curve", - "rfc6979", - "signature", - "spki", + "elliptic-curve 0.13.8", + "rfc6979 0.4.0", + "signature 2.2.0", + "spki 0.7.3", +] + +[[package]] +name = "ecdsa" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0681a4fc24c767085329728d8dfba959af91228aa4610cca4f8ce317ba46ae0" +dependencies = [ + "der 0.8.3", + "digest 0.11.3", + "elliptic-curve 0.14.3", + "rfc6979 0.6.0", + "signature 3.0.0", + "spki 0.8.1", + "zeroize", ] [[package]] @@ -2873,8 +3033,17 @@ version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ - "pkcs8", - "signature", + "pkcs8 0.10.2", + "signature 2.2.0", +] + +[[package]] +name = "ed25519" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29fcf32e6c73d1079f83ab4d782de2d81620346a5f38c6237a86a22f8368980a" +dependencies = [ + "signature 3.0.0", ] [[package]] @@ -2883,8 +3052,8 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" dependencies = [ - "curve25519-dalek", - "ed25519", + "curve25519-dalek 4.1.3", + "ed25519 2.2.3", "rand_core 0.6.4", "serde", "sha2 0.10.9", @@ -2892,6 +3061,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ed25519-dalek" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ebaa1a2bf1290ab3bfe5a7b771d050ebffab2711c19a81691c683a5144a25de" +dependencies = [ + "curve25519-dalek 5.0.0", + "ed25519 3.0.0", + "sha2 0.11.1", + "subtle", + "zeroize", +] + [[package]] name = "eframe" version = "0.37.0" @@ -3059,18 +3241,18 @@ version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ - "base16ct", + "base16ct 0.2.0", "base64ct", - "crypto-bigint", + "crypto-bigint 0.5.5", "digest 0.10.7", - "ff", + "ff 0.13.1", "generic-array", - "group", + "group 0.13.0", "hkdf", - "pem-rfc7468", - "pkcs8", + "pem-rfc7468 0.7.0", + "pkcs8 0.10.2", "rand_core 0.6.4", - "sec1", + "sec1 0.7.3", "serde_json", "serdect 0.2.0", "subtle", @@ -3078,6 +3260,26 @@ dependencies = [ "zeroize", ] +[[package]] +name = "elliptic-curve" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900f37e7e18d74a2347389af6cd69e3a30d5cc9e697f40004865679aa75e9c7c" +dependencies = [ + "base16ct 1.0.0", + "crypto-bigint 0.7.11", + "crypto-common 0.2.2", + "digest 0.11.3", + "ff 0.14.0", + "group 0.14.0", + "hybrid-array", + "pkcs8 0.11.0", + "rand_core 0.10.1", + "sec1 0.8.1", + "subtle", + "zeroize", +] + [[package]] name = "emath" version = "0.37.0" @@ -3307,12 +3509,28 @@ dependencies = [ "subtle", ] +[[package]] +name = "ff" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f686ab92a9fb0eaf188f6c6c87b89490baa6fdb0db4544ba4dc47f7942489f" +dependencies = [ + "rand_core 0.10.1", + "subtle", +] + [[package]] name = "fiat-crypto" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "fiat-crypto" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" + [[package]] name = "filetime" version = "0.2.29" @@ -3816,11 +4034,22 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "ff", + "ff 0.13.1", "rand_core 0.6.4", "subtle", ] +[[package]] +name = "group" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd1a1c7a5206c5b7a3f5a0d7ccd3ff85d0c8f5133d62a02680255b0004af5f4" +dependencies = [ + "ff 0.14.0", + "rand_core 0.10.1", + "subtle", +] + [[package]] name = "guillotiere" version = "0.7.0" @@ -4083,7 +4312,9 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17" dependencies = [ + "subtle", "typenum", + "zeroize", ] [[package]] @@ -4507,6 +4738,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a580c13f0ffc335ef42dd3f6b1a41b726051c5e1656d9a3aa6fddb3c5dfbbf9" dependencies = [ + "block-padding 0.4.2", "hybrid-array", ] @@ -4846,11 +5078,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", - "ecdsa", - "elliptic-curve", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", "once_cell", "sha2 0.10.9", - "signature", + "signature 2.2.0", ] [[package]] @@ -4862,6 +5094,16 @@ dependencies = [ "cpufeatures 0.2.17", ] +[[package]] +name = "keccak" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f198d1db720e4940b5a493201d199d9f24f568f8f746bd13706243a2f71598" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", +] + [[package]] name = "keyboard-types" version = "0.8.3" @@ -5810,38 +6052,79 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", + "primeorder 0.13.6", "sha2 0.10.9", ] +[[package]] +name = "p256" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c9239b2dbc807adbbe147e8cf72ea7450c3a0aabe62cb8e75ff4ec22e1f72a" +dependencies = [ + "ecdsa 0.17.0", + "elliptic-curve 0.14.3", + "primefield", + "primeorder 0.14.0", + "sha2 0.11.1", +] + [[package]] name = "p384" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", + "primeorder 0.13.6", "sha2 0.10.9", ] +[[package]] +name = "p384" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d17b851e6b3e378ab4ecb07fa2ed23f4d15f075735f8fec9fa1e7bdce5f8301f" +dependencies = [ + "ecdsa 0.17.0", + "elliptic-curve 0.14.3", + "fiat-crypto 0.3.0", + "primefield", + "primeorder 0.14.0", + "sha2 0.11.1", +] + [[package]] name = "p521" version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" dependencies = [ - "base16ct", - "ecdsa", - "elliptic-curve", - "primeorder", + "base16ct 0.2.0", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", + "primeorder 0.13.6", "rand_core 0.6.4", "sha2 0.10.9", ] +[[package]] +name = "p521" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ad64cc32c2dc466317c12ee5853e61f159f9eab1fe7efade0395dc2e7b43449" +dependencies = [ + "base16ct 1.0.0", + "ecdsa 0.17.0", + "elliptic-curve 0.14.3", + "primefield", + "primeorder 0.14.0", + "sha2 0.11.1", +] + [[package]] name = "parking" version = "2.2.1" @@ -5888,6 +6171,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "pbkdf2" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112d82ceb8c5bf524d9af484d4e4970c9fd5a0cc15ba14ad93dccd28873b0629" +dependencies = [ + "digest 0.11.3", + "hmac 0.13.0", +] + [[package]] name = "pdf-writer" version = "0.15.0" @@ -5919,6 +6212,15 @@ dependencies = [ "base64ct", ] +[[package]] +name = "pem-rfc7468" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6305423e0e7738146434843d1694d621cce767262b2a86910beab705e4493d9" +dependencies = [ + "base64ct", +] + [[package]] name = "peniko" version = "0.6.1" @@ -5951,7 +6253,7 @@ dependencies = [ "argon2", "base64 0.22.1", "bitfields", - "block-padding", + "block-padding 0.3.3", "blowfish", "buffer-redux", "byteorder", @@ -5962,17 +6264,17 @@ dependencies = [ "cipher 0.4.4", "const-oid 0.9.6", "crc24", - "curve25519-dalek", + "curve25519-dalek 4.1.3", "cx448", "derive_builder", "derive_more", - "des", + "des 0.8.1", "digest 0.10.7", "dsa", "eax", - "ecdsa", - "ed25519-dalek", - "elliptic-curve", + "ecdsa 0.16.9", + "ed25519-dalek 2.2.0", + "elliptic-curve 0.13.8", "flate2", "generic-array", "getrandom 0.2.17", @@ -5988,18 +6290,18 @@ dependencies = [ "num-traits", "num_enum", "ocb3", - "p256", - "p384", - "p521", + "p256 0.13.2", + "p384 0.13.1", + "p521 0.13.3", "rand 0.8.8", "replace_with", - "ripemd", - "rsa", + "ripemd 0.1.3", + "rsa 0.9.10", "sha1 0.10.7", "sha1-checked", "sha2 0.10.9", - "sha3", - "signature", + "sha3 0.10.9", + "signature 2.2.0", "smallvec", "snafu", "subtle", @@ -6110,9 +6412,19 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ - "der", - "pkcs8", - "spki", + "der 0.7.10", + "pkcs8 0.10.2", + "spki 0.7.3", +] + +[[package]] +name = "pkcs1" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6250dd7321adbe93d12b750aee0ced159fd13e77f625edcdf1cb6f83cd99f650" +dependencies = [ + "der 0.8.3", + "spki 0.8.1", ] [[package]] @@ -6121,8 +6433,18 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der", - "spki", + "der 0.7.10", + "spki 0.7.3", +] + +[[package]] +name = "pkcs8" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7" +dependencies = [ + "der 0.8.3", + "spki 0.8.1", ] [[package]] @@ -6292,13 +6614,40 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" +[[package]] +name = "primefield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c555a6e4eb7d4e158fcb028c835c3b8642206ddc279b5c6b202ef9a8bdb592f4" +dependencies = [ + "crypto-bigint 0.7.11", + "crypto-common 0.2.2", + "ff 0.14.0", + "rand_core 0.10.1", + "subtle", + "zeroize", +] + [[package]] name = "primeorder" version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ - "elliptic-curve", + "elliptic-curve 0.13.8", +] + +[[package]] +name = "primeorder" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c9f42978c78a00e3d68f69fc03e57a234debae69da4020a4fb588fcdcd07b06" +dependencies = [ + "elliptic-curve 0.14.3", + "once_cell", + "primefield", + "serdect 0.4.3", + "wnaf", ] [[package]] @@ -6598,6 +6947,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rc2" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceda21af1ae61033b63175653a1af86cae399d79cd03ca80ba347eb3a6c4a7fe" +dependencies = [ + "cipher 0.5.2", +] + [[package]] name = "read-fonts" version = "0.39.2" @@ -6771,6 +7129,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "rfc6979" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4a459cddafb3fe76b31fd8f1108007566c40301feb64dc7b54656eb7388172b" +dependencies = [ + "crypto-bigint 0.7.11", + "hmac 0.13.0", +] + [[package]] name = "rfd" version = "0.17.2" @@ -6827,6 +7195,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "ripemd" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd4211456b4172d7e44261920c25acf07367c4f04bb5f5d54fc21b090d9b159" +dependencies = [ + "digest 0.11.3", +] + [[package]] name = "roxmltree" version = "0.20.0" @@ -6853,15 +7230,32 @@ dependencies = [ "num-bigint-dig", "num-integer", "num-traits", - "pkcs1", - "pkcs8", + "pkcs1 0.7.5", + "pkcs8 0.10.2", "rand_core 0.6.4", - "signature", - "spki", + "signature 2.2.0", + "spki 0.7.3", "subtle", "zeroize", ] +[[package]] +name = "rsa" +version = "0.10.0-rc.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b2aa4ba0d89f73d1e332df05be0eeab8840351c36ca5654341dfdb57bb3caf" +dependencies = [ + "const-oid 0.10.3", + "crypto-bigint 0.7.11", + "crypto-primes", + "digest 0.11.3", + "pkcs1 0.8.0", + "pkcs8 0.11.0", + "rand_core 0.10.1", + "signature 3.0.0", + "zeroize", +] + [[package]] name = "rustc-hash" version = "1.1.0" @@ -7080,15 +7474,29 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ - "base16ct", - "der", + "base16ct 0.2.0", + "der 0.7.10", "generic-array", - "pkcs8", + "pkcs8 0.10.2", "serdect 0.2.0", "subtle", "zeroize", ] +[[package]] +name = "sec1" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56d437c2f19203ce5f7122e507831de96f3d2d4d3be5af44a0b0a09d8a80e4d" +dependencies = [ + "base16ct 1.0.0", + "ctutils", + "der 0.8.3", + "hybrid-array", + "subtle", + "zeroize", +] + [[package]] name = "security-framework" version = "3.7.0" @@ -7226,7 +7634,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" dependencies = [ - "base16ct", + "base16ct 0.2.0", "serde", ] @@ -7236,7 +7644,17 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f42f67da2385b51a5f9652db9c93d78aeaf7610bf5ec366080b6de810604af53" dependencies = [ - "base16ct", + "base16ct 0.2.0", + "serde", +] + +[[package]] +name = "serdect" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66cf8fedced2fcf12406bcb34223dffb92eaf34908ede12fed414c82b7f00b3e" +dependencies = [ + "base16ct 1.0.0", "serde", ] @@ -7302,7 +7720,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" dependencies = [ "digest 0.10.7", - "keccak", + "keccak 0.1.6", +] + +[[package]] +name = "sha3" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9bad02c26382724b2d2692c6f179285e4b54eeecd7968f52a50059c3c11759" +dependencies = [ + "digest 0.11.3", + "keccak 0.2.2", + "sponge-cursor", ] [[package]] @@ -7331,6 +7760,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "signature" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5" +dependencies = [ + "digest 0.11.3", + "rand_core 0.10.1", +] + [[package]] name = "sigstore-bundle" version = "0.6.6" @@ -7358,14 +7797,14 @@ dependencies = [ "aws-lc-rs", "base64 0.22.1", "const-oid 0.9.6", - "der", + "der 0.7.10", "digest 0.10.7", "pem", "rand_core 0.10.1", "sha2 0.10.9", - "signature", + "signature 2.2.0", "sigstore-types", - "spki", + "spki 0.7.3", "thiserror 2.0.21", "tracing", "x509-cert", @@ -7432,7 +7871,7 @@ dependencies = [ "cmpv2", "cms", "const-oid 0.9.6", - "der", + "der 0.7.10", "hex", "rand 0.10.3", "reqwest", @@ -7666,9 +8105,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der", + "der 0.7.10", ] +[[package]] +name = "spki" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef958a98b9d5da290cfc78946e9f3e61e1e62a18db0d92cac0b83cc161491a9" +dependencies = [ + "base64ct", + "der 0.8.3", +] + +[[package]] +name = "sponge-cursor" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a0219bd7d979d58245a4f41f695e1ac9f8befdffadd7f61f1bae9e39abc6620" + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -9543,6 +9998,18 @@ version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" +[[package]] +name = "wnaf" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "795ca18b3fdb5e62bf982199278341ddcf7ebf7d32e25e212ad05d496e95f6fa" +dependencies = [ + "ff 0.14.0", + "group 0.14.0", + "hybrid-array", + "primefield", +] + [[package]] name = "write-fonts" version = "0.48.1" @@ -9631,7 +10098,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 4.1.3", "rand_core 0.6.4", "serde", "zeroize", @@ -9644,10 +10111,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" dependencies = [ "const-oid 0.9.6", - "der", + "der 0.7.10", "sha1 0.10.7", - "signature", - "spki", + "signature 2.2.0", + "spki 0.7.3", "tls_codec", ] @@ -9659,7 +10126,7 @@ checksum = "f5ceece934a21607055b7ac5c25adb56a2ff559804b10705dc674d1d838c15e1" dependencies = [ "cmpv2", "cms", - "der", + "der 0.7.10", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b026ad3fc..3a7c5c9f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,6 +93,7 @@ craft-ora = { path = "crates/ora" } craft-pptx = { path = "crates/pptx" } craft-penpot = { path = "crates/penpot" } craft-pcraft-format = { path = "crates/pcraft-format" } +craft-pkcs7 = { path = "crates/pkcs7" } craft-plotter = { path = "crates/plotter" } craft-prepress = { path = "crates/prepress" } craft-print = { path = "crates/print" } diff --git a/README.md b/README.md index bc693fc7f..d68b972f8 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,10 @@ craft- = { git = "https://github.com/storytold/craft-libs", rev = "` with the document as a type parameter, `TileRef`, the entry paths, the manifest decode limits and the migration runner. The document model stays in PhotoCraft. +- [`craft-pkcs7`](crates/pkcs7/README.md): the formats of digital signatures, read, verified and + written: ASN.1 DER, X.509 certificates and chains, CMS SignedData (PKCS #7), PKCS #12 identity + files, RFC 3161 timestamps, and CRL / OCSP revocation evidence. What a signature means for a + document or a message stays in each app. - [`craft-penpot`](crates/penpot/README.md): clean-room reader and writer for the Penpot 2.x export container (`.penpot`): the ZIP archive, its manifest, the per-file, per-page and per-shape JSON members and media objects, as the JSON the file holds. Bounded on hostile input. Carved from diff --git a/crates/pkcs7/Cargo.toml b/crates/pkcs7/Cargo.toml new file mode 100644 index 000000000..8434a7a55 --- /dev/null +++ b/crates/pkcs7/Cargo.toml @@ -0,0 +1,53 @@ +[package] +name = "craft-pkcs7" +description = "The formats of digital signatures: ASN.1 DER, X.509 certificates and chains, CMS SignedData (PKCS #7), PKCS #12 identity files, RFC 3161 timestamps, and CRL / OCSP revocation evidence, read, verified and written." +version.workspace = true +edition.workspace = true +license.workspace = true +rust-version.workspace = true +repository.workspace = true + +[lints] +workspace = true + +# Every dependency here is MIT OR Apache-2.0 (RustCrypto, base64, chrono, thiserror), except +# ed25519-dalek (BSD-3-Clause) and aws-lc-rs (ISC AND (Apache-2.0 OR ISC)), all on the allowlist. +[dependencies] +thiserror = { workspace = true } +zeroize = "1" +# ASN.1 UTCTime/GeneralizedTime conversion goes through chrono (no hand-rolled calendar code). +chrono = { workspace = true } +base64 = "0.23" +sha1 = "0.11" +sha2 = "0.11" +sha3 = "0.12.0" +ripemd = "0.2.0" +p256 = { version = "0.14", default-features = false, features = ["ecdsa", "std"] } +p384 = { version = "0.14", default-features = false, features = ["ecdsa", "std"] } +# Verification only: P-521 and the Brainpool curves German qualified-signature cards use. +p521 = { version = "0.14", default-features = false, features = ["ecdsa", "std"] } +bp256 = { version = "0.14", default-features = false, features = ["arithmetic", "ecdsa", "std"] } +bp384 = { version = "0.14", default-features = false, features = ["arithmetic", "ecdsa", "std"] } +ecdsa = { version = "0.17", default-features = false, features = ["algorithm", "der"] } +ed25519-dalek = "3.0.0" +# Verification only on native targets (RSA private-key operations use aws-lc-rs). +crypto-bigint = { version = "0.7.11", default-features = false, features = ["alloc"] } +rsa = { version = "=0.10.0-rc.18", default-features = false, features = ["std", "hazmat"] } +pbkdf2 = { version = "0.13", default-features = false, features = ["hmac"] } +hmac = "0.13" +aes = "0.9" +cbc = { version = "0.2", features = ["alloc", "block-padding"] } +des = "0.9" +rc2 = "0.9" + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +aws-lc-rs = { version = "1.18", default-features = false, features = ["aws-lc-sys", "prebuilt-nasm"] } +getrandom = "0.4" + +[target.'cfg(target_arch = "wasm32")'.dependencies] +# crypto-bigint asks for randomness; in the browser it comes from Web Crypto. +getrandom = { version = "0.4", features = ["wasm_js"] } + +[[test]] +name = "it" +path = "tests/it/main.rs" diff --git a/crates/pkcs7/README.md b/crates/pkcs7/README.md new file mode 100644 index 000000000..fc715c3b9 --- /dev/null +++ b/crates/pkcs7/README.md @@ -0,0 +1,44 @@ +# craft-pkcs7 + +The formats of digital signatures, read, verified and written: what a signed PDF, a signed mail +message or a digital ID file is made of. + +- **`der`**: a small BER/DER reader and writer (ITU-T X.690). A `Tlv` borrows from the input and + keeps its exact encoding, so a signed structure is verified over the bytes that were signed. + Reading is strict DER; `parse_ber` also takes indefinite lengths and segmented strings, which + PKCS #12 files from Windows use. Nesting is bounded. +- **`x509`**: certificates (RFC 5280): names, validity, key, the extensions that matter for + signing (basic constraints, key usage, extended key usage, key identifiers, OCSP and CRL + locations), `build_chain` / `build_chain_noted` (issuers that may issue, path length, validity, + unprocessed critical extensions), `load_certificates` (DER, PEM, PKCS #7 bundles), `to_pem`, + and `Certificate::self_signed`. An extension that is present but unreadable restricts: an + unreadable key usage allows no usage, an unreadable extended key usage no purpose. +- **`cms`**: CMS SignedData (RFC 5652): `SignedData::parse` and `verify_signature`, + `sign_detached` / `sign_encapsulated`, `certificate_bundle`, and `attach_timestamp_token`. +- **`pkcs12`**: `.p12` / `.pfx` (RFC 7292): `open` reads PBES2 (PBKDF2 with HMAC-SHA-1/2; + AES-CBC or 3DES-CBC) and the legacy PBE schemes (SHA-1 with 3DES or RC2) and checks the MAC, + stopping at a fixed amount of key-derivation work; `write` uses PBES2 AES-256-CBC with + PBKDF2-HMAC-SHA-256. +- **`timestamp`**: RFC 3161 requests, responses and tokens, and a responder for a local + stamping identity. No transport: `TimestampAuthority` is the caller's. +- **`revocation`**: CRLs (RFC 5280) and OCSP responses (RFC 6960): parsed, their signatures + verified, and a certificate's status looked up. Nothing is fetched. +- **`keys`**: digests (SHA-1, SHA-2, SHA-3, RIPEMD-160), public keys for verification (RSA + PKCS #1 v1.5 and PSS, ECDSA on P-256, P-384, P-521 and the Brainpool curves, Ed25519) and + private keys for signing (RSA, P-256, P-384, or a key held elsewhere behind `ExternalKey`). + +What a signature means for a document or a message stays with the caller: which bytes it covers, +what changed after it, which certificates are trusted, and how a result is worded. + +## Cryptography + +The primitives are RustCrypto's; RSA private-key operations use aws-lc-rs on native targets. +Two things are done in this crate, both verification only and on public data, because no audited +crate offers them: the RSA signature paddings for any digest, MGF1 hash and salt length +(`rsa_pad`, over the `rsa` crate's raw public-key operation), and ECDSA on brainpoolP512r1 +(`ec512`, over `crypto-bigint`). Both are checked against signatures made by OpenSSL. + +Weak algorithms are read, not refused, because old signed documents use them: +`DigestAlg::weakness` and `PublicKey::weakness` say when one is weak, and the caller decides. + +Moved from PdfCraft's `pdfcraft-sign`. diff --git a/crates/pkcs7/src/cms.rs b/crates/pkcs7/src/cms.rs new file mode 100644 index 000000000..083aa4302 --- /dev/null +++ b/crates/pkcs7/src/cms.rs @@ -0,0 +1,595 @@ +//! CMS SignedData (RFC 5652) as PDF signatures use it: detached (`adbe.pkcs7.detached`, +//! `ETSI.CAdES.detached`) or with the digest encapsulated (`adbe.pkcs7.sha1`). + +use crate::Error; +use crate::der::{self, Time, Tlv, tag}; +use crate::keys::{DigestAlg, PrivateKey, Scheme, signature_algorithm}; +use crate::x509::Certificate; + +pub const SIGNED_DATA: &str = "1.2.840.113549.1.7.2"; +pub const DATA: &str = "1.2.840.113549.1.7.1"; +const CONTENT_TYPE: &str = "1.2.840.113549.1.9.3"; +const MESSAGE_DIGEST: &str = "1.2.840.113549.1.9.4"; +const SIGNING_TIME: &str = "1.2.840.113549.1.9.5"; +const SIGNING_CERT_V2: &str = "1.2.840.113549.1.9.16.2.47"; +const SIGNING_CERT: &str = "1.2.840.113549.1.9.16.2.12"; +const TIMESTAMP_TOKEN: &str = "1.2.840.113549.1.9.16.2.14"; + +/// How a signer names its certificate. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum SignerId { + IssuerSerial { issuer: Vec, serial: Vec }, + KeyId(Vec), +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SignerInfo { + pub sid: SignerId, + pub digest: DigestAlg, + /// The signed attributes as the SET that was signed (`None`: the signature covers the + /// content itself). + pub signed_attrs: Option>, + pub message_digest: Option>, + pub content_type: Option, + pub signing_time: Option