diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9eb55aef..8467f23f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,8 @@ permissions: env: CARGO_TERM_COLOR: always + # RSA-PSS vectors always run; CI additionally requires reciprocal live checks. + OPENSSL_BIN: openssl RUSTFLAGS: -Dwarnings XMLSEC1_PREFIX: ${{ github.workspace }}/.tools/xmlsec1-1.3.13 XMLSEC1_BIN: ${{ github.workspace }}/.tools/xmlsec1-1.3.13/bin/xmlsec1 diff --git a/LICENSE-THIRD-PARTY b/LICENSE-THIRD-PARTY index f6efba2d..3618989d 100644 --- a/LICENSE-THIRD-PARTY +++ b/LICENSE-THIRD-PARTY @@ -1,11 +1,12 @@ The xml-sec crate includes code derived from the following projects. Their copyright and permission notices are preserved below. -sad-rsa 0.10.2 (src/provider/rsa_pkcs1v15.rs) +sad-rsa 0.10.2 (src/provider/rsa_pkcs1v15.rs, src/provider/rsa_pss.rs) ------------------------------------------ Source: https://github.com/sadco-io/sad-rsa Local fixed-width recovery adaptation: docs/rsa-recovery-patch.md +Local parameterized PSS adaptation: docs/rsa-pss-patch.md Copyright (c) 2025-2026 Sadco Security Team Copyright (c) 2015-2025 RustCrypto Developers diff --git a/README.md b/README.md index 4402027c..ccf56fef 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ xml-sec = { version = "0.1", default-features = false, features = ["xmldsig", "c | Area | Available today | |------|-----------------| | Canonicalization | Canonical XML 1.0/1.1, Exclusive C14N, comments, and document subsets | -| XML signatures | XMLDSig signing and verification, RSA/DSA/ECDSA/HMAC, XPath transforms, `Manifest`, `KeyInfo`, and caller-provided references | +| XML signatures | XMLDSig signing and verification, RSA-PSS/PKCS#1, DSA/ECDSA/HMAC, XPath transforms, `Manifest`, `KeyInfo`, and caller-provided references | | XML encryption | AES-CBC/GCM, RSA-OAEP, AES Key Wrap, multiple recipients, and Element/Content replacement | | Optional compatibility algorithms | `legacy-algorithms`: MD5/RIPEMD-160 signatures and digests, AES-192, TripleDES-CBC/CMS wrap, and RSA-1.5 transport; library policy denies these by default | | X.509 | Certificate key extraction, chain validation, CRLs, required key authorization by default, and typed trust evidence | diff --git a/compatibility/libxmlsec1-1.3.13-rules.json b/compatibility/libxmlsec1-1.3.13-rules.json index 1a15f161..aeade1e8 100644 --- a/compatibility/libxmlsec1-1.3.13-rules.json +++ b/compatibility/libxmlsec1-1.3.13-rules.json @@ -47,6 +47,22 @@ } }, "rules": [ + { + "id": "native-rsa-pss-uri", + "kinds": ["algorithm-uri"], + "name_regex": "^xmlSecHrefRsaPssSha(?:224|256|384|512|3_224|3_256|3_384|3_512)$", + "outcome": "behavior-compatible", + "rationale": "RSA-PSS fixed URI signing and verification execute through CryptoProvider with exact digest-sized salt and matching MGF1; the complete upstream PSS family is exercised by public pipeline tests.", + "evidence": "native-algorithm-tests" + }, + { + "id": "legacy-rsa-pss-uri", + "kinds": ["algorithm-uri"], + "name_regex": "^xmlSecHrefRsaPssSha1$", + "outcome": "compatibility-profile-only", + "rationale": "RSA-PSS SHA-1 is implemented but requires explicit legacy signature policy permission.", + "evidence": "legacy-policy-tests" + }, { "id": "native-xpath-uri", "kinds": ["algorithm-uri"], diff --git a/compatibility/libxmlsec1-1.3.13.json b/compatibility/libxmlsec1-1.3.13.json index edea8500..2b36cada 100644 --- a/compatibility/libxmlsec1-1.3.13.json +++ b/compatibility/libxmlsec1-1.3.13.json @@ -74,6 +74,11 @@ "rationale": "The legacy-algorithms feature implements this mechanism through RustCrypto. Library defaults deny it; an explicit immutable algorithm allowlist is required. Other providers may report the capability unavailable without fallback.", "evidence": "legacy-policy-tests" }, + "legacy-rsa-pss-uri": { + "outcome": "compatibility-profile-only", + "rationale": "RSA-PSS SHA-1 is implemented but requires explicit legacy signature policy permission.", + "evidence": "legacy-policy-tests" + }, "native-cli-behavior-options": { "outcome": "behavior-compatible", "rationale": "The native CLI implements this provider-independent option with donor-compatible parsing and command behavior.", @@ -94,6 +99,11 @@ "rationale": "The native CLI implements this option only for the formats, algorithms, or fixed RustCrypto provider behavior advertised by its capability registry.", "evidence": "native-cli-tests" }, + "native-rsa-pss-uri": { + "outcome": "behavior-compatible", + "rationale": "RSA-PSS fixed URI signing and verification execute through CryptoProvider with exact digest-sized salt and matching MGF1; the complete upstream PSS family is exercised by public pipeline tests.", + "evidence": "native-algorithm-tests" + }, "native-sha1-verification-uri": { "outcome": "behavior-compatible", "rationale": "The native Rust API implements SHA-1 reference digests; secure signing defaults reject SHA-1 while an explicit compatibility policy can opt in.", @@ -5006,7 +5016,7 @@ "source": "src/strings.c", "line": 766, "detail": "http://www.w3.org/2007/05/xmldsig-more#sha1-rsa-MGF1", - "classification": "remaining-uri-surface" + "classification": "legacy-rsa-pss-uri" }, { "kind": "algorithm-uri", @@ -5014,7 +5024,7 @@ "source": "src/strings.c", "line": 769, "detail": "http://www.w3.org/2007/05/xmldsig-more#sha224-rsa-MGF1", - "classification": "remaining-uri-surface" + "classification": "native-rsa-pss-uri" }, { "kind": "algorithm-uri", @@ -5022,7 +5032,7 @@ "source": "src/strings.c", "line": 772, "detail": "http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1", - "classification": "remaining-uri-surface" + "classification": "native-rsa-pss-uri" }, { "kind": "algorithm-uri", @@ -5030,7 +5040,7 @@ "source": "src/strings.c", "line": 775, "detail": "http://www.w3.org/2007/05/xmldsig-more#sha384-rsa-MGF1", - "classification": "remaining-uri-surface" + "classification": "native-rsa-pss-uri" }, { "kind": "algorithm-uri", @@ -5038,7 +5048,7 @@ "source": "src/strings.c", "line": 781, "detail": "http://www.w3.org/2007/05/xmldsig-more#sha3-224-rsa-MGF1", - "classification": "remaining-uri-surface" + "classification": "native-rsa-pss-uri" }, { "kind": "algorithm-uri", @@ -5046,7 +5056,7 @@ "source": "src/strings.c", "line": 784, "detail": "http://www.w3.org/2007/05/xmldsig-more#sha3-256-rsa-MGF1", - "classification": "remaining-uri-surface" + "classification": "native-rsa-pss-uri" }, { "kind": "algorithm-uri", @@ -5054,7 +5064,7 @@ "source": "src/strings.c", "line": 787, "detail": "http://www.w3.org/2007/05/xmldsig-more#sha3-384-rsa-MGF1", - "classification": "remaining-uri-surface" + "classification": "native-rsa-pss-uri" }, { "kind": "algorithm-uri", @@ -5062,7 +5072,7 @@ "source": "src/strings.c", "line": 790, "detail": "http://www.w3.org/2007/05/xmldsig-more#sha3-512-rsa-MGF1", - "classification": "remaining-uri-surface" + "classification": "native-rsa-pss-uri" }, { "kind": "algorithm-uri", @@ -5070,7 +5080,7 @@ "source": "src/strings.c", "line": 778, "detail": "http://www.w3.org/2007/05/xmldsig-more#sha512-rsa-MGF1", - "classification": "remaining-uri-surface" + "classification": "native-rsa-pss-uri" }, { "kind": "algorithm-uri", diff --git a/docs/crypto-providers.md b/docs/crypto-providers.md index b6e374d0..8cf50cbc 100644 --- a/docs/crypto-providers.md +++ b/docs/crypto-providers.md @@ -42,7 +42,11 @@ SHA-1. Operational errors expose typed redacted classes, never raw module diagnostics or credentials. An explicit invalid-ciphertext result maps to `AuthenticationFailed`; a module's generic failure remains an operational error, not proof of a bad authentication tag. Both paths release no plaintext. -RSA-PSS/ECDSA signing, certificate/CRL verification, +RSA-PSS signing/verification supports SHA-1/256/384/512 with independent +MGF1 SHA-1/224/256/384/512 and explicit salt length, when the token accepts +the selected parameters. SHA-224/SHA-3 PSS message digests are not advertised +because the adapter does not expose matching combined token mechanisms. +ECDSA signing, certificate/CRL verification, private software key import, raw symmetric encryption, and KDF execution are not advertised by this adapter. @@ -86,6 +90,15 @@ Without it, that selection is an explicit unavailable-provider error. ## Mechanisms +RustCrypto implements all nine fixed RSA-PSS SHA-1/SHA-2/SHA-3 signature URIs +and parameterized `rsa-pss` via `SignatureAlgorithm::RsaPss(RsaPssParameters)`. +Message hash and MGF1 hash may differ; salt length is exact, including zero, +and must fit the RSA modulus. XML defaults are SHA-256, digest-sized salt and +trailer 1 ([RFC 9231 section 2.3.9](https://www.rfc-editor.org/rfc/rfc9231.html#section-2.3.9)). +SHA-1 in either hash requires explicit legacy policy permission. Fixed URI +variants reject parameters rather than silently overriding their contract. +The narrow [local padding adaptation](rsa-pss-patch.md) retains sad-rsa arithmetic. + `legacy-algorithms` adds RustCrypto MD5/RIPEMD-160 signatures and digests, AES-192 content encryption and key wrap, TripleDES content encryption and CMS wrap, and RSA-1.5 transport. All operations still go through `CryptoProvider` and require explicit library policy @@ -95,6 +108,7 @@ every primitive present in the underlying AWS-LC library or an approved-service The AWS provider supports SHA-1/SHA-2 and SHA3-256/384/512 digests; RSA PKCS#1 v1.5 signing with SHA-256/384/512 and verification with those digests or SHA-1; native +RSA-PSS signing/verification with SHA-256/384/512, matching MGF1 and digest-sized salt; ECDSA curve/digest combinations exposed by AWS-LC; AES-128/256 CBC and GCM; AES-128/256 key wrap; and RSA-OAEP with SHA-1/256/384/512 when MGF uses the same digest. RSA-OAEP labels are preserved. Certificate and CRL verification uses DER diff --git a/docs/rsa-pss-patch.md b/docs/rsa-pss-patch.md new file mode 100644 index 00000000..4b3a9cd3 --- /dev/null +++ b/docs/rsa-pss-patch.md @@ -0,0 +1,27 @@ +# Parameterized RSA-PSS Adaptation + +`src/provider/rsa_pss.rs` adapts sad-rsa 0.10.2's PSS encoding and MGF1 from +`src/pss.rs` and `src/algorithms/{pss,mgf}.rs`. RSA arithmetic, blinding and +fault checking remain in that dependency's `hazmat` primitives. No additional +RSA engine or separately published crate is introduced. + +The dependency's PSS API uses one digest for both the message and MGF1. +[RFC 9231 section 2.3.9](https://www.rfc-editor.org/rfc/rfc9231.html#section-2.3.9) +permits independent hashes and an explicit salt length. The local adaptation +implements those parameters using the existing SHA implementations. MGF1 hashes +borrowed chunks into stack storage rather than allocating a digest object or +buffer for every block. + +[RFC 8017 sections 9.1.1 and 9.1.2](https://www.rfc-editor.org/rfc/rfc8017.html#section-9.1) +govern encoding and checking. Verification requires the exact selected salt +length; it never guesses one from the signature. Modulus capacity is checked +before randomness or padding allocation, and nonzero leading representative +octets are rejected rather than silently truncated for non-byte-aligned keys. +RSAVP1 rejects signature integers greater than or equal to the modulus before +exponentiation, as required by [RFC 8017 section 5.2.2](https://www.rfc-editor.org/rfc/rfc8017.html#section-5.2.2); +raw modular exponentiation would otherwise accept aliases of a valid signature. +The signing padding buffer, including its random salt, is zeroized on drop. + +When updating sad-rsa, compare the named donor functions and hazmat interfaces +with this module. Independent dependency and XML-security oracle tests protect +the standard encodings and the parameterized extension. diff --git a/docs/xmldsig.md b/docs/xmldsig.md index ae01471f..b6defa42 100644 --- a/docs/xmldsig.md +++ b/docs/xmldsig.md @@ -13,7 +13,7 @@ use wildcard match arms and obtain `SignedInfo` through the parser. The `xmldsig` feature provides signing and verification pipelines for same-document XML signatures and detached references whose payloads the caller supplies. It supports inclusive and exclusive canonicalization, enveloped signatures, -Base64, XPath 1.0, and XPath Filter 2.0 transforms, RSA PKCS#1 v1.5, DSA, +Base64, XPath 1.0, and XPath Filter 2.0 transforms, RSA PKCS#1 v1.5, RSA-PSS, DSA, ECDSA with P-256/P-384/P-521 keys, HMAC truncation, embedded X.509 certificates, and configured key resolution. @@ -230,8 +230,8 @@ implementation only when the provider has no primitive work to observe. `VerifyContext::provider` covers every verification-time cryptographic operation, including reference digests, document signatures, `X509Digest` selector evaluation, X.509 candidate-path edges, complete certificate paths, and CRL authentication performed by `DefaultKeyResolver`. -Certificate authentication uses a separate typed algorithm contract so RSA-PSS parameters and -Ed25519 are not collapsed into the narrower XMLDSig `SignatureMethod` enum. Unsupported certificate +Certificate authentication uses a separate typed algorithm contract because certificate encodings +and algorithm permissions are independent of XMLDSig `SignatureMethod`. Unsupported certificate OIDs remain typed path errors rather than ordinary signature mismatches. Every certificate OID represented by that contract reaches the selected provider; the built-in provider may reject a capability such as ECDSA-SHA512 while a custom provider can implement it. For an @@ -458,7 +458,8 @@ These are historical interoperability mechanisms, not recommended algorithms for new documents. Implemented signature methods include DSA-SHA1/SHA256; HMAC-SHA1/SHA224/SHA256/SHA384/SHA512; -RSA PKCS#1 v1.5 with SHA-1/SHA224/SHA256/SHA384/SHA512; and ECDSA +RSA PKCS#1 v1.5 with SHA-1/SHA224/SHA256/SHA384/SHA512; RSA-PSS with SHA-1, +SHA224/SHA256/SHA384/SHA512 and SHA3-224/256/384/512; and ECDSA SHA-1/SHA224/SHA256/SHA384/SHA512 and SHA3-224/256/384/512. ECDSA selects P-256, P-384, or P-521 from the key independently of the hash identifier. Digest methods include SHA-1/SHA224/SHA256/SHA384/SHA512 and SHA3-224/256/384/512. EdDSA supports pure Ed25519, @@ -537,5 +538,35 @@ and these post-quantum methods require absent parameters; RSA PKCS#1 accepts NULL or absent; RSA-PSS requires valid typed parameters. An `id-RSASSA-PSS` issuer key with absent parameters imposes no parameter restrictions, as required by RFC 4055 section 3.3; present key parameters constrain the signature hash, MGF, -minimum salt length, and trailer field. XMLDSig `SignatureMethod` RSA-PSS and implicit external -resource loading are not currently supported. +minimum salt length, and trailer field. Implicit external resource loading is not supported. + +## RSA-PSS Parameters + +The nine fixed RSA-PSS methods use MGF1 with the signature digest and a salt of that digest's +width. `SignatureAlgorithm::RsaPss(RsaPssParameters)` represents the parameterized method from +[RFC 9231 section 2.3.9](https://www.rfc-editor.org/rfc/rfc9231.html#section-2.3.9), with independent +`digest`, `mgf_digest`, and exact `salt_len`. The builder emits `RSAPSSParams`; template signing +and verification parse the same typed parameters. + +An omitted digest defaults to SHA-256. An omitted MGF uses the signature digest; an explicit +MGF1 element without its digest uses SHA-256. An omitted salt length uses the signature digest's +width. Only trailer field 1 is supported. Parsing rejects duplicate, reordered, unknown, or +malformed parameters, and salt lengths outside the nonnegative `xs:int` range. Key preflight +rejects salts that cannot fit the RSA encoded message before signing work. + +SHA-1 in either the message digest or MGF requires explicit legacy permission for the exact +signature method, or an explicit `KeyTrustPolicy::parameterized_rsa_pss` family permission. +`RsaPssPermission::AllSupported` in the signing or verification policy grants the parameterized +family without enumerating salt lengths; verification retains the independent legacy trust gate. +All family permissions default to `ExactOnly`. The compatibility CLI sets both permissions before +reading input, never deriving policy from a document's parameters. +An `id-RSASSA-PSS` public key also enforces its hash, MGF, minimum salt length, +and trailer restrictions; an unrestricted RSA key does not add those restrictions. + +RustCrypto supports independent hashes and exact salts. Other providers expose only their native +capabilities, with no fallback; see [provider capabilities](crypto-providers.md). The narrow +[local RSA-PSS adaptation](rsa-pss-patch.md) retains the existing RSA arithmetic, blinding, and +fault checks. Tests cover every pinned xmlsec1 RSA-PSS fixture, reciprocal signing, restricted +keys, malformed encodings, mixed hashes, and salt/modulus boundaries. +Saved OpenSSL vectors run without external programs; set `OPENSSL_BIN` to additionally require +live reciprocal OpenSSL checks. A configured but unavailable oracle fails the test. CI enables it. diff --git a/scripts/import-donor-fixtures.sh b/scripts/import-donor-fixtures.sh index a3dce92b..a4c92776 100755 --- a/scripts/import-donor-fixtures.sh +++ b/scripts/import-donor-fixtures.sh @@ -114,6 +114,15 @@ if (( ${#fixture_paths[@]} == 0 )); then "xmlenc/aleksey-xmlenc-01/enc-aes256-kt-rsa_oaep_sha1-params.tmpl" "xmlenc/aleksey-xmlenc-01/enc-aes256-kt-rsa_oaep_enc11_sha512_mgf1_sha512.tmpl" ) + # Complete fixed-URI RSA-PSS family from the upstream DSig runner. + for hash in sha1 sha224 sha256 sha384 sha512 sha3_224 sha3_256 sha3_384 sha3_512; do + for extension in xml tmpl; do + fixture_paths+=("xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-$hash.$extension") + if [[ "$hash" != sha1 ]]; then + fixture_paths+=("xmldsig/aleksey-xmldsig-01/enveloped-$hash-rsa-pss-$hash.$extension") + fi + done + done fi for relative_path in "${fixture_paths[@]}"; do diff --git a/src/policy.rs b/src/policy.rs index fb1e3091..d1d92aca 100644 --- a/src/policy.rs +++ b/src/policy.rs @@ -16,6 +16,25 @@ use crate::xmlenc::{ DataEncryptionAlgorithm, KeyTransportAlgorithm, KeyWrapAlgorithm, OaepDigestAlgorithm, }; +/// Permission for the unbounded parameterized RSA-PSS family. +/// Exact permissions continue to use the signature algorithm allowlist. +#[cfg(feature = "xmldsig")] +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] +pub enum RsaPssPermission { + /// No additional family grant; existing allowlists and secure defaults apply. + #[default] + ExactOnly, + /// Permit every supported tuple; capability and key restrictions still apply. + AllSupported, +} + +#[cfg(feature = "xmldsig")] +impl RsaPssPermission { + fn permits(self, algorithm: SignatureAlgorithm) -> bool { + self == Self::AllSupported && matches!(algorithm, SignatureAlgorithm::RsaPss(_)) + } +} + /// Canonical diagnostics for limits represented by [`ResourcePolicy`]. /// /// Validation and every enforcement point use the same names so callers can @@ -974,6 +993,8 @@ pub struct KeyTrustPolicy { pub max_x509_candidate_paths: usize, /// Legacy signature algorithms explicitly permitted for verification. pub allowed_legacy_signature_algorithms: HashSet, + /// Independent legacy-hash permission for parameterized RSA-PSS verification. + pub parameterized_rsa_pss: RsaPssPermission, /// Certificate and CRL signature permissions, independent of XML signatures. /// `None` permits supported classical algorithms but rejects PQ algorithms; /// Explicit permissions select either an exact allowlist (including PSS @@ -1005,6 +1026,7 @@ impl Default for KeyTrustPolicy { max_x509_chain_depth: crate::hard_limits::X509_CHAIN_DEPTH_CEILING, max_x509_candidate_paths: crate::hard_limits::X509_CANDIDATE_PATH_CEILING, allowed_legacy_signature_algorithms: HashSet::new(), + parameterized_rsa_pss: RsaPssPermission::ExactOnly, certificate_signature_algorithms: None, rsa_keys: RsaKeyPolicy::default(), dsa_keys: DsaKeyPolicy::default(), @@ -1106,7 +1128,11 @@ pub enum ManifestProcessing { #[cfg(feature = "xmldsig")] #[derive(Debug, Clone, Default)] pub struct VerificationPolicy { - /// Allowed signature methods; `None` accepts every implemented method subject to + /// Family permission selected by the caller, never derived from document input. + /// Legacy hashes additionally require the independent key-trust permission. + pub parameterized_rsa_pss: RsaPssPermission, + /// Exact signature methods, supplemented by `parameterized_rsa_pss`. + /// `None` accepts every implemented method subject to /// independent gates such as [`KeyTrustPolicy::allowed_legacy_signature_algorithms`]. pub signature_algorithms: Option>, /// Allowed reference digest methods; `None` accepts every implemented method. @@ -1176,16 +1202,19 @@ impl VerificationPolicy { algorithm: algorithm.uri().to_owned(), }); } - if matches!( - algorithm, - SignatureAlgorithm::RsaSha1 - | SignatureAlgorithm::DsaSha1 - | SignatureAlgorithm::HmacSha1 - | SignatureAlgorithm::EcdsaSha1 - ) && !self - .key_trust - .allowed_legacy_signature_algorithms - .contains(&algorithm) + if (algorithm.uses_legacy_pss_hash() + || matches!( + algorithm, + SignatureAlgorithm::RsaSha1 + | SignatureAlgorithm::DsaSha1 + | SignatureAlgorithm::HmacSha1 + | SignatureAlgorithm::EcdsaSha1 + )) + && !self + .key_trust + .allowed_legacy_signature_algorithms + .contains(&algorithm) + && !self.key_trust.parameterized_rsa_pss.permits(algorithm) { return Err(PolicyViolation::Algorithm { operation: "verification", @@ -1196,6 +1225,7 @@ impl VerificationPolicy { .signature_algorithms .as_ref() .is_some_and(|allowed| !allowed.contains(&algorithm)) + && !self.parameterized_rsa_pss.permits(algorithm) { return Err(PolicyViolation::Algorithm { operation: "verification", @@ -1210,7 +1240,10 @@ impl VerificationPolicy { #[cfg(feature = "xmldsig")] #[derive(Debug, Clone, Default)] pub struct SigningPolicy { - /// Allowed signing methods; `None` uses the implemented secure defaults. + /// Explicit parameterized RSA-PSS family permission, including legacy hashes. + pub parameterized_rsa_pss: RsaPssPermission, + /// Exact signing methods, supplemented by `parameterized_rsa_pss`. + /// `None` uses the implemented secure defaults. pub signature_algorithms: Option>, /// Allowed reference digest methods; `None` uses the implemented secure defaults. pub digest_algorithms: Option>, @@ -1249,6 +1282,9 @@ impl SigningPolicy { &self, algorithm: SignatureAlgorithm, ) -> Result<(), PolicyViolation> { + if self.parameterized_rsa_pss.permits(algorithm) { + return Ok(()); + } check_signing_algorithm( self.signature_algorithms.as_ref(), algorithm, diff --git a/src/provider.rs b/src/provider.rs index 3d417018..59355b4b 100644 --- a/src/provider.rs +++ b/src/provider.rs @@ -11,6 +11,8 @@ mod aws_lc; pub mod pkcs11; #[cfg(all(feature = "xmlenc", feature = "legacy-algorithms"))] mod rsa_pkcs1v15; +#[cfg(feature = "xmldsig")] +pub(crate) mod rsa_pss; /// Secret candidate whose recovery validity is retained until content work ends. /// Debug output never exposes key bytes or padding validity. @@ -1280,6 +1282,11 @@ impl CryptoProvider for RustCryptoProvider { // Opaque keys own these primitives and reject unsupported methods // during dispatch; the provider advertises its dispatch surface. ProviderCapability::Sign(algorithm) | ProviderCapability::Verify(algorithm) => { + if let Some(parameters) = algorithm.rsa_pss_parameters() + && parameters.salt_len > i32::MAX as usize + { + return false; + } !matches!( algorithm, crate::xmldsig::SignatureAlgorithm::PostQuantum(_) @@ -1499,7 +1506,7 @@ fn is_supported_x509_signature(algorithm: X509SignatureAlgorithm) -> bool { } #[cfg(feature = "xmldsig")] -mod rustcrypto_x509 { +pub(crate) mod rustcrypto_x509 { use der::Decode as _; use dsa::pkcs8::DecodePublicKey as _; use rsa::{ @@ -1694,11 +1701,14 @@ mod rustcrypto_x509 { .is_some_and(|required| required <= em_len) } - fn compatible_rsa_pss_public_key_from_spki( + pub(crate) fn compatible_rsa_pss_public_key_from_spki( spki_der: &[u8], signature_algorithm: X509SignatureAlgorithm, ) -> Option { - let (_, spki) = x509_parser::x509::SubjectPublicKeyInfo::from_der(spki_der).ok()?; + let (rest, spki) = x509_parser::x509::SubjectPublicKeyInfo::from_der(spki_der).ok()?; + if !rest.is_empty() { + return None; + } match spki.algorithm.algorithm.to_id_string().as_str() { "1.2.840.113549.1.1.1" => RsaPublicKey::from_public_key_der(spki_der).ok(), "1.2.840.113549.1.1.10" => { @@ -1720,7 +1730,7 @@ mod rustcrypto_x509 { } } - fn rsa_pss_key_parameters_allow( + pub(crate) fn rsa_pss_key_parameters_allow( parameters: &x509_parser::asn1_rs::Any<'_>, signature_algorithm: X509SignatureAlgorithm, ) -> bool { @@ -1754,6 +1764,10 @@ mod rustcrypto_x509 { "2.16.840.1.101.3.4.2.1" => Some(DigestAlgorithm::Sha256), "2.16.840.1.101.3.4.2.2" => Some(DigestAlgorithm::Sha384), "2.16.840.1.101.3.4.2.3" => Some(DigestAlgorithm::Sha512), + "2.16.840.1.101.3.4.2.7" => Some(DigestAlgorithm::Sha3_224), + "2.16.840.1.101.3.4.2.8" => Some(DigestAlgorithm::Sha3_256), + "2.16.840.1.101.3.4.2.9" => Some(DigestAlgorithm::Sha3_384), + "2.16.840.1.101.3.4.2.10" => Some(DigestAlgorithm::Sha3_512), _ => None, } } diff --git a/src/provider/aws_lc.rs b/src/provider/aws_lc.rs index 366de60a..607f1e72 100644 --- a/src/provider/aws_lc.rs +++ b/src/provider/aws_lc.rs @@ -172,6 +172,13 @@ impl CryptoProvider for AwsLcFipsProvider { return Ok(false); } let native = verification_algorithm(algorithm, spki, key.ecdsa_encoding())?; + if let Some(parameters) = algorithm.rsa_pss_parameters() { + let encoded = super::rsa_pss::encoded_public_key(spki, parameters) + .ok_or(crate::xmldsig::SignatureVerificationError::InvalidKeyDer)?; + return Ok(signature::UnparsedPublicKey::new(native, encoded) + .verify(data, signature) + .is_ok()); + } let public = signature::ParsedPublicKey::new(native, spki) .map_err(|_| crate::xmldsig::SignatureVerificationError::InvalidKeyDer)?; Ok(public.verify_sig(data, signature).is_ok()) @@ -505,6 +512,12 @@ fn wrapping_key( } fn signing_supported(algorithm: SignatureAlgorithm) -> bool { + if let Some(digest) = native_pss_digest(algorithm) { + return matches!( + digest, + DigestAlgorithm::Sha256 | DigestAlgorithm::Sha384 | DigestAlgorithm::Sha512 + ); + } matches!( algorithm, SignatureAlgorithm::RsaSha256 @@ -519,6 +532,15 @@ fn signing_supported(algorithm: SignatureAlgorithm) -> bool { ) } +fn native_pss_digest(algorithm: SignatureAlgorithm) -> Option { + let parameters = algorithm.rsa_pss_parameters()?; + // AWS-LC's high-level PSS encodings require matching MGF1 and digest-sized salt. + // This is a provider capability restriction, not an XMLDSig policy default. + (parameters.digest == parameters.mgf_digest + && parameters.salt_len == parameters.digest.output_len()) + .then_some(parameters.digest) +} + fn certificate_method(algorithm: super::X509SignatureAlgorithm) -> Option { use super::X509SignatureAlgorithm as X; use DigestAlgorithm as D; @@ -580,11 +602,14 @@ fn verification_algorithm( { use SignatureAlgorithm as A; use signature::*; - let rsa: Option<&'static RsaParameters> = match algorithm { - A::RsaSha1 => Some(&RSA_PKCS1_2048_8192_SHA1_FOR_LEGACY_USE_ONLY), - A::RsaSha256 => Some(&RSA_PKCS1_2048_8192_SHA256), - A::RsaSha384 => Some(&RSA_PKCS1_2048_8192_SHA384), - A::RsaSha512 => Some(&RSA_PKCS1_2048_8192_SHA512), + let rsa: Option<&'static RsaParameters> = match (algorithm, native_pss_digest(algorithm)) { + (_, Some(DigestAlgorithm::Sha256)) => Some(&RSA_PSS_2048_8192_SHA256), + (_, Some(DigestAlgorithm::Sha384)) => Some(&RSA_PSS_2048_8192_SHA384), + (_, Some(DigestAlgorithm::Sha512)) => Some(&RSA_PSS_2048_8192_SHA512), + (A::RsaSha1, _) => Some(&RSA_PKCS1_2048_8192_SHA1_FOR_LEGACY_USE_ONLY), + (A::RsaSha256, _) => Some(&RSA_PKCS1_2048_8192_SHA256), + (A::RsaSha384, _) => Some(&RSA_PKCS1_2048_8192_SHA384), + (A::RsaSha512, _) => Some(&RSA_PKCS1_2048_8192_SHA512), _ => None, }; if let Some(rsa) = rsa { @@ -592,10 +617,14 @@ fn verification_algorithm( use der::Decode as _; let public = rsa::pkcs8::SubjectPublicKeyInfoRef::from_der(spki).map_err(|_| InvalidKeyDer)?; - if public.algorithm.oid != rsa::pkcs1::ALGORITHM_OID { - return Err(InvalidKeyDer); - } - let bytes = public.subject_public_key.as_bytes().ok_or(InvalidKeyDer)?; + let bytes = if let Some(parameters) = algorithm.rsa_pss_parameters() { + super::rsa_pss::encoded_public_key(spki, parameters).ok_or(InvalidKeyDer)? + } else { + if public.algorithm.oid != rsa::pkcs1::ALGORITHM_OID { + return Err(InvalidKeyDer); + } + public.subject_public_key.as_bytes().ok_or(InvalidKeyDer)? + }; let key = rsa::pkcs1::RsaPublicKey::from_der(bytes).map_err(|_| InvalidKeyDer)?; let modulus = key.modulus.as_bytes(); let first = *modulus.first().ok_or(InvalidKeyDer)?; @@ -666,7 +695,7 @@ impl AwsLcSigningKey { uri: algorithm.uri().into(), }); } - let (key, spki) = if matches!(algorithm, A::RsaSha256 | A::RsaSha384 | A::RsaSha512) { + let (key, spki) = if algorithm.is_rsa() { let key = signature::RsaKeyPair::from_pkcs8(der) .map_err(|_| SigningKeyError::InvalidKeyDer)?; let spki: PublicKeyX509Der<'static> = key @@ -775,10 +804,13 @@ impl SigningKey for AwsLcSigningKey { } match &self.key { NativeSigningKey::Rsa(key) => { - let encoding = match algorithm { - SignatureAlgorithm::RsaSha256 => &signature::RSA_PKCS1_SHA256, - SignatureAlgorithm::RsaSha384 => &signature::RSA_PKCS1_SHA384, - SignatureAlgorithm::RsaSha512 => &signature::RSA_PKCS1_SHA512, + let encoding = match (algorithm, native_pss_digest(algorithm)) { + (_, Some(DigestAlgorithm::Sha256)) => &signature::RSA_PSS_SHA256, + (_, Some(DigestAlgorithm::Sha384)) => &signature::RSA_PSS_SHA384, + (_, Some(DigestAlgorithm::Sha512)) => &signature::RSA_PSS_SHA512, + (SignatureAlgorithm::RsaSha256, _) => &signature::RSA_PKCS1_SHA256, + (SignatureAlgorithm::RsaSha384, _) => &signature::RSA_PKCS1_SHA384, + (SignatureAlgorithm::RsaSha512, _) => &signature::RSA_PKCS1_SHA512, _ => { return Err(SigningKeyError::UnsupportedAlgorithm { uri: algorithm.uri().into(), diff --git a/src/provider/pkcs11.rs b/src/provider/pkcs11.rs index 227354f9..ec1d944f 100644 --- a/src/provider/pkcs11.rs +++ b/src/provider/pkcs11.rs @@ -15,7 +15,7 @@ use cryptoki::{ mechanism::{ Mechanism, MechanismInfo, MechanismType, elliptic_curve::{EcKdf, Ecdh1DeriveParams}, - rsa::{PkcsMgfType, PkcsOaepParams, PkcsOaepSource}, + rsa::{PkcsMgfType, PkcsOaepParams, PkcsOaepSource, PkcsPssParams}, }, object::{Attribute, AttributeType, KeyType, ObjectClass, ObjectHandle}, session::{Session, UserType}, @@ -356,6 +356,32 @@ fn require_usage( } fn signature_mechanism(algorithm: SignatureAlgorithm) -> Option> { + if let Some(parameters) = algorithm.rsa_pss_parameters() { + if parameters.salt_len > i32::MAX as usize { + return None; + } + let mgf = match parameters.mgf_digest { + DigestAlgorithm::Sha1 => PkcsMgfType::MGF1_SHA1, + DigestAlgorithm::Sha224 => PkcsMgfType::MGF1_SHA224, + DigestAlgorithm::Sha256 => PkcsMgfType::MGF1_SHA256, + DigestAlgorithm::Sha384 => PkcsMgfType::MGF1_SHA384, + DigestAlgorithm::Sha512 => PkcsMgfType::MGF1_SHA512, + _ => return None, + }; + let hash_alg = digest_mechanism(parameters.digest)?.mechanism_type(); + let params = PkcsPssParams { + hash_alg, + mgf, + s_len: parameters.salt_len.try_into().ok()?, + }; + return match parameters.digest { + DigestAlgorithm::Sha1 => Some(Mechanism::Sha1RsaPkcsPss(params)), + DigestAlgorithm::Sha256 => Some(Mechanism::Sha256RsaPkcsPss(params)), + DigestAlgorithm::Sha384 => Some(Mechanism::Sha384RsaPkcsPss(params)), + DigestAlgorithm::Sha512 => Some(Mechanism::Sha512RsaPkcsPss(params)), + _ => None, + }; + } match algorithm { SignatureAlgorithm::RsaSha1 => Some(Mechanism::Sha1RsaPkcs), SignatureAlgorithm::RsaSha224 => Some(Mechanism::Sha224RsaPkcs), @@ -410,6 +436,18 @@ pub struct Pkcs11RsaKey { spki: Vec, } +impl Pkcs11RsaKey { + fn parameters_fit(&self, algorithm: SignatureAlgorithm) -> bool { + let Some(parameters) = algorithm.rsa_pss_parameters() else { + return true; + }; + let Some(first) = self.modulus.first() else { + return false; + }; + parameters.fits_modulus_bits(self.modulus.len() * 8 - first.leading_zeros() as usize) + } +} + impl SigningKey for Pkcs11RsaKey { fn provider_name(&self) -> Option<&'static str> { Some("pkcs11") @@ -426,6 +464,9 @@ impl SigningKey for Pkcs11RsaKey { self.token.check_binding(provider)?; let capability = ProviderCapability::Sign(algorithm); provider.require_capability(capability)?; + if !self.parameters_fit(algorithm) { + return Err(SigningKeyError::SigningFailed); + } let mechanism = signature_mechanism(algorithm).ok_or_else(|| unsupported(capability))?; let session = self.token.session()?; require_usage(&session, self.object, AttributeType::Sign)?; @@ -461,6 +502,9 @@ impl VerifyingKey for Pkcs11RsaKey { data: &[u8], signature: &[u8], ) -> Result { + if !self.parameters_fit(algorithm) { + return Ok(false); + } let mechanism = signature_mechanism(algorithm) .ok_or_else(|| unsupported(ProviderCapability::Verify(algorithm)))?; let session = self.token.session()?; diff --git a/src/provider/rsa_pss.rs b/src/provider/rsa_pss.rs new file mode 100644 index 00000000..89e85dc9 --- /dev/null +++ b/src/provider/rsa_pss.rs @@ -0,0 +1,291 @@ +//! Local parameterized adaptation of sad-rsa 0.10.2 PSS and MGF1. +//! +//! Derived from src/pss.rs and src/algorithms/{pss,mgf}.rs, MIT OR Apache-2.0. +//! RSA arithmetic, blinding and fault checks remain in sad-rsa. Only the +//! padding module is adapted here, as with the fixed-width recovery patch. + +use crypto_bigint::BoxedUint; +use der::{Decode as _, Reader as _, Tagged as _}; +use rsa::pkcs1::DecodeRsaPublicKey as _; +use rsa::{RsaPrivateKey, RsaPublicKey, traits::PublicKeyParts}; +use sha2::Digest as _; +use subtle::ConstantTimeEq as _; +use zeroize::Zeroizing; + +use super::{CryptoProvider, ProviderRng}; +use crate::xmldsig::{DigestAlgorithm, RsaPssParameters, SigningKeyError}; + +/// Hash borrowed parts directly into stack storage; MGF1 creates no per-block Vec. +fn hash(algorithm: DigestAlgorithm, parts: &[&[u8]], output: &mut [u8; 64]) { + macro_rules! compute { + ($digest:ty) => {{ + let mut digest = <$digest>::new(); + for part in parts { + digest.update(part); + } + let result = digest.finalize(); + output[..result.len()].copy_from_slice(&result); + }}; + } + match algorithm { + DigestAlgorithm::Sha1 => compute!(sha1::Sha1), + DigestAlgorithm::Sha224 => compute!(sha2::Sha224), + DigestAlgorithm::Sha256 => compute!(sha2::Sha256), + DigestAlgorithm::Sha384 => compute!(sha2::Sha384), + DigestAlgorithm::Sha512 => compute!(sha2::Sha512), + DigestAlgorithm::Sha3_224 => compute!(sha3::Sha3_224), + DigestAlgorithm::Sha3_256 => compute!(sha3::Sha3_256), + DigestAlgorithm::Sha3_384 => compute!(sha3::Sha3_384), + DigestAlgorithm::Sha3_512 => compute!(sha3::Sha3_512), + #[cfg(feature = "legacy-algorithms")] + DigestAlgorithm::Md5 => compute!(md5::Md5), + #[cfg(feature = "legacy-algorithms")] + DigestAlgorithm::Ripemd160 => compute!(ripemd::Ripemd160), + } +} + +fn mask(out: &mut [u8], algorithm: DigestAlgorithm, seed: &[u8]) { + // RFC 8017 appendix B.2.1: Hash(seed || I2OSP(counter, 4)). + // https://www.rfc-editor.org/rfc/rfc8017.html#appendix-B.2.1 + // RSA's absolute modulus ceiling bounds the counter far below 2^32. + let mut block = [0u8; 64]; + for (counter, chunk) in out.chunks_mut(algorithm.output_len()).enumerate() { + hash( + algorithm, + &[seed, &(counter as u32).to_be_bytes()], + &mut block, + ); + for (byte, mask) in chunk.iter_mut().zip(&block) { + *byte ^= mask; + } + } +} + +fn valid_key(parameters: RsaPssParameters, key: &impl PublicKeyParts) -> bool { + let bits = key.n().bits() as usize; + bits <= crate::hard_limits::RSA_MODULUS_BIT_CEILING && parameters.fits_modulus_bits(bits) +} + +pub(crate) fn public_key(spki: &[u8], parameters: RsaPssParameters) -> Option { + // RFC 4055 section 3.3: a PSS SPKI restricts hashes/trailer and sets a + // minimum salt length; absent parameters permit any supported PSS tuple. + // https://www.rfc-editor.org/rfc/rfc4055.html#section-3.3 + RsaPublicKey::from_pkcs1_der(encoded_public_key(spki, parameters)?).ok() +} + +/// Borrow the RSA bit string after checking its algorithm restrictions. Native +/// providers share this preflight without allocating software RSA bigints. +pub(crate) fn encoded_public_key(spki: &[u8], parameters: RsaPssParameters) -> Option<&[u8]> { + use x509_parser::prelude::FromDer as _; + let public = rsa::pkcs8::SubjectPublicKeyInfoRef::from_der(spki).ok()?; + let (_, parsed) = x509_parser::x509::SubjectPublicKeyInfo::from_der(spki).ok()?; + match parsed.algorithm.algorithm.as_bytes() { + [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01] => { + if public + .algorithm + .parameters + .is_some_and(|value| !value.is_null()) + { + return None; + } + } + [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a] => { + if public + .algorithm + .parameters + .is_some_and(|value| !valid_parameter_encoding(value)) + { + return None; + } + if parsed.algorithm.parameters.as_ref().is_some_and(|value| { + !super::rustcrypto_x509::rsa_pss_key_parameters_allow( + value, + super::X509SignatureAlgorithm::RsaPss { + digest: parameters.digest, + mgf_digest: parameters.mgf_digest, + salt_len: parameters.salt_len, + }, + ) + }) { + return None; + } + } + _ => return None, + } + public.subject_public_key.as_bytes() +} + +fn valid_parameter_encoding(parameters: der::asn1::AnyRef<'_>) -> bool { + // RFC 8017 appendix A.2.3 defines an ordered, explicitly tagged sequence. + // x509-parser's value decoder does not check its unconsumed suffix, so + // validate the complete borrowed DER before interpreting key restrictions. + // https://www.rfc-editor.org/rfc/rfc8017.html#appendix-A.2.3 + parameters + .sequence(|reader| -> der::Result<()> { + let mut previous = None; + while !reader.is_finished() { + let field: der::asn1::AnyRef<'_> = reader.decode()?; + let der::Tag::ContextSpecific { + constructed: true, + number, + } = field.tag() + else { + return Err(field.tag().value_error().into()); + }; + if number.0 > 3 || previous.is_some_and(|last| number.0 <= last) { + return Err(field.tag().value_error().into()); + } + previous = Some(number.0); + match number.0 { + 0 | 1 => { + let algorithm = + rsa::pkcs8::AlgorithmIdentifierRef::from_der(field.value())?; + let hash = if number.0 == 1 { + algorithm + .parameters + .ok_or(field.tag().value_error())? + .decode_as::>()? + } else { + algorithm + }; + if hash.parameters.is_some_and(|value| !value.is_null()) { + return Err(field.tag().value_error().into()); + } + } + _ => { + u32::from_der(field.value())?; + } + } + } + Ok(()) + }) + .is_ok() +} + +pub(crate) fn sign( + provider: &dyn CryptoProvider, + key: &RsaPrivateKey, + parameters: RsaPssParameters, + message: &[u8], +) -> Result, SigningKeyError> { + if !valid_key(parameters, key) { + return Err(SigningKeyError::SigningFailed); + } + let bits = key.n().bits() as usize - 1; + let em_len = bits.div_ceil(8); + let h_len = parameters.digest.output_len(); + let mut m_hash = [0u8; 64]; + hash(parameters.digest, &[message], &mut m_hash); + let mut encoded = Zeroizing::new(vec![0u8; em_len]); + let (db, tail) = encoded.split_at_mut(em_len - h_len - 1); + let h = &mut tail[..h_len]; + let separator = db.len() - parameters.salt_len - 1; + db[separator] = 1; + provider.fill_random(&mut db[separator + 1..])?; + let mut h_hash = [0u8; 64]; + hash( + parameters.digest, + &[&[0; 8], &m_hash[..h_len], &db[separator + 1..]], + &mut h_hash, + ); + h.copy_from_slice(&h_hash[..h_len]); + mask(db, parameters.mgf_digest, h); + db[0] &= 0xff >> (em_len * 8 - bits); + encoded[em_len - 1] = 0xbc; + let value = BoxedUint::from_be_slice(&encoded, key.n_bits_precision()) + .map_err(|_| SigningKeyError::SigningFailed)?; + let value = rsa::hazmat::rsa_decrypt_and_check(key, Some(&mut ProviderRng(provider)), &value) + .map_err(|_| SigningKeyError::SigningFailed)?; + let bytes = value.to_be_bytes(); + Ok(bytes[bytes.len() - key.size()..].to_vec()) +} + +pub(crate) fn verify( + key: &RsaPublicKey, + parameters: RsaPssParameters, + message: &[u8], + signature: &[u8], +) -> bool { + if signature.len() != key.size() || !valid_key(parameters, key) { + return false; + } + let Ok(value) = BoxedUint::from_be_slice(signature, key.n_bits_precision()) else { + return false; + }; + // RSAVP1 rejects representatives outside [0, n); raw modular arithmetic + // alone would accept the alternate encoding s+n of a valid signature. + // RFC 8017 section 5.2.2: https://www.rfc-editor.org/rfc/rfc8017.html#section-5.2.2 + if value >= *key.n().as_ref() { + return false; + } + let Ok(value) = rsa::hazmat::rsa_encrypt(key, &value) else { + return false; + }; + let mut encoded = value.to_be_bytes(); + let bits = key.n().bits() as usize - 1; + let em_len = bits.div_ceil(8); + let leading = encoded.len() - em_len; + // RFC 8017 section 8.1.2 step 2 requires an emLen-octet representative. + // Do not silently truncate a nonzero octet for moduli congruent to 1 mod 8. + // https://www.rfc-editor.org/rfc/rfc8017.html#section-8.1.2 + if encoded[..leading].iter().any(|byte| *byte != 0) { + return false; + } + let encoded = &mut encoded[leading..]; + if encoded[em_len - 1] != 0xbc { + return false; + } + let h_len = parameters.digest.output_len(); + let (db, tail) = encoded.split_at_mut(em_len - h_len - 1); + let h = &tail[..h_len]; + let high_bits = em_len * 8 - bits; + if db[0] & !(0xff >> high_bits) != 0 { + return false; + } + mask(db, parameters.mgf_digest, h); + db[0] &= 0xff >> high_bits; + let separator = db.len() - parameters.salt_len - 1; + let mut valid = db[separator].ct_eq(&1); + for byte in &db[..separator] { + valid &= byte.ct_eq(&0); + } + let mut m_hash = [0u8; 64]; + hash(parameters.digest, &[message], &mut m_hash); + let mut expected = [0u8; 64]; + hash( + parameters.digest, + &[&[0; 8], &m_hash[..h_len], &db[separator + 1..]], + &mut expected, + ); + bool::from(valid & expected[..h_len].ct_eq(h)) +} + +#[cfg(test)] +mod tests { + use super::*; + use rand_chacha::{ChaCha8Rng, rand_core::SeedableRng as _}; + + #[test] + fn signs_non_byte_aligned_modulus_with_dependency_verification() { + // Exercise our signing encoder at modBits == 1 mod 8 without relying + // on sad-rsa's unrelated odd-width private DER exporter. + let private = RsaPrivateKey::new(&mut ChaCha8Rng::seed_from_u64(2049), 2049) + .expect("deterministic odd-width RSA key"); + let signature = sign( + &super::super::RustCryptoProvider, + &private, + RsaPssParameters::DEFAULT, + b"odd modulus", + ) + .expect("odd-width PSS signing"); + let public = RsaPublicKey::from(&private); + assert_eq!(signature.len(), 257); + public + .verify( + rsa::Pss::::new(), + &sha2::Sha256::digest(b"odd modulus"), + &signature, + ) + .expect("independent PSS verifier accepts odd-width signature"); + } +} diff --git a/src/xmldsig/builder.rs b/src/xmldsig/builder.rs index 77afdce9..ee917d64 100644 --- a/src/xmldsig/builder.rs +++ b/src/xmldsig/builder.rs @@ -66,6 +66,9 @@ pub enum SignatureBuilderError { /// The selected signature method cannot carry a cryptographic context. #[error("signature context is not applicable to algorithm: {0}")] SignatureContextNotApplicable(&'static str), + /// RSA-PSS salt length cannot be represented by the XML xs:int contract. + #[error("RSA-PSS salt length exceeds xs:int")] + InvalidRsaPssParameters, /// The XML writer failed. #[error("XML serialization error: {0}")] Serialization(#[from] std::io::Error), @@ -269,7 +272,37 @@ impl SignatureBuilder { "CanonicalizationMethod", self.c14n_method.uri(), )?; - if self.signature_context.as_bytes().is_empty() { + if let SignatureAlgorithm::RsaPss(parameters) = self.sign_method { + let method_name = qualified_name(prefix, "SignatureMethod"); + writer.start(&method_name, [("Algorithm", self.sign_method.uri())])?; + // RFC 9231 section 2.3.9 defines the parameter order and namespaces. + // https://www.rfc-editor.org/rfc/rfc9231.html#section-2.3.9 + writer.start("RSAPSSParams", [("xmlns", super::parse::RSA_PSS_NS)])?; + writer.empty( + "DigestMethod", + [ + ("xmlns", XMLDSIG_NS), + ("Algorithm", parameters.digest.uri()), + ], + )?; + writer.start( + "MaskGenerationFunction", + [("Algorithm", "http://www.w3.org/2007/05/xmldsig-more#MGF1")], + )?; + writer.empty( + "DigestMethod", + [ + ("xmlns", XMLDSIG_NS), + ("Algorithm", parameters.mgf_digest.uri()), + ], + )?; + writer.end("MaskGenerationFunction")?; + writer.start("SaltLength", std::iter::empty::<(&str, &str)>())?; + writer.text(¶meters.salt_len.to_string())?; + writer.end("SaltLength")?; + writer.end("RSAPSSParams")?; + writer.end(&method_name)?; + } else if self.signature_context.as_bytes().is_empty() { write_algorithm( &mut writer, prefix, @@ -412,6 +445,11 @@ impl SignatureBuilder { policy: &SigningPolicy, xpath_signature_budget: &mut XPathSignatureParseBudget, ) -> Result<(), SignatureBuilderError> { + if let Some(parameters) = self.sign_method.rsa_pss_parameters() + && parameters.salt_len > i32::MAX as usize + { + return Err(SignatureBuilderError::InvalidRsaPssParameters); + } if !self.signature_context.as_bytes().is_empty() && self.sign_method.context_element().is_none() { diff --git a/src/xmldsig/keys.rs b/src/xmldsig/keys.rs index c049f895..8ec16899 100644 --- a/src/xmldsig/keys.rs +++ b/src/xmldsig/keys.rs @@ -251,7 +251,17 @@ impl VerifyingKey for VerificationKey { | SignatureAlgorithm::RsaSha224 | SignatureAlgorithm::RsaSha256 | SignatureAlgorithm::RsaSha384 - | SignatureAlgorithm::RsaSha512 => validate_rsa_signature_spki_with_minimum( + | SignatureAlgorithm::RsaSha512 + | SignatureAlgorithm::RsaPssSha1 + | SignatureAlgorithm::RsaPssSha224 + | SignatureAlgorithm::RsaPssSha256 + | SignatureAlgorithm::RsaPssSha384 + | SignatureAlgorithm::RsaPssSha512 + | SignatureAlgorithm::RsaPssSha3_224 + | SignatureAlgorithm::RsaPssSha3_256 + | SignatureAlgorithm::RsaPssSha3_384 + | SignatureAlgorithm::RsaPssSha3_512 + | SignatureAlgorithm::RsaPss(_) => validate_rsa_signature_spki_with_minimum( self.algorithm, &self.public_key_bytes, policy.key_trust.rsa_keys.minimum_modulus_bits, @@ -364,7 +374,17 @@ impl VerifyingKey for VerificationKey { | SignatureAlgorithm::RsaSha224 | SignatureAlgorithm::RsaSha256 | SignatureAlgorithm::RsaSha384 - | SignatureAlgorithm::RsaSha512 => verify_rsa_signature_spki_primitive( + | SignatureAlgorithm::RsaSha512 + | SignatureAlgorithm::RsaPssSha1 + | SignatureAlgorithm::RsaPssSha224 + | SignatureAlgorithm::RsaPssSha256 + | SignatureAlgorithm::RsaPssSha384 + | SignatureAlgorithm::RsaPssSha512 + | SignatureAlgorithm::RsaPssSha3_224 + | SignatureAlgorithm::RsaPssSha3_256 + | SignatureAlgorithm::RsaPssSha3_384 + | SignatureAlgorithm::RsaPssSha3_512 + | SignatureAlgorithm::RsaPss(_) => verify_rsa_signature_spki_primitive( algorithm, &self.public_key_bytes, signed_data, @@ -1669,6 +1689,16 @@ fn validate_spki_algorithm( public_key_bytes: &[u8], algorithm: SignatureAlgorithm, ) -> Result<(), KeyResolutionError> { + if algorithm.rsa_pss_parameters().is_some() { + // RFC 4055 section 1.2 requires id-RSASSA-PSS for PSS-only keys. + // Share the borrowed RSA validator so resolver and provider enforce the + // same parameter restrictions; the generic parser recognizes only rsaEncryption. + // https://www.rfc-editor.org/rfc/rfc4055.html#section-1.2 + // Eight bits is structural validation only; the selected policy's + // strength minimum is enforced on the resolved key before execution. + return validate_rsa_signature_spki_with_minimum(algorithm, public_key_bytes, 8) + .map_err(|_| KeyResolutionError::InvalidPublicKey); + } if algorithm.eddsa_signature_len().is_some() || matches!(algorithm, SignatureAlgorithm::PostQuantum(_)) { diff --git a/src/xmldsig/mod.rs b/src/xmldsig/mod.rs index 27dc0a41..743bd167 100644 --- a/src/xmldsig/mod.rs +++ b/src/xmldsig/mod.rs @@ -84,8 +84,9 @@ pub use keys::{ pub use modern::EdDsaSigningKey; pub use parse::{ KeyInfo, KeyInfoSource, KeyValueInfo, ParseError, Reference, RetrievalMethodTransforms, - SignatureAlgorithm, SignatureContext, SignedInfo, X509DataInfo, find_signature_node, - parse_key_info, parse_reference, parse_signed_info, x509_certificate_matches_selectors, + RsaPssParameters, SignatureAlgorithm, SignatureContext, SignedInfo, X509DataInfo, + find_signature_node, parse_key_info, parse_reference, parse_signed_info, + x509_certificate_matches_selectors, }; pub use sign::{ ComputedReferenceDigest, DerEncodedKeyValueInfoWriter, DsaSigningKey, EcdsaP256SigningKey, diff --git a/src/xmldsig/parse.rs b/src/xmldsig/parse.rs index 6ae0bf69..4fa58ef7 100644 --- a/src/xmldsig/parse.rs +++ b/src/xmldsig/parse.rs @@ -100,6 +100,45 @@ const MAX_X509_SERIAL_NUMBER_BYTES: usize = 20; const MAX_X509_DATA_ENTRY_COUNT: usize = 64; pub(crate) const MAX_X509_DATA_TOTAL_BINARY_LEN: usize = 1_048_576; +/// Parameters of RFC 9231 section 2.3.9 RSA-PSS, not algorithm permissions. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct RsaPssParameters { + /// Hash applied to the message and PSS encoding. + pub digest: DigestAlgorithm, + /// Independent hash underlying MGF1. + pub mgf_digest: DigestAlgorithm, + /// Exact salt width in octets; zero is permitted by RFC 8017. + pub salt_len: usize, +} + +impl Default for RsaPssParameters { + fn default() -> Self { + Self::DEFAULT + } +} + +impl RsaPssParameters { + /// XML defaults, which intentionally differ from ASN.1 PSS defaults. + pub const DEFAULT: Self = Self { + digest: DigestAlgorithm::Sha256, + mgf_digest: DigestAlgorithm::Sha256, + salt_len: 32, + }; + + pub(crate) fn fits_modulus_bits(self, bits: usize) -> bool { + // RFC 8017 section 9.1.1 step 3, before allocation or RNG. + // https://www.rfc-editor.org/rfc/rfc8017.html#section-9.1.1 + if bits < 2 || self.salt_len > i32::MAX as usize { + return false; + } + let em_len = (bits - 1).div_ceil(8); + let hash_len = self.digest.output_len(); + em_len >= hash_len + 2 && self.salt_len <= em_len - hash_len - 2 + } +} + +pub(crate) const RSA_PSS_NS: &str = "http://www.w3.org/2007/05/xmldsig-more#"; + /// Signature algorithms supported for signing and verification. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[non_exhaustive] @@ -143,6 +182,26 @@ pub enum SignatureAlgorithm { RsaSha384, /// RSA with SHA-512. RsaSha512, + /// RSA-PSS with SHA1, matching MGF1 and digest-sized salt. + RsaPssSha1, + /// RSA-PSS with SHA224, matching MGF1 and digest-sized salt. + RsaPssSha224, + /// RSA-PSS with SHA256, matching MGF1 and digest-sized salt. + RsaPssSha256, + /// RSA-PSS with SHA384, matching MGF1 and digest-sized salt. + RsaPssSha384, + /// RSA-PSS with SHA512, matching MGF1 and digest-sized salt. + RsaPssSha512, + /// RSA-PSS with SHA3-224, matching MGF1 and digest-sized salt. + RsaPssSha3_224, + /// RSA-PSS with SHA3-256, matching MGF1 and digest-sized salt. + RsaPssSha3_256, + /// RSA-PSS with SHA3-384, matching MGF1 and digest-sized salt. + RsaPssSha3_384, + /// RSA-PSS with SHA3-512, matching MGF1 and digest-sized salt. + RsaPssSha3_512, + /// Parameterized RSA-PSS under RFC 9231 section 2.3.9. + RsaPss(RsaPssParameters), /// ECDSA with SHA-1; the key selects the elliptic curve. EcdsaSha1, /// ECDSA with SHA-224; the key selects the elliptic curve. @@ -176,9 +235,44 @@ pub enum SignatureAlgorithm { } impl SignatureAlgorithm { + /// Effective PSS parameters for fixed and parameterized method identifiers. + pub fn rsa_pss_parameters(self) -> Option { + let digest = match self { + Self::RsaPss(parameters) => return Some(parameters), + Self::RsaPssSha1 => DigestAlgorithm::Sha1, + Self::RsaPssSha224 => DigestAlgorithm::Sha224, + Self::RsaPssSha256 => DigestAlgorithm::Sha256, + Self::RsaPssSha384 => DigestAlgorithm::Sha384, + Self::RsaPssSha512 => DigestAlgorithm::Sha512, + Self::RsaPssSha3_224 => DigestAlgorithm::Sha3_224, + Self::RsaPssSha3_256 => DigestAlgorithm::Sha3_256, + Self::RsaPssSha3_384 => DigestAlgorithm::Sha3_384, + Self::RsaPssSha3_512 => DigestAlgorithm::Sha3_512, + _ => return None, + }; + Some(RsaPssParameters { + digest, + mgf_digest: digest, + salt_len: digest.output_len(), + }) + } + + /// Whether either PSS hash needs explicit historical-algorithm permission. + pub fn uses_legacy_pss_hash(self) -> bool { + self.rsa_pss_parameters().is_some_and(|parameters| { + [parameters.digest, parameters.mgf_digest] + .into_iter() + .any(|digest| match digest { + DigestAlgorithm::Sha1 => true, + #[cfg(feature = "legacy-algorithms")] + DigestAlgorithm::Md5 | DigestAlgorithm::Ripemd160 => true, + _ => false, + }) + }) + } /// Every signature algorithm recognized by this release. pub const ALL: [Self; - 35 + if cfg!(feature = "legacy-algorithms") { + 45 + if cfg!(feature = "legacy-algorithms") { 5 } else { 0 @@ -205,6 +299,16 @@ impl SignatureAlgorithm { Self::RsaSha256, Self::RsaSha384, Self::RsaSha512, + Self::RsaPssSha1, + Self::RsaPssSha224, + Self::RsaPssSha256, + Self::RsaPssSha384, + Self::RsaPssSha512, + Self::RsaPssSha3_224, + Self::RsaPssSha3_256, + Self::RsaPssSha3_384, + Self::RsaPssSha3_512, + Self::RsaPss(RsaPssParameters::DEFAULT), Self::EcdsaSha1, Self::EcdsaSha224, Self::EcdsaSha256, @@ -305,6 +409,26 @@ impl SignatureAlgorithm { #[must_use] pub fn from_uri(uri: &str) -> Option { match uri { + "http://www.w3.org/2007/05/xmldsig-more#sha1-rsa-MGF1" => Some(Self::RsaPssSha1), + "http://www.w3.org/2007/05/xmldsig-more#sha224-rsa-MGF1" => Some(Self::RsaPssSha224), + "http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1" => Some(Self::RsaPssSha256), + "http://www.w3.org/2007/05/xmldsig-more#sha384-rsa-MGF1" => Some(Self::RsaPssSha384), + "http://www.w3.org/2007/05/xmldsig-more#sha512-rsa-MGF1" => Some(Self::RsaPssSha512), + "http://www.w3.org/2007/05/xmldsig-more#sha3-224-rsa-MGF1" => { + Some(Self::RsaPssSha3_224) + } + "http://www.w3.org/2007/05/xmldsig-more#sha3-256-rsa-MGF1" => { + Some(Self::RsaPssSha3_256) + } + "http://www.w3.org/2007/05/xmldsig-more#sha3-384-rsa-MGF1" => { + Some(Self::RsaPssSha3_384) + } + "http://www.w3.org/2007/05/xmldsig-more#sha3-512-rsa-MGF1" => { + Some(Self::RsaPssSha3_512) + } + "http://www.w3.org/2007/05/xmldsig-more#rsa-pss" => { + Some(Self::RsaPss(RsaPssParameters::DEFAULT)) + } #[cfg(feature = "legacy-algorithms")] "http://www.w3.org/2001/04/xmldsig-more#rsa-md5" => Some(Self::RsaMd5), #[cfg(feature = "legacy-algorithms")] @@ -358,6 +482,16 @@ impl SignatureAlgorithm { #[must_use] pub fn uri(self) -> &'static str { match self { + Self::RsaPssSha1 => "http://www.w3.org/2007/05/xmldsig-more#sha1-rsa-MGF1", + Self::RsaPssSha224 => "http://www.w3.org/2007/05/xmldsig-more#sha224-rsa-MGF1", + Self::RsaPssSha256 => "http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1", + Self::RsaPssSha384 => "http://www.w3.org/2007/05/xmldsig-more#sha384-rsa-MGF1", + Self::RsaPssSha512 => "http://www.w3.org/2007/05/xmldsig-more#sha512-rsa-MGF1", + Self::RsaPssSha3_224 => "http://www.w3.org/2007/05/xmldsig-more#sha3-224-rsa-MGF1", + Self::RsaPssSha3_256 => "http://www.w3.org/2007/05/xmldsig-more#sha3-256-rsa-MGF1", + Self::RsaPssSha3_384 => "http://www.w3.org/2007/05/xmldsig-more#sha3-384-rsa-MGF1", + Self::RsaPssSha3_512 => "http://www.w3.org/2007/05/xmldsig-more#sha3-512-rsa-MGF1", + Self::RsaPss(_) => "http://www.w3.org/2007/05/xmldsig-more#rsa-pss", #[cfg(feature = "legacy-algorithms")] Self::RsaMd5 => "http://www.w3.org/2001/04/xmldsig-more#rsa-md5", #[cfg(feature = "legacy-algorithms")] @@ -401,7 +535,7 @@ impl SignatureAlgorithm { /// Whether this algorithm is allowed for signing (not just verification). #[must_use] pub fn signing_allowed(self) -> bool { - if self.requires_explicit_permission() { + if self.requires_explicit_permission() || self.uses_legacy_pss_hash() { return false; } !matches!( @@ -426,6 +560,16 @@ impl SignatureAlgorithm { /// Whether this method uses an RSA key and PKCS#1 signature encoding. pub const fn is_rsa(self) -> bool { match self { + Self::RsaPssSha1 => true, + Self::RsaPssSha224 => true, + Self::RsaPssSha256 => true, + Self::RsaPssSha384 => true, + Self::RsaPssSha512 => true, + Self::RsaPssSha3_224 => true, + Self::RsaPssSha3_256 => true, + Self::RsaPssSha3_384 => true, + Self::RsaPssSha3_512 => true, + Self::RsaPss(_) => true, #[cfg(feature = "legacy-algorithms")] Self::RsaMd5 | Self::RsaRipemd160 => true, Self::RsaSha1 @@ -796,17 +940,24 @@ pub(crate) fn parse_signed_info_with_xpath_budget( #[derive(Clone, Copy)] struct ByteAlignedHmacOutputLength(usize); -pub(crate) fn parse_signature_method( +/// Parse a complete SignatureMethod, including its bounded algorithm parameters. +/// This is also usable for unsigned templates whose DigestValue placeholders +/// are not yet valid signature input; callers still apply operation policy. +pub fn parse_signature_method( node: Node<'_, '_>, resources: &crate::policy::ResourcePolicy, ) -> Result<(SignatureAlgorithm, Option, SignatureContext), ParseError> { verify_ds_element(node, "SignatureMethod")?; let uri = required_algorithm_attr(node, "SignatureMethod")?; - let algorithm = + let mut algorithm = SignatureAlgorithm::from_uri(uri).ok_or_else(|| ParseError::UnsupportedAlgorithm { uri: uri.to_string(), })?; ensure_no_non_whitespace_text(node, "SignatureMethod")?; + if matches!(algorithm, SignatureAlgorithm::RsaPss(_)) { + algorithm = SignatureAlgorithm::RsaPss(parse_rsa_pss_parameters(node)?); + return Ok((algorithm, None, SignatureContext::default())); + } let (hmac, context) = if algorithm.context_element().is_some() { (None, parse_signature_context(node, algorithm, resources)?) } else { @@ -818,6 +969,152 @@ pub(crate) fn parse_signature_method( Ok((algorithm, hmac, context)) } +fn parse_rsa_pss_parameters(node: Node<'_, '_>) -> Result { + // RFC 9231 section 2.3.9 defines an ordered sequence of optional + // DigestMethod, MaskGenerationFunction, SaltLength and TrailerField. + // https://www.rfc-editor.org/rfc/rfc9231.html#section-2.3.9 + let mut parameters = RsaPssParameters::DEFAULT; + let mut children = element_children(node); + let Some(params) = children.next() else { + return Ok(parameters); + }; + if !params.has_tag_name((RSA_PSS_NS, "RSAPSSParams")) || children.next().is_some() { + return Err(ParseError::InvalidStructure( + "invalid RSAPSSParams element".into(), + )); + } + ensure_no_non_whitespace_text(params, "RSAPSSParams")?; + let mut last = 0; + let mut salt_seen = false; + let mut mgf_seen = false; + for child in element_children(params) { + let rank = match (child.tag_name().namespace(), child.tag_name().name()) { + (Some(XMLDSIG_NS), "DigestMethod") => 1, + (Some(RSA_PSS_NS), "MaskGenerationFunction") => 2, + (Some(RSA_PSS_NS), "SaltLength") => 3, + (Some(RSA_PSS_NS), "TrailerField") => 4, + _ => { + return Err(ParseError::InvalidStructure( + "unknown RSAPSSParams child".into(), + )); + } + }; + if rank <= last { + return Err(ParseError::InvalidStructure( + "duplicate or unordered RSAPSSParams child".into(), + )); + } + last = rank; + match rank { + 1 => parameters.digest = parse_pss_digest(child)?, + 2 => { + ensure_no_non_whitespace_text(child, "MaskGenerationFunction")?; + if child + .attribute("Algorithm") + .is_some_and(|uri| uri != "http://www.w3.org/2007/05/xmldsig-more#MGF1") + { + return Err(ParseError::InvalidStructure( + "unsupported PSS mask generation function".into(), + )); + } + let mut digests = element_children(child); + parameters.mgf_digest = match digests.next() { + Some(digest) => parse_pss_digest(digest)?, + // RFC 9231 section 2.3.9 uses SHA-256 when this explicit + // hash-bearing parameter omits its DigestMethod. An absent + // MGF parameter instead inherits the message hash below. + None => DigestAlgorithm::Sha256, + }; + if digests.next().is_some() { + return Err(ParseError::InvalidStructure( + "duplicate MGF1 DigestMethod".into(), + )); + } + mgf_seen = true; + } + 3 => { + parameters.salt_len = parse_pss_integer(child)?; + salt_seen = true; + } + 4 => { + if parse_pss_integer(child)? != 1 { + // RFC 8017 appendix A.2.3 supports only trailerFieldBC. + // https://www.rfc-editor.org/rfc/rfc8017.html#appendix-A.2.3 + return Err(ParseError::InvalidStructure( + "PSS TrailerField must be 1".into(), + )); + } + } + _ => unreachable!(), + } + } + if !mgf_seen { + parameters.mgf_digest = parameters.digest; + } + if !salt_seen { + parameters.salt_len = parameters.digest.output_len(); + } + Ok(parameters) +} + +fn parse_pss_digest(node: Node<'_, '_>) -> Result { + verify_ds_element(node, "DigestMethod")?; + ensure_no_element_children(node, "DigestMethod")?; + ensure_no_non_whitespace_text(node, "DigestMethod")?; + let uri = required_algorithm_attr(node, "DigestMethod")?; + DigestAlgorithm::from_uri(uri) + .ok_or_else(|| ParseError::UnsupportedAlgorithm { uri: uri.into() }) +} + +fn parse_pss_integer(node: Node<'_, '_>) -> Result { + ensure_no_element_children(node, "PSS integer")?; + // xs:int lexical space permits XML whitespace and either sign; -0 is zero. + // Stream text chunks, including around comments, without a temporary String. + // https://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#int + let invalid = || ParseError::InvalidStructure("PSS integer must be nonnegative xs:int".into()); + let mut value = 0usize; + let mut started = false; + let mut digit_seen = false; + let mut ended = false; + let mut negative = false; + for character in node + .children() + .filter_map(|child| child.text().filter(|_| child.is_text())) + .flat_map(str::chars) + { + if matches!(character, ' ' | '\t' | '\r' | '\n') { + if started { + ended = true; + } + continue; + } + if ended { + return Err(invalid()); + } + if !started && matches!(character, '+' | '-') { + started = true; + negative = character == '-'; + continue; + } + let Some(digit) = character + .to_digit(10) + .filter(|_| character.is_ascii_digit()) + else { + return Err(invalid()); + }; + if value > (i32::MAX as usize - digit as usize) / 10 { + return Err(invalid()); + } + value = value * 10 + digit as usize; + started = true; + digit_seen = true; + } + if !digit_seen || (negative && value != 0) { + return Err(invalid()); + } + Ok(value) +} + impl ByteAlignedHmacOutputLength { fn parse(text: &str, maximum_bits: usize) -> Result { // xs:integer whitespace collapse covers only XML whitespace, not Unicode diff --git a/src/xmldsig/sign.rs b/src/xmldsig/sign.rs index d70a998d..eed580ac 100644 --- a/src/xmldsig/sign.rs +++ b/src/xmldsig/sign.rs @@ -407,9 +407,23 @@ fn expected_signature_output_len( SigningPublicKeyInfo::Rsa { modulus, exponent, .. }, - ) if method.is_rsa() => policy - .rsa_keys - .validate_components("signing", &modulus, &exponent)?, + ) if method.is_rsa() => { + let width = policy + .rsa_keys + .validate_components("signing", &modulus, &exponent)?; + if let Some(parameters) = method.rsa_pss_parameters() { + let normalized = modulus + .iter() + .position(|byte| *byte != 0) + .map(|start| &modulus[start..]) + .ok_or(SigningKeyError::InvalidPublicKeyInfo)?; + let bits = normalized.len() * 8 - normalized[0].leading_zeros() as usize; + if !parameters.fits_modulus_bits(bits) { + return Err(SigningKeyError::InvalidPublicKeyInfo.into()); + } + } + width + } (method, SigningPublicKeyInfo::Ec { public_key, .. }) if method.ecdsa_digest().is_some() && public_key.first() == Some(&0x04) @@ -880,6 +894,14 @@ impl SigningKey for RsaSigningKey { algorithm: SignatureAlgorithm, canonical_signed_info: &[u8], ) -> Result, SigningKeyError> { + if let Some(parameters) = algorithm.rsa_pss_parameters() { + return crate::provider::rsa_pss::sign( + provider, + &self.key, + parameters, + canonical_signed_info, + ); + } match algorithm { #[cfg(feature = "legacy-algorithms")] SignatureAlgorithm::RsaMd5 => sign_rsa_pkcs1v15_with_rng( diff --git a/src/xmldsig/signature.rs b/src/xmldsig/signature.rs index 95669a01..7026dce9 100644 --- a/src/xmldsig/signature.rs +++ b/src/xmldsig/signature.rs @@ -46,6 +46,10 @@ pub(crate) fn signature_value_matches_algorithm_with_encoding( signature_value: &[u8], encoding: EcdsaSignatureValueEncoding, ) -> bool { + if algorithm.rsa_pss_parameters().is_some() { + return (1..=crate::hard_limits::RSA_MODULUS_BIT_CEILING / 8) + .contains(&signature_value.len()); + } match algorithm { #[cfg(feature = "legacy-algorithms")] SignatureAlgorithm::RsaMd5 | SignatureAlgorithm::RsaRipemd160 => { @@ -96,6 +100,16 @@ pub(crate) fn signature_value_matches_algorithm_with_encoding( | SignatureAlgorithm::RsaSha512 => { (1..=crate::hard_limits::RSA_MODULUS_BIT_CEILING / 8).contains(&signature_value.len()) } + SignatureAlgorithm::RsaPssSha1 + | SignatureAlgorithm::RsaPssSha224 + | SignatureAlgorithm::RsaPssSha256 + | SignatureAlgorithm::RsaPssSha384 + | SignatureAlgorithm::RsaPssSha512 + | SignatureAlgorithm::RsaPssSha3_224 + | SignatureAlgorithm::RsaPssSha3_256 + | SignatureAlgorithm::RsaPssSha3_384 + | SignatureAlgorithm::RsaPssSha3_512 + | SignatureAlgorithm::RsaPss(_) => unreachable!("PSS handled before dispatch"), SignatureAlgorithm::EcdsaSha1 | SignatureAlgorithm::EcdsaSha224 | SignatureAlgorithm::EcdsaSha256 @@ -156,6 +170,19 @@ pub(crate) fn signature_value_matches_spki_with_encoding( }); } } + if let Some(parameters) = algorithm.rsa_pss_parameters() { + use der::Decode as _; + let bytes = crate::provider::rsa_pss::encoded_public_key(public_key_spki_der, parameters) + .ok_or(SignatureVerificationError::InvalidKeyDer)?; + let key = rsa::pkcs1::RsaPublicKey::from_der(bytes) + .map_err(|_| SignatureVerificationError::InvalidKeyDer)?; + let modulus = key.modulus.as_bytes(); + let Some(first) = modulus.first() else { + return Err(SignatureVerificationError::InvalidKeyDer); + }; + let bits = modulus.len() * 8 - first.leading_zeros() as usize; + return Ok(parameters.fits_modulus_bits(bits) && signature_value.len() == modulus.len()); + } let (rest, spki) = SubjectPublicKeyInfo::from_der(public_key_spki_der) .map_err(|_| SignatureVerificationError::InvalidKeyDer)?; if !rest.is_empty() { @@ -372,6 +399,27 @@ pub(crate) fn validate_rsa_signature_spki_with_minimum( public_key_spki_der: &[u8], minimum_modulus_bits: usize, ) -> Result<(), SignatureVerificationError> { + if let Some(parameters) = algorithm.rsa_pss_parameters() { + use der::Decode as _; + let bytes = crate::provider::rsa_pss::encoded_public_key(public_key_spki_der, parameters) + .ok_or(SignatureVerificationError::InvalidKeyDer)?; + let key = rsa::pkcs1::RsaPublicKey::from_der(bytes) + .map_err(|_| SignatureVerificationError::InvalidKeyDer)?; + let modulus = key.modulus.as_bytes(); + validate_rsa_key_components( + modulus, + key.public_exponent.as_bytes(), + minimum_modulus_bits, + )?; + let bits = modulus.len() * 8 - modulus[0].leading_zeros() as usize; + return if parameters.fits_modulus_bits(bits) { + Ok(()) + } else { + Err(SignatureVerificationError::KeyAlgorithmMismatch { + uri: algorithm.uri().into(), + }) + }; + } let (rest, spki) = SubjectPublicKeyInfo::from_der(public_key_spki_der) .map_err(|_| SignatureVerificationError::InvalidKeyDer)?; if !rest.is_empty() { @@ -395,6 +443,16 @@ pub(crate) fn verify_rsa_signature_spki_primitive( signature_value: &[u8], ) -> Result { ensure_rsa_signature_algorithm(algorithm)?; + if let Some(parameters) = algorithm.rsa_pss_parameters() { + let key = crate::provider::rsa_pss::public_key(public_key_spki_der, parameters) + .ok_or(SignatureVerificationError::InvalidKeyDer)?; + return Ok(crate::provider::rsa_pss::verify( + &key, + parameters, + signed_data, + signature_value, + )); + } let key = rsa::RsaPublicKey::from_public_key_der(public_key_spki_der) .map_err(|_| SignatureVerificationError::InvalidKeyDer)?; let Ok(signature) = RsaPkcs1v15Signature::try_from(signature_value) else { @@ -674,7 +732,22 @@ fn validate_rsa_public_key( minimum_modulus_bits: usize, ) -> Result<(), SignatureVerificationError> { ensure_rsa_signature_algorithm(algorithm)?; - validate_rsa_key_components(rsa.modulus, rsa.exponent, minimum_modulus_bits) + validate_rsa_key_components(rsa.modulus, rsa.exponent, minimum_modulus_bits)?; + if let Some(parameters) = algorithm.rsa_pss_parameters() { + let modulus = rsa + .modulus + .iter() + .position(|byte| *byte != 0) + .map(|start| &rsa.modulus[start..]) + .ok_or(SignatureVerificationError::InvalidKeyDer)?; + let bits = modulus.len() * 8 - modulus[0].leading_zeros() as usize; + if !parameters.fits_modulus_bits(bits) { + return Err(SignatureVerificationError::KeyAlgorithmMismatch { + uri: algorithm.uri().into(), + }); + } + } + Ok(()) } /// Apply the RSA key-strength invariant shared by XMLDSig and X.509 algorithms. diff --git a/src/xmldsig/verify.rs b/src/xmldsig/verify.rs index 03f4f978..212a4dac 100644 --- a/src/xmldsig/verify.rs +++ b/src/xmldsig/verify.rs @@ -4244,7 +4244,17 @@ fn verify_with_algorithm( | SignatureAlgorithm::RsaSha224 | SignatureAlgorithm::RsaSha256 | SignatureAlgorithm::RsaSha384 - | SignatureAlgorithm::RsaSha512 => Ok(verify_rsa_signature_pem( + | SignatureAlgorithm::RsaSha512 + | SignatureAlgorithm::RsaPssSha1 + | SignatureAlgorithm::RsaPssSha224 + | SignatureAlgorithm::RsaPssSha256 + | SignatureAlgorithm::RsaPssSha384 + | SignatureAlgorithm::RsaPssSha512 + | SignatureAlgorithm::RsaPssSha3_224 + | SignatureAlgorithm::RsaPssSha3_256 + | SignatureAlgorithm::RsaPssSha3_384 + | SignatureAlgorithm::RsaPssSha3_512 + | SignatureAlgorithm::RsaPss(_) => Ok(verify_rsa_signature_pem( algorithm, public_key_pem, signed_data, diff --git a/tests/capability_ledger.rs b/tests/capability_ledger.rs index 0abd557c..0ee265fa 100644 --- a/tests/capability_ledger.rs +++ b/tests/capability_ledger.rs @@ -165,7 +165,7 @@ fn complete_surface_categories_are_stable() { "https://github.com/lsh123/xmlsec" ); assert_eq!(ledger.generated_by, "xml-sec-capability-ledger/2"); - assert_eq!(ledger.classifications.len(), 21); + assert_eq!(ledger.classifications.len(), 23); assert_eq!(ledger.availability.len(), 427); let counts = ledger @@ -349,7 +349,7 @@ fn native_algorithm_claims_match_the_rust_api() { ) }) .collect(); - assert_eq!(claims.len(), 64); + assert_eq!(claims.len(), 73); for item in claims { if item.classification == "feature-gated-legacy-uri" { // The ledger records the build requirement, not unconditional API @@ -412,7 +412,16 @@ fn assert_native_uri_support(item: &Item) { | "xmlSecHrefRsaSha224" | "xmlSecHrefRsaSha256" | "xmlSecHrefRsaSha384" - | "xmlSecHrefRsaSha512" => { + | "xmlSecHrefRsaSha512" + | "xmlSecHrefRsaPssSha1" + | "xmlSecHrefRsaPssSha224" + | "xmlSecHrefRsaPssSha256" + | "xmlSecHrefRsaPssSha384" + | "xmlSecHrefRsaPssSha512" + | "xmlSecHrefRsaPssSha3_224" + | "xmlSecHrefRsaPssSha3_256" + | "xmlSecHrefRsaPssSha3_384" + | "xmlSecHrefRsaPssSha3_512" => { assert_eq!(SignatureAlgorithm::from_uri(uri).unwrap().uri(), uri); } "xmlSecHrefSha1" | "xmlSecHrefSha224" | "xmlSecHrefSha256" | "xmlSecHrefSha384" @@ -560,6 +569,7 @@ fn legacy_algorithm_claims_are_policy_gated() { "xmlSecHrefEcdsaSha1", "xmlSecHrefHmacSha1", "xmlSecHrefRsaSha1", + "xmlSecHrefRsaPssSha1", "xmlSecHrefAes192Cbc", "xmlSecHrefAes192Gcm", "xmlSecHrefKWAes192", diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha224-rsa-pss-sha224.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha224-rsa-pss-sha224.tmpl new file mode 100644 index 00000000..c9423eb9 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha224-rsa-pss-sha224.tmpl @@ -0,0 +1,26 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + + + + + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha224-rsa-pss-sha224.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha224-rsa-pss-sha224.xml new file mode 100644 index 00000000..ff65af7a --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha224-rsa-pss-sha224.xml @@ -0,0 +1,36 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + 4eFM4tAZ1DS8K31g9ylGlRdmBSe/j8sbFbmgYQ== + + + VuECanZg7nYVF2ku4s5JwIoE1OMCaz3XqGj3vGMcDM5c6iKf4SeZKwm9/rsS7oUr +pYdOaJc1QlCk7aRE/kGxCjesjvXSDHeuWQ1lfFtV6bmCGNb1zIeV1W3rurCCjAPo +NII7wnaYFyVmAlqhKwkR/9ISkCacHATh+LtN/F2BxgXvqE/G9I/FMbQ/q+nIGz9w +EmBkBvQ9+YFQ6XY7JbgifYy5SEhR7goAvQTVTWPxk5zyEPeZHGANKWkHuqcYV9K6 +b2BMfnearO57pWThC7HRtN26UpUYmiKSruf+h+tBwOF+720hLYlwgG/vKa1vnkjs +7fbxdA7/gEkg1DZsbLUJVmXKbn70bV10npZEGIjShAe343zLRAprzJun/3mdkFuy +sORKQP5PKTY1IPMt8RA+0drZl7YI6zyv17uJA6aXWwxBm5j2tKpy7OikI5A+n6eR +SjBbrAOOUPbFhaJPDTEgawzXw3oQiNx8WXDUKnpE+EjpuqJvfqEmnGADW7zFOdrT +e6cqpmRjhCMvEUgWtMgJIN0G2Nvs5YNIHWXHysZ2md9zfDND6jfu1Soynxv4z8IL +bYr1VuzJ+4GJP4B9pIJFBLF4egUWcYnpg9QKqrO3M9+noLH05CLnCftrzK4CIx0f +Q3GHq88P4fT/ET+nroo5dX/oS6FodfpS+zPQR/6LVCc= + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha256-rsa-pss-sha256.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha256-rsa-pss-sha256.tmpl new file mode 100644 index 00000000..bdef3a89 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha256-rsa-pss-sha256.tmpl @@ -0,0 +1,26 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + + + + + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha256-rsa-pss-sha256.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha256-rsa-pss-sha256.xml new file mode 100644 index 00000000..5433f0f6 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha256-rsa-pss-sha256.xml @@ -0,0 +1,36 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + SsyGDfQDqAg9cuEzSIJDsrp8cSWGzoRqH8E3atXJ4Dw= + + + RYtGpV+HMqXKVtpRBpMDY1WQgIbejaIQitwzBk7n9H6rv46QCvtE5pKyS/OCfRPS +yb3WY7SwxFK+mCr0OwiTCh1XlS3pqjitG3GaM0gObOJIQp2Abia7VMsB3/wgXI8M +ewLOVE936r0eV0qD+9ZteRBS6zQ4z0ydtpiKCLgWHfs334xrzZoTB8WBF+sR+owO +dNqZOelE9bDBHBy1SCNfVTdA+YKB9CcqsQ0eafF+6DNp4Qj4d8Sww1T0zOaOA0B4 +SkAB91rrEDwpxFFxOZoQxBqWeNjrpLYnnici0gcgQyDmFke7zsauWe5kBhv/izvp +x1L9hChVOk/k8ZU964pQFOxuHzwD3ANJGxeBaqmAtwr3w8X9MEUHYGJ9EaixFxaN +eAzI6oypL3jkMaSDZnQV8KaIwdE4V792tpWrA7ZIdRnrMa93A14sMd3g+a3wE7Oz +rlrG1SmHXdWKl/ZKr5nH2mQWim2XgDGp6RwT/yrQkjrIcHKzVH55S+yrqhTHW9Ps +nst6aOIDoo1uFQjtfw7nsLQ1RFra4OrUaTHlJ6e1vvMZZxXATb8PIg3FvXQfoknd +/SW/FxJDo2xU99tLOvnN6Ssrio4OYbpHNG5H93vZZT92R4jYHFxqh524FPcHYN+v +GaHgWUeSovV+imPfvRrDOjCAtDyeeq4K5k6/nfvg7Lc= + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha384-rsa-pss-sha384.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha384-rsa-pss-sha384.tmpl new file mode 100644 index 00000000..df0f226d --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha384-rsa-pss-sha384.tmpl @@ -0,0 +1,26 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + + + + + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha384-rsa-pss-sha384.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha384-rsa-pss-sha384.xml new file mode 100644 index 00000000..7b7e5254 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha384-rsa-pss-sha384.xml @@ -0,0 +1,36 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + KWY6fYC7HAkpMGN1mD/luDV8Mt3J3r4F0u0h6tKpVu+Z5/y7dM3gh9PHJ4BzTfv2 + + + WS8bi9nyeBxkzt65FV/Ktm4+1ecw0qIxSECCvEJUA8Iak7eAfeF4cJ6VVRi7SJjc +EZ68RUBNvfQWOSiaKU3tBQ3AilEmZQir10BGffo0MB4K+XZVkKNwhL65vh9rgcX9 +RSxuWtmSaJXo/k6gaz/HhLJRA2usiUWkJqy3UKRT5A+FOKYopzfbd61byZ6kp2bk +Jky3FQKi7G/2MZ9Jc6nDnBPV778lGLMSDF9d3FvmEXTKyWMNUZeqezi7nVs7g0zy +mXf4m7hRaUsK8LcVdTyKFYstjlpTh8Dy2sKT7xqFXl8WwlhXbB1kFfrvhncZpFHQ +KkJlzDKt+zYndgmqzRiCRsH1PaNldHJDv9FXLZnqElamMnIQmo/24apH0+y4sdJg +0s/ZEIFdVwt3YizPIJdLXtJnm0H3CWm1MmfAImFirXdnxRp2SfKKK3boeEb4m0g/ +31ZtlNPc5fvtd/e8C6e1W8agq/f3gV4eNZmUzvDpoK8qjA9WQ/btgQ+9GZBPlmNs +Obq79MJd2GOA4tgH3Rwd9dYswsHmHArVjlybRK8H9aNQJsR3Qiyqr/PKxDGZDRTb +t9Gfh9mwr0ZEVCydBK4Ie6hI+UVPjjPWyP48YfMHkEaqHPlkmOgsyTp+k4yjUag+ +jVw5UHfDhkLNwEv3KcsHrndaOhAtIEP2LW6JRaSJLEw= + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_224-rsa-pss-sha3_224.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_224-rsa-pss-sha3_224.tmpl new file mode 100644 index 00000000..a3985158 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_224-rsa-pss-sha3_224.tmpl @@ -0,0 +1,26 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + + + + + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_224-rsa-pss-sha3_224.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_224-rsa-pss-sha3_224.xml new file mode 100644 index 00000000..e9a1e544 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_224-rsa-pss-sha3_224.xml @@ -0,0 +1,36 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + X3tXSS57ZkC9bE4vyycAGIV0qvGKUx0KU+YwYQ== + + + PdLHaxh/nCB58B5A8FlrykoR8wN/atO8Sx0nV0N1F0MW4J1gZJRbSxxOwH24/Kni +zJ+MIfvaLEaUrWw7exlfaF8hvdNV6uC+AnlWFSKbcbHx/BVOuThMaqLIEoOr83dn +CVlEv+LT5A+Fh9kvRj6kzcTwU+DQ8xIhOMxf/1PS5DP3M+WsR5iqoOGvTqEKKIBb +JvIjb9EJ2Oxe67Li0RtSbPcBJom9Q9kgTo/ktyUxobjir3ZHMbCkMVYN9mrSd24G +qEqxpw96mvGc5yHhzalmJavEMgZBcN5w8uh2FblMBLPDTZMlDDIB4smO86YhlKu8 +W78slmVMZsvjQLZIjdtZsFkWOV35e2d/QMpRQ7apVGpHjGuUro+BA+CCBtISqxXq +el0s4+94M4jJN85ERj/TXNWP9HFEYIw3HbWpIAFRg03/hMZxD5zCjKQbwHfEgyg6 +2EBKG4kYbxzC3gLs89YyILVk7d4hnxPupMws+XRVCh/fQTfsE1F7TV2e1LvRFkFY +I27P5Bus60CEq2xFFAKLpxnF4rOsJJqu1bNQJ8aC0M+FRqopqpareZuBhN5H8OMf +tjvtznggIkZziutvXPe+kIc8e1TlOFS97kLaz3kMC3s2N/tDl67+ADdwtZ7r15a7 +eOFY+UEtTtrSyfnspZwRoYr4KWzN8tjtK69XDRGzXZo= + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_256-rsa-pss-sha3_256.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_256-rsa-pss-sha3_256.tmpl new file mode 100644 index 00000000..7dd2c6a2 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_256-rsa-pss-sha3_256.tmpl @@ -0,0 +1,26 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + + + + + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_256-rsa-pss-sha3_256.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_256-rsa-pss-sha3_256.xml new file mode 100644 index 00000000..2e0d0cf8 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_256-rsa-pss-sha3_256.xml @@ -0,0 +1,36 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + XShr8Zf1KPWBrMfl2AoK9S96oaida2VecLFHlcojXFA= + + + GLd/elfx9CUwUj83SlgcFZ/gukXh4hUc9C8aEcJtL9bKdIdQkwmzw/ECyzF+LIw/ +HbkwNW4K7vSAOtq/UPnp4OOTXGVplDe6+kJnt0r0337F0yQvHp6k3NMfiXYX85kH +CmmUKoUjQ+GBW+otveBC6vORnymbhOx/GhqTQlkGByv7IUWK+JWMqnXhkFN9ImS1 +lFSpF1q1RcyoRkWLT2yMtJ1aZJd2Oy12YoT2E1WUNr3h2dxgDDkQQuLilEhJEofK +ao4vGWBdYoHwHy6Kb+P6tns1+hx5V6QzN3EiKuufqJdnWE7KPOWukz1oj6jtAnId +rxtLs3kk40NwApUhcWSJpvsj/LYyEBYXdDwY/Fn3My2xjsAGwLpGthVp0bt32EDY +nzS05tiXPKacrykVXAr//lyKznLneTspLsIf7D9Ua5IvyR5M3PBlYSNOrye8osSf +An+7QtSdv3qO/6EOmic78bG/xk9IkHf03BrA/2U35mouY2y48fUBW+tARrYKcPR3 +Eg8R49SNdFB57yCpiW3TILwCAjKf/XrHy0XKXHF8IhHUBiSliDMVq4S5rt/a5Zq3 +ING6paNbBdenDugXqrjiTQPlQJrIWgnm/vNtm+ji/I0dV2SFWi5V5Jv891Dos41X +qDam5d4WKcV+hy0rGu2hkVrVR45915kgoQYq4fh+Zrs= + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_384-rsa-pss-sha3_384.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_384-rsa-pss-sha3_384.tmpl new file mode 100644 index 00000000..cd017b16 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_384-rsa-pss-sha3_384.tmpl @@ -0,0 +1,26 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + + + + + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_384-rsa-pss-sha3_384.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_384-rsa-pss-sha3_384.xml new file mode 100644 index 00000000..78a1e810 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_384-rsa-pss-sha3_384.xml @@ -0,0 +1,36 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + qLTg42nGDACNpd3s/550RxL+qjn68swOr4Vp9PIOngvR72LYrsCcDCnrotZb2bdJ + + + EY7UDZQvpEtIcmk7cvrK101Pdg0RP0swd9U+3KMbEXBTZVCmbpw7C2e9reaF74Wl +RsEzXp2uEuGBtgQMhbXFEy8bvJUSwXMQ3CL1qrmGbuvKvjXg/DctuF3loYRiLrbi +8yNhzObBw/HfsYL5TW9F91ztqoXI3MYj5xqr0PpB6+F3MNqtqXKk5qHxSrF8UAEX +Rb0JERfj7ocCoV7JywVXSHwAk3dbGN+ibp+2WtuUUUfNNLNlnUScecl2Kj/Dr1Z2 +TCVufK8zlenmSx4EZTK6Qxoi3euCruE4HF2jRBAf5Sue2BI+cGyQKmQxb8sdioOf +zqnVNRRFpn7CZ8mD08/jXoW6pbnBZqu6ngUe2ZjXmF7Ph5ByV5alDZazf/JDY8Tq +2iycgNlmky2ZoJYenQ2DgyFZS6bTH/fZL3I4OTNyfMqGWz1SaE4zAqpingwVlyku +rzkmNq6RMFnJcgZlk0GwDj1K4YOugl3LUgYsid4ooKY7dx/b3I0l5HZgViCmzg5o +6BITl3WP2REqms87c0CynhchDKC8bDSyd9Lq/S05XXPLhGR4BO9GjWUsYS9ntLEb +o25EpWEA/afdic0+njwe+Kq83ZAr98tNthRahi8bZQm0aWkdF7FE9NC8DNcHiaP6 +10SYqKw/VBXETTgGVwgoPisI044sC+BvSDPkKtumy00= + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_512-rsa-pss-sha3_512.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_512-rsa-pss-sha3_512.tmpl new file mode 100644 index 00000000..2f42dafb --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_512-rsa-pss-sha3_512.tmpl @@ -0,0 +1,26 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + + + + + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_512-rsa-pss-sha3_512.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_512-rsa-pss-sha3_512.xml new file mode 100644 index 00000000..c4c8929f --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha3_512-rsa-pss-sha3_512.xml @@ -0,0 +1,37 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + 2p/RHQqLCamFpk0wX2uDvHgr1VbW4R59AMPS+55of+I8aow3ngAPjcZCviYDOB56 +BcDmVio+EcwhfxroBGT4QA== + + + PBX+bOpCoHaZVl3A42Ru6Yk8oz/0Anl6Evn3DUfogVFM4S4hMxCpupotH4gpRXnI +V6oRT0GOFK0G856Nos6yfqk5WVTF26SaYwXoMMzZjeb+8A4GkBxRO08ua5P0vLsj +Wi+2dCggVhRz7LJJ2ycigEnsKmBQTWG2vcgcX9nQOAtIBTYhkrlTwxWnaD97huU4 +MsW1ljAIdGMFPFZnGkOwj49svSKIcvWaXBbQE5ZvilKggZVGpkg40PTvLjoDQ69s +ilRtbcYwskcBlS0bHcif8bm76HQbybdGzjrF4F1aeXpo13z1z4D5oh/C+de9HLLx +ZD4qXMaNCrwUIxDIwojMV3r4BD2Vj2+vizkIQqOiO/CUn9f7Tr0x+8w8cU/oR+9F +AFE6OixCEam7RjSecyvO+Dele6pfBePbvzl2qbAhpzE18esVUQLke8YTMcYrA09Z +Be0kKC5V2nFpMqDfsZsxjEmjr2zMJvHFK1YKVh5wRffgT2Z+6ciKfdZB3NNtcpoY +ywg1slvp0OlQpmbtZJBIJdJ76KXh1LtR18L3khdJR0jYKFGSgi3Rrxstz2LRFg+J +XTOTan/xGKlXw1YVBcVH8WmDWOBDnZPm3L2U5w7n5jwYkeV1cnVheQWKGKbz98d2 +ldQ0fHMThiJJYoprcHQTtzvGL9hpcnjAC0cQYNoRiek= + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha512-rsa-pss-sha512.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha512-rsa-pss-sha512.tmpl new file mode 100644 index 00000000..2a0b33ab --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha512-rsa-pss-sha512.tmpl @@ -0,0 +1,26 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + + + + + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha512-rsa-pss-sha512.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha512-rsa-pss-sha512.xml new file mode 100644 index 00000000..952c6f12 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloped-sha512-rsa-pss-sha512.xml @@ -0,0 +1,37 @@ + + + + Hello, World! + + + + + + + + + + not(ancestor-or-self::dsig:Signature) + + + + j12SN+LRqX4RricEwl5iEpjyand0nCMO8T5dNYR5P661F2ZrUS5wSbyMdu826KrG +IQbvvjmkI+9+QmCrcJyXXA== + + + k1tvINMmNgpZ4/J7daVcif6dZ7xhTKEuwDFumjkPm/lwHZMlJ9zfig0dEnlnONyZ +O9vlLxtgmpsjxavfLRqCNhaRVrrco/TymP1tuYijZio01iKmPYKjqSJdgO9Fc0NT +UtzKZZOo/9Yld3oemiYOJmEzJ+qJXh9iX0eVFr7s+pO8rarBj87L0OSawf9OCdEt +qlR6Mp1OsdIVzaUyShZGbLAaFonUTlxbPhAJcTj9nwFPMKI+k2sc80QlDgD+JG1c +ltLpMeIw1ZpUDfZPTIUXfE7qe0tEIyXAQ00Nr9+LNQOqHpD+pZduVee16hX5YmEG +7Tm4nqg5ZvKNRYJbTHd+b08zPQR16CFFLsbrHGPyDi66vO7J/jTsa6dBDIoMoFmM +vS7if4/cZKEhw/dpVCKjJlZIkjVlh+9zNaivC0I5wEsEEKnvjtEDiiTEhu6yxzAo +p5D3bLKC6Dx6kj/QbqSLkoWlEsPUT3HZIIVsSEIOZX53piZShnKr4mxz4xfYKQVK +LXgu7ammZoziJCMG2j27WkcfX/L3EPc5gASmgBOBfhqc2heEqKONkgWM1uHAECiz +8rbulTgRm5CRjVnYFWEg2ZT4GpivvGZ89dTjiExY+CAewmGQMtHlp+u4iixK/AeV +Qp1p2v+x32XPFgOuPr02+rR3gJOUsMW6KJav9MVaZVk= + + TestKeyName-rsa-4096 + + + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha1.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha1.tmpl new file mode 100644 index 00000000..d6ccf332 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha1.tmpl @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + TestKeyName-rsa-4096 + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha1.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha1.xml new file mode 100644 index 00000000..b613bf29 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha1.xml @@ -0,0 +1,121 @@ + + + + + + + + 7/XTsHaBSOnJ/jXD5v0zL6VKYsk= + + + FAUL4QfiWr/MO4Y5RKqSupTrUh5EatIFzBOYjTzSKdzCRbHA3Hf4yT74ubOWviAu +L33V2Qmkfd5iJFxEC+uryK4U7B/7egwHZMTZm3wUYuvewzgY2ON0mY54+w2gS64q +NUQLm0sL0p6BCtvM5mQt8AwkAUewdExM4/r7bNxk3MsZDf4NfutFxWTyhcQ/YAXd +9X17c3I1+VzfTmrULImu7NVo8UVZQHr51bGvujhz++Zzqc0Snx4aU0onpvOtuC3Y +68L6BUAgBaQyW8wYe8uCfbN7S5tCRBy3YyKqWY/fSVjK1phxw9ej9mOO2cxBQxXA +vVIZH2+nxxmUJArWMHtURHiSEFiw9O5kNYdYUqTWnjjBQp5CJNRchyNo4CvMqsNu +g+9GqMPUf2ZiwrJNUV23EibzgZr2UDqLOZkgJa0zX+ID0WBkdbiUQsdCU81oZJVv +Slxddx7d4D+w4CyFw8ZfwG6z+tTUEyCalDuaY9PQM12pnvoyMr7kQiZs54lDoyBb +qS1dnKPCgAI4RiV3ayfaUwXzMNcZ3sahDiGU6dkazBkdoM+cwVOjCnnZU8SyC8+i +RhvdaCpy60aqzJohjku3Xx9MCwoHexu2WdwC9V7waWfVDOTz/DfiKw2AfT5QMg6t +yQIdBUzAWvvcAWM4rYKkd3Zp8mBx8UhV8ydNiCid3bM= + + TestKeyName-rsa-4096 + +MIIGFjCCBP6gAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT1QwDQYJKoZIhvcNAQEL +BQAwgbYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRgwFgYDVQQLEw9TZWNvbmQgbGV2ZWwgQ0ExFjAUBgNVBAMTDUFsZWtz +ZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTAgFw0y +NjAzMDgyMjE0MjdaGA8yMTI2MDIxMjIyMTQyN1owfTELMAkGA1UEBhMCVVMxEzAR +BgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJyYXJ5 +IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxGjAYBgNVBAMTEVRlc3Qg +S2V5IHJzYS00MDk2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApFht +8oSsDMTV1GOWqg7o7NVllW2835GtOiLPJ/dnRy9vEQGYqB+KSSX9axIVyrFNfiS6 +SsH7Tam9A4bEHSBP6risPS9wyoTpyy7q2a31ZUETmI0pFej9db2vgAvpmx8DX3e8 +Y03SecMYqNLr2HLj7daWhu9/OY+xrd6q567NLFmG3335Hr8wHNwl/HbdCwmXBWaw +16D1g1RSV0kkFvD1gHMZqAjANJsqmuKJogMj2waXFAy/KAsUK3cPDCDKu7KHxtAT +LZ0UWqPNgz8GLBPI87vmyxSGgbtw1XQWQa4zxdknz80qRGExROc8DMszs575N7+Z +vjSusT+PT+CQxmDSyiqtp/v2OIQS3zAR7uFv0Xb3DS5Cs0VWkGU/N0mrdU1nd4WB +ecdTZCXbG959r1HKtqiWKa7nOOxKTrwHr9cDrlzSW2kyXb/1tvdEE5gy1HNOil07 +SVUv4Vi6CRvUa3Jv/B6ifb0lY9wp82gc42TOLv9Udx9xm7Barh8lfzqc4T+VR1ON +jbHzeLyMC6aG54rZZpcorUOT7f6SfPHcbx2Jmz3T4g3UaML4nlJkBfpBSkBRloRp +dKffhnpyru5OQEb7fLxlDePEAOkYrTNbBaHEXFqO1gKSxz3Mg+4gCA9mZOXP9yLC +Dz10S9vROUVSu9H4CT4ucUPT2cEg95X5H/2fqRMCAwEAAaOCAVAwggFMMAwGA1Ud +EwQFMAMBAf8wLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp +ZmljYXRlMB0GA1UdDgQWBBTrTMwsoJ/NDeqdcDMAHNE2l2BDxDCB7gYDVR0jBIHm +MIHjgBTRfResRUKKjvmwFyXVPHKYnYg6JaGBtKSBsTCBrjELMAkGA1UEBhMCVVMx +EzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJy +YXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxEDAOBgNVBAsTB1Jv +b3QgQ0ExFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnht +bHNlY0BhbGVrc2V5LmNvbYIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcN +AQELBQADggEBAIlPInAPcM4cRhUqeRmWcwi4Ue5xkn5UL8hNPKsfbNDvRoa3aOKz +jc0WNd7LQZJzALP4Q+VoE9+TDYbM0fwIGpUr0RMcNUt1DzwVKyDKtbv/tOayIS2j +L8pI9AALHzjGdRjk713LuOd1ixwvEyaVBJtQ+vz39c3baSJQtSvXeVU0KLxJSqy8 +fgbBuiNx+hZiGsee9BzocAyCoSyKuyEqhxbvcBSDIIgLyCoroR/uXk+wsBgy/15X +QGa1GHVWwSLdaqACDlqvu5PYMMQq4IfY+fADf3tYl81ZiIJerRcHwZMa2zgof/lZ +0tzrqr9lKyHcVitF2kkwC50xi2hvkDrZhvI= + +MIIFEjCCA/qgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT04wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NDQ3WhgPMjEyNjAyMTIyMjA0NDdaMIGuMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEQMA4GA1UECxMHUm9vdCBDQTEWMBQG +A1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtz +ZXkuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtbKBr4EAoOm8 +zAW/RL8Wrd1+24EPUbz1RYQuSlcuHcyBwt3uGXVvXNQ6fCGLq5ikIi3NkMymecIB +9u1Jc96T0FkpSxQrqIIvlCP6gpaLBa+lz8ix8Xeb0uJ4Dg8RDmwTBfQU2ENagYLc +v0mpW7myAmqzGq1+xdgd2Cbt1FRB5t4YKqNl6+pFbeXL9EGbRoNPyuu+CfWrWVEe +JfWD1YzM6fhB0c/zqCxC32Y1h/sAzNFyYRmYUULh2MwVBVyt839h0jAUBzzBh0/q +EoVL5a9daDx3m6+PS1ACb+nXUSYaOu8lVM2rPxRjVITHBo+NHn012T8JNrwcExMn +FgeaVXo+NwIDAQABo4IBIjCCAR4wHQYDVR0OBBYEFDN5WuQBQ05geQStksygwwDM +bhBEMIHuBgNVHSMEgeYwgeOAFDN5WuQBQ05geQStksygwwDMbhBEoYG0pIGxMIGu +MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1M +IFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2Vj +KTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8G +CSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tghR3Ne5If2hi2vGzlW2WHMsP +pvNPTjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBVUqxGkYxvFZ7s +/Zkmjj1u88PvOjdj36LnGQCyVDwJPXXAXoqW9I3W3BPra/Xy1vjFo5erkdjvNh0f ++iyZVS/9EVdPKssPdZd39p0YIiUyG1RUYmN/IBDzSX/LwBTiLGlMBHFTRj6Lfs+e +Nfu6PISqABh+It3/3jlB882eixesdsjvtZc0J6sDka1byMoqe40twfI0tTMMv4Jr +QwGn7YeiVuWZ/GKUQxYrA+FfIWR5maBWtnhdmjaOBgmUhNtJB8yBcH82cRrxRIMX +f2quQrB3P4/WQC2bw3YPGxSv5wQoZwcwCn6f7g7oQFy6cANONMBG7GJpbw5B/8uB +S1a6d6Rg + +MIIFSDCCBDCgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NzQyWhgPMjEyNjAyMTIyMjA3NDJaMIG2MQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEYMBYGA1UECxMPU2Vjb25kIGxldmVs +IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxz +ZWNAYWxla3NleS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDw +fEPVxQD3TLiNRpoh7g1KRYODmnJcdJzi7FMXfKuAgkhNmQaoAHQd7/pcwtg3oNUH +QukupST89AC7/qakF7ykdEQnVzxggYgdXbhfDZhLcaVUuMtFGgM6lHL0hnSZo8U9 +LHKWOlPIhJemE/XziHqgAsQposis7IRhuUlSsDa2xFW7MfS2xF/+UhiclaHgyBZ/ +RDzn2b5K14VAJdt1xRaoMC5zVIzu1uk33+j97L78+z65VRG7fxGTau2c94Mcl2V+ +KjDulHAnxLVJkjczo0mVi+u0Vczq9VhUqbNlig9TERQAPBC3D4ZJHhJsBmJz+47i +7pNL/Pms8qr9U0PgbZaPAgMBAAGjggFQMIIBTDAMBgNVHRMEBTADAQH/MCwGCWCG +SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E +FgQU0X0XrEVCio75sBcl1TxymJ2IOiUwge4GA1UdIwSB5jCB44AUM3la5AFDTmB5 +BK2SzKDDAMxuEEShgbSkgbEwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxp +Zm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3 +dy5hbGVrc2V5LmNvbS94bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQD +Ew1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5j +b22CFHc17kh/aGLa8bOVbZYcyw+m809OMA0GCSqGSIb3DQEBCwUAA4IBAQAhrm/J +FdnYclb8HwQJdgGSYtUw2Wdrl1950H/ZUGwSKs6lGX8YT5xnj55AELLhbetTo+Be +Wwmg9kZbqnRC9tt0vIhFMko/uQZkn7vzrFEIfXgnEm2UGkkULfXH9pgtO4A9EQ2s +bbR4Oyi3n9q1w39aBdkUZnw3uthWKVHjcMW+n4m0RZBh4/snhHHlnxaIJzm4lB/s +DKNcXJTJHUbd1Kch5aOuSXCCmltwpEdEM9yaY1mr+jH9aD7lfo3FEJQxpO6M+AH6 +JDdmS2LzQUSXDO4fibegrI/IeTQeST92mZI4foLxqp6SG19WGs9sNFFDYCIl6lNq +LDAhZycGntLtGaZF + + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha224.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha224.tmpl new file mode 100644 index 00000000..7ab13b6c --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha224.tmpl @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + TestKeyName-rsa-4096 + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha224.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha224.xml new file mode 100644 index 00000000..1b489129 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha224.xml @@ -0,0 +1,121 @@ + + + + + + + + azpKU6mkkPqPdDdtDXlEzVb0Xo2HgZMfuJ8KBw== + + + JElfN7fBKH0q7fLSndPfwHZwMOUU1CLSeL5WtV/fYNFOlu7mUUiGahYAWXpehs62 +rlBCaE4TTBqfs80+9XBTSQeiZ1uNu6XhDc+GQ0IDJNU23xYA/Pr1OCBC8QVGAQBE +MfjqWgYHgtFuQuEzHte6mXzqIF4Hh6vYaE7d9Yp+I5Yd7pamk479gvbA/J6XKc/v +ct4cGPOrc7MINL/3sHRANJ9+02b8t3F9avXlqNXSbzTQcPc6RlnbMHK1s3ImSQ66 +b4Yny93/x3EDovfHPIa8/5A4IqjmLkIDP2BNkHSh2OUfFv4nsyLPiXR9d2LUSooX +qZyYiZFUfRgA95Qdbobd4OSHYOJGqQxdirBo3uV7DFr8s31tw3ngRNbUtAG4TnNw +NarexES9K3MTwAc9LgMggTt4dnQRW6+CFLK1J77MxFjwKtvwwVhIiL4fZcVORGa0 +duxo6OxeijMjBVmDOPi2kLtR11FBwnXXaUAuzHvYp7jIM7Gx5sRwKV7krz5t+fpG +y4UdKdMuXe5nbgAkDf2F/5uBu6XQG7rsAg+9p8SqMXuvoGGvAMzWXKRbxb8Pvr5a +RG7YLKnmNUm61h3Jz/+kvVv5Q/cSbwV1S3m4hvzgKmrRvwzlSm2lfLVeqmvWwiNk +T+vaHf5KLBCYT0MjErvQg9W+MpcHBnYSBqEkPtfHDUU= + + TestKeyName-rsa-4096 + +MIIGFjCCBP6gAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT1QwDQYJKoZIhvcNAQEL +BQAwgbYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRgwFgYDVQQLEw9TZWNvbmQgbGV2ZWwgQ0ExFjAUBgNVBAMTDUFsZWtz +ZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTAgFw0y +NjAzMDgyMjE0MjdaGA8yMTI2MDIxMjIyMTQyN1owfTELMAkGA1UEBhMCVVMxEzAR +BgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJyYXJ5 +IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxGjAYBgNVBAMTEVRlc3Qg +S2V5IHJzYS00MDk2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApFht +8oSsDMTV1GOWqg7o7NVllW2835GtOiLPJ/dnRy9vEQGYqB+KSSX9axIVyrFNfiS6 +SsH7Tam9A4bEHSBP6risPS9wyoTpyy7q2a31ZUETmI0pFej9db2vgAvpmx8DX3e8 +Y03SecMYqNLr2HLj7daWhu9/OY+xrd6q567NLFmG3335Hr8wHNwl/HbdCwmXBWaw +16D1g1RSV0kkFvD1gHMZqAjANJsqmuKJogMj2waXFAy/KAsUK3cPDCDKu7KHxtAT +LZ0UWqPNgz8GLBPI87vmyxSGgbtw1XQWQa4zxdknz80qRGExROc8DMszs575N7+Z +vjSusT+PT+CQxmDSyiqtp/v2OIQS3zAR7uFv0Xb3DS5Cs0VWkGU/N0mrdU1nd4WB +ecdTZCXbG959r1HKtqiWKa7nOOxKTrwHr9cDrlzSW2kyXb/1tvdEE5gy1HNOil07 +SVUv4Vi6CRvUa3Jv/B6ifb0lY9wp82gc42TOLv9Udx9xm7Barh8lfzqc4T+VR1ON +jbHzeLyMC6aG54rZZpcorUOT7f6SfPHcbx2Jmz3T4g3UaML4nlJkBfpBSkBRloRp +dKffhnpyru5OQEb7fLxlDePEAOkYrTNbBaHEXFqO1gKSxz3Mg+4gCA9mZOXP9yLC +Dz10S9vROUVSu9H4CT4ucUPT2cEg95X5H/2fqRMCAwEAAaOCAVAwggFMMAwGA1Ud +EwQFMAMBAf8wLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp +ZmljYXRlMB0GA1UdDgQWBBTrTMwsoJ/NDeqdcDMAHNE2l2BDxDCB7gYDVR0jBIHm +MIHjgBTRfResRUKKjvmwFyXVPHKYnYg6JaGBtKSBsTCBrjELMAkGA1UEBhMCVVMx +EzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJy +YXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxEDAOBgNVBAsTB1Jv +b3QgQ0ExFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnht +bHNlY0BhbGVrc2V5LmNvbYIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcN +AQELBQADggEBAIlPInAPcM4cRhUqeRmWcwi4Ue5xkn5UL8hNPKsfbNDvRoa3aOKz +jc0WNd7LQZJzALP4Q+VoE9+TDYbM0fwIGpUr0RMcNUt1DzwVKyDKtbv/tOayIS2j +L8pI9AALHzjGdRjk713LuOd1ixwvEyaVBJtQ+vz39c3baSJQtSvXeVU0KLxJSqy8 +fgbBuiNx+hZiGsee9BzocAyCoSyKuyEqhxbvcBSDIIgLyCoroR/uXk+wsBgy/15X +QGa1GHVWwSLdaqACDlqvu5PYMMQq4IfY+fADf3tYl81ZiIJerRcHwZMa2zgof/lZ +0tzrqr9lKyHcVitF2kkwC50xi2hvkDrZhvI= + +MIIFEjCCA/qgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT04wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NDQ3WhgPMjEyNjAyMTIyMjA0NDdaMIGuMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEQMA4GA1UECxMHUm9vdCBDQTEWMBQG +A1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtz +ZXkuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtbKBr4EAoOm8 +zAW/RL8Wrd1+24EPUbz1RYQuSlcuHcyBwt3uGXVvXNQ6fCGLq5ikIi3NkMymecIB +9u1Jc96T0FkpSxQrqIIvlCP6gpaLBa+lz8ix8Xeb0uJ4Dg8RDmwTBfQU2ENagYLc +v0mpW7myAmqzGq1+xdgd2Cbt1FRB5t4YKqNl6+pFbeXL9EGbRoNPyuu+CfWrWVEe +JfWD1YzM6fhB0c/zqCxC32Y1h/sAzNFyYRmYUULh2MwVBVyt839h0jAUBzzBh0/q +EoVL5a9daDx3m6+PS1ACb+nXUSYaOu8lVM2rPxRjVITHBo+NHn012T8JNrwcExMn +FgeaVXo+NwIDAQABo4IBIjCCAR4wHQYDVR0OBBYEFDN5WuQBQ05geQStksygwwDM +bhBEMIHuBgNVHSMEgeYwgeOAFDN5WuQBQ05geQStksygwwDMbhBEoYG0pIGxMIGu +MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1M +IFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2Vj +KTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8G +CSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tghR3Ne5If2hi2vGzlW2WHMsP +pvNPTjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBVUqxGkYxvFZ7s +/Zkmjj1u88PvOjdj36LnGQCyVDwJPXXAXoqW9I3W3BPra/Xy1vjFo5erkdjvNh0f ++iyZVS/9EVdPKssPdZd39p0YIiUyG1RUYmN/IBDzSX/LwBTiLGlMBHFTRj6Lfs+e +Nfu6PISqABh+It3/3jlB882eixesdsjvtZc0J6sDka1byMoqe40twfI0tTMMv4Jr +QwGn7YeiVuWZ/GKUQxYrA+FfIWR5maBWtnhdmjaOBgmUhNtJB8yBcH82cRrxRIMX +f2quQrB3P4/WQC2bw3YPGxSv5wQoZwcwCn6f7g7oQFy6cANONMBG7GJpbw5B/8uB +S1a6d6Rg + +MIIFSDCCBDCgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NzQyWhgPMjEyNjAyMTIyMjA3NDJaMIG2MQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEYMBYGA1UECxMPU2Vjb25kIGxldmVs +IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxz +ZWNAYWxla3NleS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDw +fEPVxQD3TLiNRpoh7g1KRYODmnJcdJzi7FMXfKuAgkhNmQaoAHQd7/pcwtg3oNUH +QukupST89AC7/qakF7ykdEQnVzxggYgdXbhfDZhLcaVUuMtFGgM6lHL0hnSZo8U9 +LHKWOlPIhJemE/XziHqgAsQposis7IRhuUlSsDa2xFW7MfS2xF/+UhiclaHgyBZ/ +RDzn2b5K14VAJdt1xRaoMC5zVIzu1uk33+j97L78+z65VRG7fxGTau2c94Mcl2V+ +KjDulHAnxLVJkjczo0mVi+u0Vczq9VhUqbNlig9TERQAPBC3D4ZJHhJsBmJz+47i +7pNL/Pms8qr9U0PgbZaPAgMBAAGjggFQMIIBTDAMBgNVHRMEBTADAQH/MCwGCWCG +SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E +FgQU0X0XrEVCio75sBcl1TxymJ2IOiUwge4GA1UdIwSB5jCB44AUM3la5AFDTmB5 +BK2SzKDDAMxuEEShgbSkgbEwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxp +Zm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3 +dy5hbGVrc2V5LmNvbS94bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQD +Ew1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5j +b22CFHc17kh/aGLa8bOVbZYcyw+m809OMA0GCSqGSIb3DQEBCwUAA4IBAQAhrm/J +FdnYclb8HwQJdgGSYtUw2Wdrl1950H/ZUGwSKs6lGX8YT5xnj55AELLhbetTo+Be +Wwmg9kZbqnRC9tt0vIhFMko/uQZkn7vzrFEIfXgnEm2UGkkULfXH9pgtO4A9EQ2s +bbR4Oyi3n9q1w39aBdkUZnw3uthWKVHjcMW+n4m0RZBh4/snhHHlnxaIJzm4lB/s +DKNcXJTJHUbd1Kch5aOuSXCCmltwpEdEM9yaY1mr+jH9aD7lfo3FEJQxpO6M+AH6 +JDdmS2LzQUSXDO4fibegrI/IeTQeST92mZI4foLxqp6SG19WGs9sNFFDYCIl6lNq +LDAhZycGntLtGaZF + + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha256.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha256.tmpl new file mode 100644 index 00000000..da768718 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha256.tmpl @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + TestKeyName-rsa-4096 + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha256.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha256.xml new file mode 100644 index 00000000..c414d78a --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha256.xml @@ -0,0 +1,121 @@ + + + + + + + + iDhYt78o294fA6pzQ7k44+eejrQMi+WX3l3UrUdtL1Q= + + + Q+2QFtQAEwGK7BGLcQV9mRRPTBCH2QTT6kMRWFF+KPHnULmnNS8dqmkiueMrHqhC +blVdrjtV7/h0cF0Qdf+6PQm77ceucN4PaZOd2BenLQYbW2ZgDuCtj44yb57Chrk4 +38r2nSCo7KIYp1Ue2pF88veDMWs+JWhLKTySBlfj3lPdrG1pssm+WIYMBVjTwSU8 +ldRP/0+njtN19l3KB4U+UEH4ycgooThnhvjcuV6pB9Bvry+t5fFehnL5WzgTTnoQ +lC8J6TuAndq8HDo3KYfA2UdIG+fybExszp4cQzvd5ttt7VehhKhZolGCohorRThS ++VKvVWX0R7W5Dq9yYOsPsvLE18tDV8ZXorR0bIVHrz9IfYzo2X+u26UUgfyF/LcY +R7N7HI1tpzpwpwG4Qu5xwJ66b6Aj4uRUmqHm4TtpAFKUPepJw/8kG0ky30QZXsGY +caIfEyJ7blYUQr4rV218OPhJ/Rx4oPCiCH//muzwQTyWVt9keAtDd9TtENJqUB/r +LNlSaoDOqTffkbKNetCIe+OwLontMcl/jiRBZwKPNDj9IQFfKAgn4Hof5Nrwu9hy +JrpwbF4nuW54g1z2c9ssQd3uyAwIltPuynIwi4gMMsurnBwwqSEFJwPGn4KEebCq +AR6kZGZCZZfrtUCOSx8k70ASv/0dxSwG0WQok7ophi4= + + TestKeyName-rsa-4096 + +MIIGFjCCBP6gAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT1QwDQYJKoZIhvcNAQEL +BQAwgbYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRgwFgYDVQQLEw9TZWNvbmQgbGV2ZWwgQ0ExFjAUBgNVBAMTDUFsZWtz +ZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTAgFw0y +NjAzMDgyMjE0MjdaGA8yMTI2MDIxMjIyMTQyN1owfTELMAkGA1UEBhMCVVMxEzAR +BgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJyYXJ5 +IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxGjAYBgNVBAMTEVRlc3Qg +S2V5IHJzYS00MDk2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApFht +8oSsDMTV1GOWqg7o7NVllW2835GtOiLPJ/dnRy9vEQGYqB+KSSX9axIVyrFNfiS6 +SsH7Tam9A4bEHSBP6risPS9wyoTpyy7q2a31ZUETmI0pFej9db2vgAvpmx8DX3e8 +Y03SecMYqNLr2HLj7daWhu9/OY+xrd6q567NLFmG3335Hr8wHNwl/HbdCwmXBWaw +16D1g1RSV0kkFvD1gHMZqAjANJsqmuKJogMj2waXFAy/KAsUK3cPDCDKu7KHxtAT +LZ0UWqPNgz8GLBPI87vmyxSGgbtw1XQWQa4zxdknz80qRGExROc8DMszs575N7+Z +vjSusT+PT+CQxmDSyiqtp/v2OIQS3zAR7uFv0Xb3DS5Cs0VWkGU/N0mrdU1nd4WB +ecdTZCXbG959r1HKtqiWKa7nOOxKTrwHr9cDrlzSW2kyXb/1tvdEE5gy1HNOil07 +SVUv4Vi6CRvUa3Jv/B6ifb0lY9wp82gc42TOLv9Udx9xm7Barh8lfzqc4T+VR1ON +jbHzeLyMC6aG54rZZpcorUOT7f6SfPHcbx2Jmz3T4g3UaML4nlJkBfpBSkBRloRp +dKffhnpyru5OQEb7fLxlDePEAOkYrTNbBaHEXFqO1gKSxz3Mg+4gCA9mZOXP9yLC +Dz10S9vROUVSu9H4CT4ucUPT2cEg95X5H/2fqRMCAwEAAaOCAVAwggFMMAwGA1Ud +EwQFMAMBAf8wLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp +ZmljYXRlMB0GA1UdDgQWBBTrTMwsoJ/NDeqdcDMAHNE2l2BDxDCB7gYDVR0jBIHm +MIHjgBTRfResRUKKjvmwFyXVPHKYnYg6JaGBtKSBsTCBrjELMAkGA1UEBhMCVVMx +EzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJy +YXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxEDAOBgNVBAsTB1Jv +b3QgQ0ExFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnht +bHNlY0BhbGVrc2V5LmNvbYIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcN +AQELBQADggEBAIlPInAPcM4cRhUqeRmWcwi4Ue5xkn5UL8hNPKsfbNDvRoa3aOKz +jc0WNd7LQZJzALP4Q+VoE9+TDYbM0fwIGpUr0RMcNUt1DzwVKyDKtbv/tOayIS2j +L8pI9AALHzjGdRjk713LuOd1ixwvEyaVBJtQ+vz39c3baSJQtSvXeVU0KLxJSqy8 +fgbBuiNx+hZiGsee9BzocAyCoSyKuyEqhxbvcBSDIIgLyCoroR/uXk+wsBgy/15X +QGa1GHVWwSLdaqACDlqvu5PYMMQq4IfY+fADf3tYl81ZiIJerRcHwZMa2zgof/lZ +0tzrqr9lKyHcVitF2kkwC50xi2hvkDrZhvI= + +MIIFEjCCA/qgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT04wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NDQ3WhgPMjEyNjAyMTIyMjA0NDdaMIGuMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEQMA4GA1UECxMHUm9vdCBDQTEWMBQG +A1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtz +ZXkuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtbKBr4EAoOm8 +zAW/RL8Wrd1+24EPUbz1RYQuSlcuHcyBwt3uGXVvXNQ6fCGLq5ikIi3NkMymecIB +9u1Jc96T0FkpSxQrqIIvlCP6gpaLBa+lz8ix8Xeb0uJ4Dg8RDmwTBfQU2ENagYLc +v0mpW7myAmqzGq1+xdgd2Cbt1FRB5t4YKqNl6+pFbeXL9EGbRoNPyuu+CfWrWVEe +JfWD1YzM6fhB0c/zqCxC32Y1h/sAzNFyYRmYUULh2MwVBVyt839h0jAUBzzBh0/q +EoVL5a9daDx3m6+PS1ACb+nXUSYaOu8lVM2rPxRjVITHBo+NHn012T8JNrwcExMn +FgeaVXo+NwIDAQABo4IBIjCCAR4wHQYDVR0OBBYEFDN5WuQBQ05geQStksygwwDM +bhBEMIHuBgNVHSMEgeYwgeOAFDN5WuQBQ05geQStksygwwDMbhBEoYG0pIGxMIGu +MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1M +IFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2Vj +KTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8G +CSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tghR3Ne5If2hi2vGzlW2WHMsP +pvNPTjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBVUqxGkYxvFZ7s +/Zkmjj1u88PvOjdj36LnGQCyVDwJPXXAXoqW9I3W3BPra/Xy1vjFo5erkdjvNh0f ++iyZVS/9EVdPKssPdZd39p0YIiUyG1RUYmN/IBDzSX/LwBTiLGlMBHFTRj6Lfs+e +Nfu6PISqABh+It3/3jlB882eixesdsjvtZc0J6sDka1byMoqe40twfI0tTMMv4Jr +QwGn7YeiVuWZ/GKUQxYrA+FfIWR5maBWtnhdmjaOBgmUhNtJB8yBcH82cRrxRIMX +f2quQrB3P4/WQC2bw3YPGxSv5wQoZwcwCn6f7g7oQFy6cANONMBG7GJpbw5B/8uB +S1a6d6Rg + +MIIFSDCCBDCgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NzQyWhgPMjEyNjAyMTIyMjA3NDJaMIG2MQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEYMBYGA1UECxMPU2Vjb25kIGxldmVs +IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxz +ZWNAYWxla3NleS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDw +fEPVxQD3TLiNRpoh7g1KRYODmnJcdJzi7FMXfKuAgkhNmQaoAHQd7/pcwtg3oNUH +QukupST89AC7/qakF7ykdEQnVzxggYgdXbhfDZhLcaVUuMtFGgM6lHL0hnSZo8U9 +LHKWOlPIhJemE/XziHqgAsQposis7IRhuUlSsDa2xFW7MfS2xF/+UhiclaHgyBZ/ +RDzn2b5K14VAJdt1xRaoMC5zVIzu1uk33+j97L78+z65VRG7fxGTau2c94Mcl2V+ +KjDulHAnxLVJkjczo0mVi+u0Vczq9VhUqbNlig9TERQAPBC3D4ZJHhJsBmJz+47i +7pNL/Pms8qr9U0PgbZaPAgMBAAGjggFQMIIBTDAMBgNVHRMEBTADAQH/MCwGCWCG +SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E +FgQU0X0XrEVCio75sBcl1TxymJ2IOiUwge4GA1UdIwSB5jCB44AUM3la5AFDTmB5 +BK2SzKDDAMxuEEShgbSkgbEwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxp +Zm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3 +dy5hbGVrc2V5LmNvbS94bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQD +Ew1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5j +b22CFHc17kh/aGLa8bOVbZYcyw+m809OMA0GCSqGSIb3DQEBCwUAA4IBAQAhrm/J +FdnYclb8HwQJdgGSYtUw2Wdrl1950H/ZUGwSKs6lGX8YT5xnj55AELLhbetTo+Be +Wwmg9kZbqnRC9tt0vIhFMko/uQZkn7vzrFEIfXgnEm2UGkkULfXH9pgtO4A9EQ2s +bbR4Oyi3n9q1w39aBdkUZnw3uthWKVHjcMW+n4m0RZBh4/snhHHlnxaIJzm4lB/s +DKNcXJTJHUbd1Kch5aOuSXCCmltwpEdEM9yaY1mr+jH9aD7lfo3FEJQxpO6M+AH6 +JDdmS2LzQUSXDO4fibegrI/IeTQeST92mZI4foLxqp6SG19WGs9sNFFDYCIl6lNq +LDAhZycGntLtGaZF + + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha384.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha384.tmpl new file mode 100644 index 00000000..0a7a75e1 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha384.tmpl @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + TestKeyName-rsa-4096 + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha384.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha384.xml new file mode 100644 index 00000000..cc33e045 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha384.xml @@ -0,0 +1,121 @@ + + + + + + + + uTx8AeqrTmv+nijRsWW7TOs1pCIuCudsFRVloP6hPin8Q4x9fFX2j/zj53XB37OG + + + KaNzTq93ZeVp3Df2fRSh+DD6VQo6V8R+V5nsWWGAy5MfdHlSigo1URqLJhHJvwbG +Y0+o8tcL6KMNZTYgytz5UbPAzXgZIvukyitbVq3XupTgryv7HtVA1DE+BponmFW4 +VC3DMCpYsOFN1vC0Z5l9XIaoOWZoRAV/0S4UtLG6uZ49uNmNkQtSNwyrndz6coP3 +Mw65hjz6u5Mh1NGh/JVUjwSl+0w/YZI+OafWexqBOhga8CXi//yBEWwGrPECagAe +GUesSbdIBrqcd606K1XarYNwuADCmKJRus8/HheeJa9KDkPp2XY5DCYzLMVp9QIZ +8FjFZ8Y3bUTdUStIrl85uv+azJTue52+DWDMIcLE5zzUuRFMZXiowbz7t/OiiEjs +ZHB5HxdZQbCHNCFPavOF2unb8FKgDC7gOXk4UznuvpQJI1Ruxd8SQG4Kf/jfFBas +zajHcRQMSL14yk9NexHh7Jo3HiCRDI1+v7JE43U0fpCFAj+NO/WFkiAOBW6DRGZa ++rr92mbL0S5eHmnweWxmohd7+H20Rsc75mJpT4SMeRsswBaE1LWC0CmbHyL1H6P4 +vcf1/65kWT5pT0kHTbec7GPUeAZON9apivn3AWuj6r8cOeVgRuAQjOSPhMrShexF +EdDpg3d+Q7ObuD0Ou1wUhF22WkRiQPw1U0Br9D44A9o= + + TestKeyName-rsa-4096 + +MIIGFjCCBP6gAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT1QwDQYJKoZIhvcNAQEL +BQAwgbYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRgwFgYDVQQLEw9TZWNvbmQgbGV2ZWwgQ0ExFjAUBgNVBAMTDUFsZWtz +ZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTAgFw0y +NjAzMDgyMjE0MjdaGA8yMTI2MDIxMjIyMTQyN1owfTELMAkGA1UEBhMCVVMxEzAR +BgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJyYXJ5 +IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxGjAYBgNVBAMTEVRlc3Qg +S2V5IHJzYS00MDk2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApFht +8oSsDMTV1GOWqg7o7NVllW2835GtOiLPJ/dnRy9vEQGYqB+KSSX9axIVyrFNfiS6 +SsH7Tam9A4bEHSBP6risPS9wyoTpyy7q2a31ZUETmI0pFej9db2vgAvpmx8DX3e8 +Y03SecMYqNLr2HLj7daWhu9/OY+xrd6q567NLFmG3335Hr8wHNwl/HbdCwmXBWaw +16D1g1RSV0kkFvD1gHMZqAjANJsqmuKJogMj2waXFAy/KAsUK3cPDCDKu7KHxtAT +LZ0UWqPNgz8GLBPI87vmyxSGgbtw1XQWQa4zxdknz80qRGExROc8DMszs575N7+Z +vjSusT+PT+CQxmDSyiqtp/v2OIQS3zAR7uFv0Xb3DS5Cs0VWkGU/N0mrdU1nd4WB +ecdTZCXbG959r1HKtqiWKa7nOOxKTrwHr9cDrlzSW2kyXb/1tvdEE5gy1HNOil07 +SVUv4Vi6CRvUa3Jv/B6ifb0lY9wp82gc42TOLv9Udx9xm7Barh8lfzqc4T+VR1ON +jbHzeLyMC6aG54rZZpcorUOT7f6SfPHcbx2Jmz3T4g3UaML4nlJkBfpBSkBRloRp +dKffhnpyru5OQEb7fLxlDePEAOkYrTNbBaHEXFqO1gKSxz3Mg+4gCA9mZOXP9yLC +Dz10S9vROUVSu9H4CT4ucUPT2cEg95X5H/2fqRMCAwEAAaOCAVAwggFMMAwGA1Ud +EwQFMAMBAf8wLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp +ZmljYXRlMB0GA1UdDgQWBBTrTMwsoJ/NDeqdcDMAHNE2l2BDxDCB7gYDVR0jBIHm +MIHjgBTRfResRUKKjvmwFyXVPHKYnYg6JaGBtKSBsTCBrjELMAkGA1UEBhMCVVMx +EzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJy +YXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxEDAOBgNVBAsTB1Jv +b3QgQ0ExFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnht +bHNlY0BhbGVrc2V5LmNvbYIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcN +AQELBQADggEBAIlPInAPcM4cRhUqeRmWcwi4Ue5xkn5UL8hNPKsfbNDvRoa3aOKz +jc0WNd7LQZJzALP4Q+VoE9+TDYbM0fwIGpUr0RMcNUt1DzwVKyDKtbv/tOayIS2j +L8pI9AALHzjGdRjk713LuOd1ixwvEyaVBJtQ+vz39c3baSJQtSvXeVU0KLxJSqy8 +fgbBuiNx+hZiGsee9BzocAyCoSyKuyEqhxbvcBSDIIgLyCoroR/uXk+wsBgy/15X +QGa1GHVWwSLdaqACDlqvu5PYMMQq4IfY+fADf3tYl81ZiIJerRcHwZMa2zgof/lZ +0tzrqr9lKyHcVitF2kkwC50xi2hvkDrZhvI= + +MIIFEjCCA/qgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT04wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NDQ3WhgPMjEyNjAyMTIyMjA0NDdaMIGuMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEQMA4GA1UECxMHUm9vdCBDQTEWMBQG +A1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtz +ZXkuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtbKBr4EAoOm8 +zAW/RL8Wrd1+24EPUbz1RYQuSlcuHcyBwt3uGXVvXNQ6fCGLq5ikIi3NkMymecIB +9u1Jc96T0FkpSxQrqIIvlCP6gpaLBa+lz8ix8Xeb0uJ4Dg8RDmwTBfQU2ENagYLc +v0mpW7myAmqzGq1+xdgd2Cbt1FRB5t4YKqNl6+pFbeXL9EGbRoNPyuu+CfWrWVEe +JfWD1YzM6fhB0c/zqCxC32Y1h/sAzNFyYRmYUULh2MwVBVyt839h0jAUBzzBh0/q +EoVL5a9daDx3m6+PS1ACb+nXUSYaOu8lVM2rPxRjVITHBo+NHn012T8JNrwcExMn +FgeaVXo+NwIDAQABo4IBIjCCAR4wHQYDVR0OBBYEFDN5WuQBQ05geQStksygwwDM +bhBEMIHuBgNVHSMEgeYwgeOAFDN5WuQBQ05geQStksygwwDMbhBEoYG0pIGxMIGu +MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1M +IFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2Vj +KTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8G +CSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tghR3Ne5If2hi2vGzlW2WHMsP +pvNPTjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBVUqxGkYxvFZ7s +/Zkmjj1u88PvOjdj36LnGQCyVDwJPXXAXoqW9I3W3BPra/Xy1vjFo5erkdjvNh0f ++iyZVS/9EVdPKssPdZd39p0YIiUyG1RUYmN/IBDzSX/LwBTiLGlMBHFTRj6Lfs+e +Nfu6PISqABh+It3/3jlB882eixesdsjvtZc0J6sDka1byMoqe40twfI0tTMMv4Jr +QwGn7YeiVuWZ/GKUQxYrA+FfIWR5maBWtnhdmjaOBgmUhNtJB8yBcH82cRrxRIMX +f2quQrB3P4/WQC2bw3YPGxSv5wQoZwcwCn6f7g7oQFy6cANONMBG7GJpbw5B/8uB +S1a6d6Rg + +MIIFSDCCBDCgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NzQyWhgPMjEyNjAyMTIyMjA3NDJaMIG2MQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEYMBYGA1UECxMPU2Vjb25kIGxldmVs +IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxz +ZWNAYWxla3NleS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDw +fEPVxQD3TLiNRpoh7g1KRYODmnJcdJzi7FMXfKuAgkhNmQaoAHQd7/pcwtg3oNUH +QukupST89AC7/qakF7ykdEQnVzxggYgdXbhfDZhLcaVUuMtFGgM6lHL0hnSZo8U9 +LHKWOlPIhJemE/XziHqgAsQposis7IRhuUlSsDa2xFW7MfS2xF/+UhiclaHgyBZ/ +RDzn2b5K14VAJdt1xRaoMC5zVIzu1uk33+j97L78+z65VRG7fxGTau2c94Mcl2V+ +KjDulHAnxLVJkjczo0mVi+u0Vczq9VhUqbNlig9TERQAPBC3D4ZJHhJsBmJz+47i +7pNL/Pms8qr9U0PgbZaPAgMBAAGjggFQMIIBTDAMBgNVHRMEBTADAQH/MCwGCWCG +SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E +FgQU0X0XrEVCio75sBcl1TxymJ2IOiUwge4GA1UdIwSB5jCB44AUM3la5AFDTmB5 +BK2SzKDDAMxuEEShgbSkgbEwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxp +Zm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3 +dy5hbGVrc2V5LmNvbS94bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQD +Ew1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5j +b22CFHc17kh/aGLa8bOVbZYcyw+m809OMA0GCSqGSIb3DQEBCwUAA4IBAQAhrm/J +FdnYclb8HwQJdgGSYtUw2Wdrl1950H/ZUGwSKs6lGX8YT5xnj55AELLhbetTo+Be +Wwmg9kZbqnRC9tt0vIhFMko/uQZkn7vzrFEIfXgnEm2UGkkULfXH9pgtO4A9EQ2s +bbR4Oyi3n9q1w39aBdkUZnw3uthWKVHjcMW+n4m0RZBh4/snhHHlnxaIJzm4lB/s +DKNcXJTJHUbd1Kch5aOuSXCCmltwpEdEM9yaY1mr+jH9aD7lfo3FEJQxpO6M+AH6 +JDdmS2LzQUSXDO4fibegrI/IeTQeST92mZI4foLxqp6SG19WGs9sNFFDYCIl6lNq +LDAhZycGntLtGaZF + + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_224.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_224.tmpl new file mode 100644 index 00000000..893841a8 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_224.tmpl @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + TestKeyName-rsa-4096 + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_224.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_224.xml new file mode 100644 index 00000000..6e5f154b --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_224.xml @@ -0,0 +1,121 @@ + + + + + + + + yQUUZbH+NLUc6YAU+AOR8F2W7wlOUbAuFYnbQQ== + + + G2Oon533K3qjM8KMV3vhd5tP7M5pe8vOciY9XTCxEuLuo17IHoUGJpqO4wUsq9kr +Sy5XPeIslcVZGn8QqNhrLmIe7/Txjjv+KzYayV6w3voxV99TwybiJSUC/BxQpVs5 +1pbgLoUMnjknRU5QinOZyrLM+99RXCkX05FoW9XW8S4/RWSEDovUu1/g1TP+2Niv +PDTqdlPU6rdcXszGsMnNSnF2ZwJ8s0TFnToqJd87YHPFdm+jhzkwB9wywSyrXI8T +FPauzEq8E68phuFYHv746FJMAe9QT1ncHBSgHXat38ooPSnj27qAT06Adp75XSQO +iYy0yoI/aJetvPiGdmEU7OZ5JsNH7q5XpD0DnKwCXqchu8uq8ob0NENkCUaBGMUX +vO9vSPmUbg953IjfUSGTE1vlr++IPX15wqARuqMabf5gxqHEy1CDRoTJh6Oeg5SN +4qygsg96JZEgDBOzpM8IulcBp7xi5LW4ZYp5CeHfJjECTcto4GcIxjRjGOtf3JMp +of8FZEXkdJ+VWgozuguomBnRVIAhr+JDJzyNkovYCT7DBfEhWhHzH2ZJS4Fe9ymg +m0jkIW5ghf1ZIZQ3XSyy95v4aq78JCYdShIUGndK81lFzd3VLKp8Rx+AZPLJT5Sq +k05iqRaiY0EMWaF+QEUNkFe4ozjhaEuCTvwK0Tq5Hlw= + + TestKeyName-rsa-4096 + +MIIGFjCCBP6gAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT1QwDQYJKoZIhvcNAQEL +BQAwgbYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRgwFgYDVQQLEw9TZWNvbmQgbGV2ZWwgQ0ExFjAUBgNVBAMTDUFsZWtz +ZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTAgFw0y +NjAzMDgyMjE0MjdaGA8yMTI2MDIxMjIyMTQyN1owfTELMAkGA1UEBhMCVVMxEzAR +BgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJyYXJ5 +IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxGjAYBgNVBAMTEVRlc3Qg +S2V5IHJzYS00MDk2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApFht +8oSsDMTV1GOWqg7o7NVllW2835GtOiLPJ/dnRy9vEQGYqB+KSSX9axIVyrFNfiS6 +SsH7Tam9A4bEHSBP6risPS9wyoTpyy7q2a31ZUETmI0pFej9db2vgAvpmx8DX3e8 +Y03SecMYqNLr2HLj7daWhu9/OY+xrd6q567NLFmG3335Hr8wHNwl/HbdCwmXBWaw +16D1g1RSV0kkFvD1gHMZqAjANJsqmuKJogMj2waXFAy/KAsUK3cPDCDKu7KHxtAT +LZ0UWqPNgz8GLBPI87vmyxSGgbtw1XQWQa4zxdknz80qRGExROc8DMszs575N7+Z +vjSusT+PT+CQxmDSyiqtp/v2OIQS3zAR7uFv0Xb3DS5Cs0VWkGU/N0mrdU1nd4WB +ecdTZCXbG959r1HKtqiWKa7nOOxKTrwHr9cDrlzSW2kyXb/1tvdEE5gy1HNOil07 +SVUv4Vi6CRvUa3Jv/B6ifb0lY9wp82gc42TOLv9Udx9xm7Barh8lfzqc4T+VR1ON +jbHzeLyMC6aG54rZZpcorUOT7f6SfPHcbx2Jmz3T4g3UaML4nlJkBfpBSkBRloRp +dKffhnpyru5OQEb7fLxlDePEAOkYrTNbBaHEXFqO1gKSxz3Mg+4gCA9mZOXP9yLC +Dz10S9vROUVSu9H4CT4ucUPT2cEg95X5H/2fqRMCAwEAAaOCAVAwggFMMAwGA1Ud +EwQFMAMBAf8wLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp +ZmljYXRlMB0GA1UdDgQWBBTrTMwsoJ/NDeqdcDMAHNE2l2BDxDCB7gYDVR0jBIHm +MIHjgBTRfResRUKKjvmwFyXVPHKYnYg6JaGBtKSBsTCBrjELMAkGA1UEBhMCVVMx +EzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJy +YXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxEDAOBgNVBAsTB1Jv +b3QgQ0ExFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnht +bHNlY0BhbGVrc2V5LmNvbYIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcN +AQELBQADggEBAIlPInAPcM4cRhUqeRmWcwi4Ue5xkn5UL8hNPKsfbNDvRoa3aOKz +jc0WNd7LQZJzALP4Q+VoE9+TDYbM0fwIGpUr0RMcNUt1DzwVKyDKtbv/tOayIS2j +L8pI9AALHzjGdRjk713LuOd1ixwvEyaVBJtQ+vz39c3baSJQtSvXeVU0KLxJSqy8 +fgbBuiNx+hZiGsee9BzocAyCoSyKuyEqhxbvcBSDIIgLyCoroR/uXk+wsBgy/15X +QGa1GHVWwSLdaqACDlqvu5PYMMQq4IfY+fADf3tYl81ZiIJerRcHwZMa2zgof/lZ +0tzrqr9lKyHcVitF2kkwC50xi2hvkDrZhvI= + +MIIFEjCCA/qgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT04wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NDQ3WhgPMjEyNjAyMTIyMjA0NDdaMIGuMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEQMA4GA1UECxMHUm9vdCBDQTEWMBQG +A1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtz +ZXkuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtbKBr4EAoOm8 +zAW/RL8Wrd1+24EPUbz1RYQuSlcuHcyBwt3uGXVvXNQ6fCGLq5ikIi3NkMymecIB +9u1Jc96T0FkpSxQrqIIvlCP6gpaLBa+lz8ix8Xeb0uJ4Dg8RDmwTBfQU2ENagYLc +v0mpW7myAmqzGq1+xdgd2Cbt1FRB5t4YKqNl6+pFbeXL9EGbRoNPyuu+CfWrWVEe +JfWD1YzM6fhB0c/zqCxC32Y1h/sAzNFyYRmYUULh2MwVBVyt839h0jAUBzzBh0/q +EoVL5a9daDx3m6+PS1ACb+nXUSYaOu8lVM2rPxRjVITHBo+NHn012T8JNrwcExMn +FgeaVXo+NwIDAQABo4IBIjCCAR4wHQYDVR0OBBYEFDN5WuQBQ05geQStksygwwDM +bhBEMIHuBgNVHSMEgeYwgeOAFDN5WuQBQ05geQStksygwwDMbhBEoYG0pIGxMIGu +MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1M +IFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2Vj +KTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8G +CSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tghR3Ne5If2hi2vGzlW2WHMsP +pvNPTjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBVUqxGkYxvFZ7s +/Zkmjj1u88PvOjdj36LnGQCyVDwJPXXAXoqW9I3W3BPra/Xy1vjFo5erkdjvNh0f ++iyZVS/9EVdPKssPdZd39p0YIiUyG1RUYmN/IBDzSX/LwBTiLGlMBHFTRj6Lfs+e +Nfu6PISqABh+It3/3jlB882eixesdsjvtZc0J6sDka1byMoqe40twfI0tTMMv4Jr +QwGn7YeiVuWZ/GKUQxYrA+FfIWR5maBWtnhdmjaOBgmUhNtJB8yBcH82cRrxRIMX +f2quQrB3P4/WQC2bw3YPGxSv5wQoZwcwCn6f7g7oQFy6cANONMBG7GJpbw5B/8uB +S1a6d6Rg + +MIIFSDCCBDCgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NzQyWhgPMjEyNjAyMTIyMjA3NDJaMIG2MQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEYMBYGA1UECxMPU2Vjb25kIGxldmVs +IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxz +ZWNAYWxla3NleS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDw +fEPVxQD3TLiNRpoh7g1KRYODmnJcdJzi7FMXfKuAgkhNmQaoAHQd7/pcwtg3oNUH +QukupST89AC7/qakF7ykdEQnVzxggYgdXbhfDZhLcaVUuMtFGgM6lHL0hnSZo8U9 +LHKWOlPIhJemE/XziHqgAsQposis7IRhuUlSsDa2xFW7MfS2xF/+UhiclaHgyBZ/ +RDzn2b5K14VAJdt1xRaoMC5zVIzu1uk33+j97L78+z65VRG7fxGTau2c94Mcl2V+ +KjDulHAnxLVJkjczo0mVi+u0Vczq9VhUqbNlig9TERQAPBC3D4ZJHhJsBmJz+47i +7pNL/Pms8qr9U0PgbZaPAgMBAAGjggFQMIIBTDAMBgNVHRMEBTADAQH/MCwGCWCG +SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E +FgQU0X0XrEVCio75sBcl1TxymJ2IOiUwge4GA1UdIwSB5jCB44AUM3la5AFDTmB5 +BK2SzKDDAMxuEEShgbSkgbEwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxp +Zm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3 +dy5hbGVrc2V5LmNvbS94bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQD +Ew1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5j +b22CFHc17kh/aGLa8bOVbZYcyw+m809OMA0GCSqGSIb3DQEBCwUAA4IBAQAhrm/J +FdnYclb8HwQJdgGSYtUw2Wdrl1950H/ZUGwSKs6lGX8YT5xnj55AELLhbetTo+Be +Wwmg9kZbqnRC9tt0vIhFMko/uQZkn7vzrFEIfXgnEm2UGkkULfXH9pgtO4A9EQ2s +bbR4Oyi3n9q1w39aBdkUZnw3uthWKVHjcMW+n4m0RZBh4/snhHHlnxaIJzm4lB/s +DKNcXJTJHUbd1Kch5aOuSXCCmltwpEdEM9yaY1mr+jH9aD7lfo3FEJQxpO6M+AH6 +JDdmS2LzQUSXDO4fibegrI/IeTQeST92mZI4foLxqp6SG19WGs9sNFFDYCIl6lNq +LDAhZycGntLtGaZF + + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_256.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_256.tmpl new file mode 100644 index 00000000..cbaf7b65 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_256.tmpl @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + TestKeyName-rsa-4096 + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_256.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_256.xml new file mode 100644 index 00000000..612abafa --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_256.xml @@ -0,0 +1,121 @@ + + + + + + + + qanKU/we6k5r1tjbmGxVrK8hH1lKjtf6MrX5OVz0WpE= + + + RQkAncwTDIet3Xw3gteKhLMsuaY8O8EZJE1zvBEVQWemQZl/cciymsGtOYOOy3U3 +zQLczCbLN5fI3BF0mwGavnyuBe1UJfYzLad6KO3vLJF9VHWdVcKKxy7HKtErXomf +xo83jIxhRXCs5g2yHPtCm+PohLosuYQ6KK5KB9jrEYIWURnszRI3r52q2D2kVxIM +0RgJ9egzkO9IAsbApUUzU71WwB+EdeAhE1TbTNk92VQ89dkKpST89DuVlvzbMkXm +JCUPy65fJ0VYx2ml/Kqy/oPrvI6NC+ig9lMZYtoTDL10gtbeTiU8fHov1p0tM/6q +Ie+zCqpUQfvtlVEQ0A0+tDMByT3GjfUQ+uvTgU6evAiJAmZSdVEpUEriakassltp ++uZxCzuu3aywnSg2UwvY0RSr2auY7AlCOp1e43ip48ogbQBzao6fqDCcUDEK6yly +49DfvBBYPE+i9ncQ1GRxF2dEW2aVoDiO0bojkvp9iug6zRbjwD1jFagV/uN00sk+ +0ihg+kByBJIYeuLuVwlDLr/KIDkjfwXgUrXeuiPSaZhRRPY4QUT+leGFT2LY3GYy +yOQ6X0KeEGe9/rtPF+bAQkKChXaS1qbshxZE8ZATQWkOCNPDQYY44M/8WvZrkr+x +2M08Y1Mmsh5rIUZxEPYn0zCbuId4ue81RZlFe4hz1A8= + + TestKeyName-rsa-4096 + +MIIGFjCCBP6gAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT1QwDQYJKoZIhvcNAQEL +BQAwgbYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRgwFgYDVQQLEw9TZWNvbmQgbGV2ZWwgQ0ExFjAUBgNVBAMTDUFsZWtz +ZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTAgFw0y +NjAzMDgyMjE0MjdaGA8yMTI2MDIxMjIyMTQyN1owfTELMAkGA1UEBhMCVVMxEzAR +BgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJyYXJ5 +IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxGjAYBgNVBAMTEVRlc3Qg +S2V5IHJzYS00MDk2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApFht +8oSsDMTV1GOWqg7o7NVllW2835GtOiLPJ/dnRy9vEQGYqB+KSSX9axIVyrFNfiS6 +SsH7Tam9A4bEHSBP6risPS9wyoTpyy7q2a31ZUETmI0pFej9db2vgAvpmx8DX3e8 +Y03SecMYqNLr2HLj7daWhu9/OY+xrd6q567NLFmG3335Hr8wHNwl/HbdCwmXBWaw +16D1g1RSV0kkFvD1gHMZqAjANJsqmuKJogMj2waXFAy/KAsUK3cPDCDKu7KHxtAT +LZ0UWqPNgz8GLBPI87vmyxSGgbtw1XQWQa4zxdknz80qRGExROc8DMszs575N7+Z +vjSusT+PT+CQxmDSyiqtp/v2OIQS3zAR7uFv0Xb3DS5Cs0VWkGU/N0mrdU1nd4WB +ecdTZCXbG959r1HKtqiWKa7nOOxKTrwHr9cDrlzSW2kyXb/1tvdEE5gy1HNOil07 +SVUv4Vi6CRvUa3Jv/B6ifb0lY9wp82gc42TOLv9Udx9xm7Barh8lfzqc4T+VR1ON +jbHzeLyMC6aG54rZZpcorUOT7f6SfPHcbx2Jmz3T4g3UaML4nlJkBfpBSkBRloRp +dKffhnpyru5OQEb7fLxlDePEAOkYrTNbBaHEXFqO1gKSxz3Mg+4gCA9mZOXP9yLC +Dz10S9vROUVSu9H4CT4ucUPT2cEg95X5H/2fqRMCAwEAAaOCAVAwggFMMAwGA1Ud +EwQFMAMBAf8wLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp +ZmljYXRlMB0GA1UdDgQWBBTrTMwsoJ/NDeqdcDMAHNE2l2BDxDCB7gYDVR0jBIHm +MIHjgBTRfResRUKKjvmwFyXVPHKYnYg6JaGBtKSBsTCBrjELMAkGA1UEBhMCVVMx +EzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJy +YXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxEDAOBgNVBAsTB1Jv +b3QgQ0ExFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnht +bHNlY0BhbGVrc2V5LmNvbYIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcN +AQELBQADggEBAIlPInAPcM4cRhUqeRmWcwi4Ue5xkn5UL8hNPKsfbNDvRoa3aOKz +jc0WNd7LQZJzALP4Q+VoE9+TDYbM0fwIGpUr0RMcNUt1DzwVKyDKtbv/tOayIS2j +L8pI9AALHzjGdRjk713LuOd1ixwvEyaVBJtQ+vz39c3baSJQtSvXeVU0KLxJSqy8 +fgbBuiNx+hZiGsee9BzocAyCoSyKuyEqhxbvcBSDIIgLyCoroR/uXk+wsBgy/15X +QGa1GHVWwSLdaqACDlqvu5PYMMQq4IfY+fADf3tYl81ZiIJerRcHwZMa2zgof/lZ +0tzrqr9lKyHcVitF2kkwC50xi2hvkDrZhvI= + +MIIFEjCCA/qgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT04wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NDQ3WhgPMjEyNjAyMTIyMjA0NDdaMIGuMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEQMA4GA1UECxMHUm9vdCBDQTEWMBQG +A1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtz +ZXkuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtbKBr4EAoOm8 +zAW/RL8Wrd1+24EPUbz1RYQuSlcuHcyBwt3uGXVvXNQ6fCGLq5ikIi3NkMymecIB +9u1Jc96T0FkpSxQrqIIvlCP6gpaLBa+lz8ix8Xeb0uJ4Dg8RDmwTBfQU2ENagYLc +v0mpW7myAmqzGq1+xdgd2Cbt1FRB5t4YKqNl6+pFbeXL9EGbRoNPyuu+CfWrWVEe +JfWD1YzM6fhB0c/zqCxC32Y1h/sAzNFyYRmYUULh2MwVBVyt839h0jAUBzzBh0/q +EoVL5a9daDx3m6+PS1ACb+nXUSYaOu8lVM2rPxRjVITHBo+NHn012T8JNrwcExMn +FgeaVXo+NwIDAQABo4IBIjCCAR4wHQYDVR0OBBYEFDN5WuQBQ05geQStksygwwDM +bhBEMIHuBgNVHSMEgeYwgeOAFDN5WuQBQ05geQStksygwwDMbhBEoYG0pIGxMIGu +MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1M +IFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2Vj +KTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8G +CSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tghR3Ne5If2hi2vGzlW2WHMsP +pvNPTjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBVUqxGkYxvFZ7s +/Zkmjj1u88PvOjdj36LnGQCyVDwJPXXAXoqW9I3W3BPra/Xy1vjFo5erkdjvNh0f ++iyZVS/9EVdPKssPdZd39p0YIiUyG1RUYmN/IBDzSX/LwBTiLGlMBHFTRj6Lfs+e +Nfu6PISqABh+It3/3jlB882eixesdsjvtZc0J6sDka1byMoqe40twfI0tTMMv4Jr +QwGn7YeiVuWZ/GKUQxYrA+FfIWR5maBWtnhdmjaOBgmUhNtJB8yBcH82cRrxRIMX +f2quQrB3P4/WQC2bw3YPGxSv5wQoZwcwCn6f7g7oQFy6cANONMBG7GJpbw5B/8uB +S1a6d6Rg + +MIIFSDCCBDCgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NzQyWhgPMjEyNjAyMTIyMjA3NDJaMIG2MQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEYMBYGA1UECxMPU2Vjb25kIGxldmVs +IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxz +ZWNAYWxla3NleS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDw +fEPVxQD3TLiNRpoh7g1KRYODmnJcdJzi7FMXfKuAgkhNmQaoAHQd7/pcwtg3oNUH +QukupST89AC7/qakF7ykdEQnVzxggYgdXbhfDZhLcaVUuMtFGgM6lHL0hnSZo8U9 +LHKWOlPIhJemE/XziHqgAsQposis7IRhuUlSsDa2xFW7MfS2xF/+UhiclaHgyBZ/ +RDzn2b5K14VAJdt1xRaoMC5zVIzu1uk33+j97L78+z65VRG7fxGTau2c94Mcl2V+ +KjDulHAnxLVJkjczo0mVi+u0Vczq9VhUqbNlig9TERQAPBC3D4ZJHhJsBmJz+47i +7pNL/Pms8qr9U0PgbZaPAgMBAAGjggFQMIIBTDAMBgNVHRMEBTADAQH/MCwGCWCG +SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E +FgQU0X0XrEVCio75sBcl1TxymJ2IOiUwge4GA1UdIwSB5jCB44AUM3la5AFDTmB5 +BK2SzKDDAMxuEEShgbSkgbEwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxp +Zm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3 +dy5hbGVrc2V5LmNvbS94bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQD +Ew1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5j +b22CFHc17kh/aGLa8bOVbZYcyw+m809OMA0GCSqGSIb3DQEBCwUAA4IBAQAhrm/J +FdnYclb8HwQJdgGSYtUw2Wdrl1950H/ZUGwSKs6lGX8YT5xnj55AELLhbetTo+Be +Wwmg9kZbqnRC9tt0vIhFMko/uQZkn7vzrFEIfXgnEm2UGkkULfXH9pgtO4A9EQ2s +bbR4Oyi3n9q1w39aBdkUZnw3uthWKVHjcMW+n4m0RZBh4/snhHHlnxaIJzm4lB/s +DKNcXJTJHUbd1Kch5aOuSXCCmltwpEdEM9yaY1mr+jH9aD7lfo3FEJQxpO6M+AH6 +JDdmS2LzQUSXDO4fibegrI/IeTQeST92mZI4foLxqp6SG19WGs9sNFFDYCIl6lNq +LDAhZycGntLtGaZF + + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_384.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_384.tmpl new file mode 100644 index 00000000..ef994ae0 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_384.tmpl @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + TestKeyName-rsa-4096 + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_384.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_384.xml new file mode 100644 index 00000000..79ae3698 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_384.xml @@ -0,0 +1,121 @@ + + + + + + + + Ix91uCahqTmb4m5TkDCFkRzhFAX/cYMGe0IMy2OvXSM4wlTS0kujJrf8k9KgCB6N + + + cDlH1fRVeyXR8Da1CFE3Zntw89dhuv5jlRP21roTYZp1RxgA3OObX1LOQQfDrpAT +CsRdYhPSFUhBLQU8KDPWNdhfUSY21jLs5hBN8c5z/PlOSJ41zSsG12RYET4YcAtX +vt5k7JOdGMXUueLOZwS4BcNR6SoHVbTkl42J9Q5wbr+NIXRzbdTmC6BYXPnigner +YeveBRa3wHYowsv4QXcb7TcC9rRTNzenCLboINmKQwwV9bU1QZH4aPzFDr5zax5i +0FF8dQEw/8NjYmuT8gKCyUJqNwmVA9eV2HG3cJtH0dRTKsV6I+G8eUsXQIBguP+6 +VOrkgzZOFqEgry2RZBfXBW4pyDz8ii87RvrbS1KPIiac8ZkA4iPFXUwNigcCgJxI +YwCJtGPuOy5En3kh1qZh3AvBnkR0VLKti35pAKlRI7CQZe9qitY0dduihe9Ai0dF +O1Ke/1jyvwLysuQYink8ux6tfSISgrLduLF7w5W7poA3/vsHpeYrCDw9osq9F/Sx +DqcjVumOnoRpcTndaMIUVGBhmDwh26+dvC1Q/fxUWOyHe8WUbwczMKaV7soKLqhi +GOwyBahHP+wEsqu2vBoCOD2jcy7OdOWvzhq9WGQ78blMpKerDIdrxtp4gJd/qlc3 +9O1d8FVM9vE94vnBNfrbAxJL1b18if05/2GBj13Ac2c= + + TestKeyName-rsa-4096 + +MIIGFjCCBP6gAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT1QwDQYJKoZIhvcNAQEL +BQAwgbYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRgwFgYDVQQLEw9TZWNvbmQgbGV2ZWwgQ0ExFjAUBgNVBAMTDUFsZWtz +ZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTAgFw0y +NjAzMDgyMjE0MjdaGA8yMTI2MDIxMjIyMTQyN1owfTELMAkGA1UEBhMCVVMxEzAR +BgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJyYXJ5 +IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxGjAYBgNVBAMTEVRlc3Qg +S2V5IHJzYS00MDk2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApFht +8oSsDMTV1GOWqg7o7NVllW2835GtOiLPJ/dnRy9vEQGYqB+KSSX9axIVyrFNfiS6 +SsH7Tam9A4bEHSBP6risPS9wyoTpyy7q2a31ZUETmI0pFej9db2vgAvpmx8DX3e8 +Y03SecMYqNLr2HLj7daWhu9/OY+xrd6q567NLFmG3335Hr8wHNwl/HbdCwmXBWaw +16D1g1RSV0kkFvD1gHMZqAjANJsqmuKJogMj2waXFAy/KAsUK3cPDCDKu7KHxtAT +LZ0UWqPNgz8GLBPI87vmyxSGgbtw1XQWQa4zxdknz80qRGExROc8DMszs575N7+Z +vjSusT+PT+CQxmDSyiqtp/v2OIQS3zAR7uFv0Xb3DS5Cs0VWkGU/N0mrdU1nd4WB +ecdTZCXbG959r1HKtqiWKa7nOOxKTrwHr9cDrlzSW2kyXb/1tvdEE5gy1HNOil07 +SVUv4Vi6CRvUa3Jv/B6ifb0lY9wp82gc42TOLv9Udx9xm7Barh8lfzqc4T+VR1ON +jbHzeLyMC6aG54rZZpcorUOT7f6SfPHcbx2Jmz3T4g3UaML4nlJkBfpBSkBRloRp +dKffhnpyru5OQEb7fLxlDePEAOkYrTNbBaHEXFqO1gKSxz3Mg+4gCA9mZOXP9yLC +Dz10S9vROUVSu9H4CT4ucUPT2cEg95X5H/2fqRMCAwEAAaOCAVAwggFMMAwGA1Ud +EwQFMAMBAf8wLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp +ZmljYXRlMB0GA1UdDgQWBBTrTMwsoJ/NDeqdcDMAHNE2l2BDxDCB7gYDVR0jBIHm +MIHjgBTRfResRUKKjvmwFyXVPHKYnYg6JaGBtKSBsTCBrjELMAkGA1UEBhMCVVMx +EzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJy +YXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxEDAOBgNVBAsTB1Jv +b3QgQ0ExFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnht +bHNlY0BhbGVrc2V5LmNvbYIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcN +AQELBQADggEBAIlPInAPcM4cRhUqeRmWcwi4Ue5xkn5UL8hNPKsfbNDvRoa3aOKz +jc0WNd7LQZJzALP4Q+VoE9+TDYbM0fwIGpUr0RMcNUt1DzwVKyDKtbv/tOayIS2j +L8pI9AALHzjGdRjk713LuOd1ixwvEyaVBJtQ+vz39c3baSJQtSvXeVU0KLxJSqy8 +fgbBuiNx+hZiGsee9BzocAyCoSyKuyEqhxbvcBSDIIgLyCoroR/uXk+wsBgy/15X +QGa1GHVWwSLdaqACDlqvu5PYMMQq4IfY+fADf3tYl81ZiIJerRcHwZMa2zgof/lZ +0tzrqr9lKyHcVitF2kkwC50xi2hvkDrZhvI= + +MIIFEjCCA/qgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT04wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NDQ3WhgPMjEyNjAyMTIyMjA0NDdaMIGuMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEQMA4GA1UECxMHUm9vdCBDQTEWMBQG +A1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtz +ZXkuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtbKBr4EAoOm8 +zAW/RL8Wrd1+24EPUbz1RYQuSlcuHcyBwt3uGXVvXNQ6fCGLq5ikIi3NkMymecIB +9u1Jc96T0FkpSxQrqIIvlCP6gpaLBa+lz8ix8Xeb0uJ4Dg8RDmwTBfQU2ENagYLc +v0mpW7myAmqzGq1+xdgd2Cbt1FRB5t4YKqNl6+pFbeXL9EGbRoNPyuu+CfWrWVEe +JfWD1YzM6fhB0c/zqCxC32Y1h/sAzNFyYRmYUULh2MwVBVyt839h0jAUBzzBh0/q +EoVL5a9daDx3m6+PS1ACb+nXUSYaOu8lVM2rPxRjVITHBo+NHn012T8JNrwcExMn +FgeaVXo+NwIDAQABo4IBIjCCAR4wHQYDVR0OBBYEFDN5WuQBQ05geQStksygwwDM +bhBEMIHuBgNVHSMEgeYwgeOAFDN5WuQBQ05geQStksygwwDMbhBEoYG0pIGxMIGu +MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1M +IFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2Vj +KTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8G +CSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tghR3Ne5If2hi2vGzlW2WHMsP +pvNPTjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBVUqxGkYxvFZ7s +/Zkmjj1u88PvOjdj36LnGQCyVDwJPXXAXoqW9I3W3BPra/Xy1vjFo5erkdjvNh0f ++iyZVS/9EVdPKssPdZd39p0YIiUyG1RUYmN/IBDzSX/LwBTiLGlMBHFTRj6Lfs+e +Nfu6PISqABh+It3/3jlB882eixesdsjvtZc0J6sDka1byMoqe40twfI0tTMMv4Jr +QwGn7YeiVuWZ/GKUQxYrA+FfIWR5maBWtnhdmjaOBgmUhNtJB8yBcH82cRrxRIMX +f2quQrB3P4/WQC2bw3YPGxSv5wQoZwcwCn6f7g7oQFy6cANONMBG7GJpbw5B/8uB +S1a6d6Rg + +MIIFSDCCBDCgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NzQyWhgPMjEyNjAyMTIyMjA3NDJaMIG2MQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEYMBYGA1UECxMPU2Vjb25kIGxldmVs +IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxz +ZWNAYWxla3NleS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDw +fEPVxQD3TLiNRpoh7g1KRYODmnJcdJzi7FMXfKuAgkhNmQaoAHQd7/pcwtg3oNUH +QukupST89AC7/qakF7ykdEQnVzxggYgdXbhfDZhLcaVUuMtFGgM6lHL0hnSZo8U9 +LHKWOlPIhJemE/XziHqgAsQposis7IRhuUlSsDa2xFW7MfS2xF/+UhiclaHgyBZ/ +RDzn2b5K14VAJdt1xRaoMC5zVIzu1uk33+j97L78+z65VRG7fxGTau2c94Mcl2V+ +KjDulHAnxLVJkjczo0mVi+u0Vczq9VhUqbNlig9TERQAPBC3D4ZJHhJsBmJz+47i +7pNL/Pms8qr9U0PgbZaPAgMBAAGjggFQMIIBTDAMBgNVHRMEBTADAQH/MCwGCWCG +SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E +FgQU0X0XrEVCio75sBcl1TxymJ2IOiUwge4GA1UdIwSB5jCB44AUM3la5AFDTmB5 +BK2SzKDDAMxuEEShgbSkgbEwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxp +Zm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3 +dy5hbGVrc2V5LmNvbS94bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQD +Ew1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5j +b22CFHc17kh/aGLa8bOVbZYcyw+m809OMA0GCSqGSIb3DQEBCwUAA4IBAQAhrm/J +FdnYclb8HwQJdgGSYtUw2Wdrl1950H/ZUGwSKs6lGX8YT5xnj55AELLhbetTo+Be +Wwmg9kZbqnRC9tt0vIhFMko/uQZkn7vzrFEIfXgnEm2UGkkULfXH9pgtO4A9EQ2s +bbR4Oyi3n9q1w39aBdkUZnw3uthWKVHjcMW+n4m0RZBh4/snhHHlnxaIJzm4lB/s +DKNcXJTJHUbd1Kch5aOuSXCCmltwpEdEM9yaY1mr+jH9aD7lfo3FEJQxpO6M+AH6 +JDdmS2LzQUSXDO4fibegrI/IeTQeST92mZI4foLxqp6SG19WGs9sNFFDYCIl6lNq +LDAhZycGntLtGaZF + + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_512.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_512.tmpl new file mode 100644 index 00000000..c5fe35e2 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_512.tmpl @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + TestKeyName-rsa-4096 + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_512.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_512.xml new file mode 100644 index 00000000..c7d1b273 --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha3_512.xml @@ -0,0 +1,122 @@ + + + + + + + + wJcHmvGU4UsasvF9P/LSqERhxxtzgbUauhYITSZfTk9+wMjCaEjnLlboZ2deHwL/ +YdUiamQ0koSBvhd8zb+Rsw== + + + JGPePi4CmNzC1X+uGQNCT99/VpIXb9+YRmVXoh2I/rakwW06Coe841d0fCSpk8k5 +GyYIJwuLDeb99Fd5ls40YdQf3JVZOAhzkujijOHL7GXvvmj4044fDfRZGjZuMsQn +A+0VAGNv2RL9k2tZaElt6PJn/BNa0MUcEV4mas8TTPk1DULe1LBf6rmdgpJxg/LY +VfOFY9WxkgI5E55KgoCDMOy5cRSUdeNYzsSSVAW8h7J7H5FAXxIZ0jYoEE9FLZ+L +R6ChI1KWOExczt1x5ceBdEhzU4j5hShIFfUKypRnDlyojFR02H8uImL3Rpk9aSrG +RmCpQEEgvgm4bA9d2FBln5cC4qs8nNeb/RrlANdsa+/JbJ85tN71GPBF4yAj47Bh +WQLMbwl7KIM9a/tPVMT0emVXw7HwtnjVcSZlH/4YwpIlKOdzVR6bTZi7GZocSiSb +nFa3IPU6/81CNT8uojPEYS3S8N4TjdlkzAf7rlAfNP/Pk7BofgeH430mndLZwaMH +20dkr6dzOCmd+camQo5HpZXear2ncjpwgUyzfI3C6GZjTD5Te2Qp7tU/QozXS4is +SzgbPkushE7fpbsfIdM2G/nnN9odoV7sN2GTUQ4k+atP65AypOrKrLOk5bKbihtl +q95mh/tCaewxuZ89KiS2fWbh6v/kv5Tkza+vBKbp5PM= + + TestKeyName-rsa-4096 + +MIIGFjCCBP6gAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT1QwDQYJKoZIhvcNAQEL +BQAwgbYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRgwFgYDVQQLEw9TZWNvbmQgbGV2ZWwgQ0ExFjAUBgNVBAMTDUFsZWtz +ZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTAgFw0y +NjAzMDgyMjE0MjdaGA8yMTI2MDIxMjIyMTQyN1owfTELMAkGA1UEBhMCVVMxEzAR +BgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJyYXJ5 +IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxGjAYBgNVBAMTEVRlc3Qg +S2V5IHJzYS00MDk2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApFht +8oSsDMTV1GOWqg7o7NVllW2835GtOiLPJ/dnRy9vEQGYqB+KSSX9axIVyrFNfiS6 +SsH7Tam9A4bEHSBP6risPS9wyoTpyy7q2a31ZUETmI0pFej9db2vgAvpmx8DX3e8 +Y03SecMYqNLr2HLj7daWhu9/OY+xrd6q567NLFmG3335Hr8wHNwl/HbdCwmXBWaw +16D1g1RSV0kkFvD1gHMZqAjANJsqmuKJogMj2waXFAy/KAsUK3cPDCDKu7KHxtAT +LZ0UWqPNgz8GLBPI87vmyxSGgbtw1XQWQa4zxdknz80qRGExROc8DMszs575N7+Z +vjSusT+PT+CQxmDSyiqtp/v2OIQS3zAR7uFv0Xb3DS5Cs0VWkGU/N0mrdU1nd4WB +ecdTZCXbG959r1HKtqiWKa7nOOxKTrwHr9cDrlzSW2kyXb/1tvdEE5gy1HNOil07 +SVUv4Vi6CRvUa3Jv/B6ifb0lY9wp82gc42TOLv9Udx9xm7Barh8lfzqc4T+VR1ON +jbHzeLyMC6aG54rZZpcorUOT7f6SfPHcbx2Jmz3T4g3UaML4nlJkBfpBSkBRloRp +dKffhnpyru5OQEb7fLxlDePEAOkYrTNbBaHEXFqO1gKSxz3Mg+4gCA9mZOXP9yLC +Dz10S9vROUVSu9H4CT4ucUPT2cEg95X5H/2fqRMCAwEAAaOCAVAwggFMMAwGA1Ud +EwQFMAMBAf8wLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp +ZmljYXRlMB0GA1UdDgQWBBTrTMwsoJ/NDeqdcDMAHNE2l2BDxDCB7gYDVR0jBIHm +MIHjgBTRfResRUKKjvmwFyXVPHKYnYg6JaGBtKSBsTCBrjELMAkGA1UEBhMCVVMx +EzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJy +YXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxEDAOBgNVBAsTB1Jv +b3QgQ0ExFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnht +bHNlY0BhbGVrc2V5LmNvbYIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcN +AQELBQADggEBAIlPInAPcM4cRhUqeRmWcwi4Ue5xkn5UL8hNPKsfbNDvRoa3aOKz +jc0WNd7LQZJzALP4Q+VoE9+TDYbM0fwIGpUr0RMcNUt1DzwVKyDKtbv/tOayIS2j +L8pI9AALHzjGdRjk713LuOd1ixwvEyaVBJtQ+vz39c3baSJQtSvXeVU0KLxJSqy8 +fgbBuiNx+hZiGsee9BzocAyCoSyKuyEqhxbvcBSDIIgLyCoroR/uXk+wsBgy/15X +QGa1GHVWwSLdaqACDlqvu5PYMMQq4IfY+fADf3tYl81ZiIJerRcHwZMa2zgof/lZ +0tzrqr9lKyHcVitF2kkwC50xi2hvkDrZhvI= + +MIIFEjCCA/qgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT04wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NDQ3WhgPMjEyNjAyMTIyMjA0NDdaMIGuMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEQMA4GA1UECxMHUm9vdCBDQTEWMBQG +A1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtz +ZXkuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtbKBr4EAoOm8 +zAW/RL8Wrd1+24EPUbz1RYQuSlcuHcyBwt3uGXVvXNQ6fCGLq5ikIi3NkMymecIB +9u1Jc96T0FkpSxQrqIIvlCP6gpaLBa+lz8ix8Xeb0uJ4Dg8RDmwTBfQU2ENagYLc +v0mpW7myAmqzGq1+xdgd2Cbt1FRB5t4YKqNl6+pFbeXL9EGbRoNPyuu+CfWrWVEe +JfWD1YzM6fhB0c/zqCxC32Y1h/sAzNFyYRmYUULh2MwVBVyt839h0jAUBzzBh0/q +EoVL5a9daDx3m6+PS1ACb+nXUSYaOu8lVM2rPxRjVITHBo+NHn012T8JNrwcExMn +FgeaVXo+NwIDAQABo4IBIjCCAR4wHQYDVR0OBBYEFDN5WuQBQ05geQStksygwwDM +bhBEMIHuBgNVHSMEgeYwgeOAFDN5WuQBQ05geQStksygwwDMbhBEoYG0pIGxMIGu +MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1M +IFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2Vj +KTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8G +CSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tghR3Ne5If2hi2vGzlW2WHMsP +pvNPTjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBVUqxGkYxvFZ7s +/Zkmjj1u88PvOjdj36LnGQCyVDwJPXXAXoqW9I3W3BPra/Xy1vjFo5erkdjvNh0f ++iyZVS/9EVdPKssPdZd39p0YIiUyG1RUYmN/IBDzSX/LwBTiLGlMBHFTRj6Lfs+e +Nfu6PISqABh+It3/3jlB882eixesdsjvtZc0J6sDka1byMoqe40twfI0tTMMv4Jr +QwGn7YeiVuWZ/GKUQxYrA+FfIWR5maBWtnhdmjaOBgmUhNtJB8yBcH82cRrxRIMX +f2quQrB3P4/WQC2bw3YPGxSv5wQoZwcwCn6f7g7oQFy6cANONMBG7GJpbw5B/8uB +S1a6d6Rg + +MIIFSDCCBDCgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NzQyWhgPMjEyNjAyMTIyMjA3NDJaMIG2MQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEYMBYGA1UECxMPU2Vjb25kIGxldmVs +IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxz +ZWNAYWxla3NleS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDw +fEPVxQD3TLiNRpoh7g1KRYODmnJcdJzi7FMXfKuAgkhNmQaoAHQd7/pcwtg3oNUH +QukupST89AC7/qakF7ykdEQnVzxggYgdXbhfDZhLcaVUuMtFGgM6lHL0hnSZo8U9 +LHKWOlPIhJemE/XziHqgAsQposis7IRhuUlSsDa2xFW7MfS2xF/+UhiclaHgyBZ/ +RDzn2b5K14VAJdt1xRaoMC5zVIzu1uk33+j97L78+z65VRG7fxGTau2c94Mcl2V+ +KjDulHAnxLVJkjczo0mVi+u0Vczq9VhUqbNlig9TERQAPBC3D4ZJHhJsBmJz+47i +7pNL/Pms8qr9U0PgbZaPAgMBAAGjggFQMIIBTDAMBgNVHRMEBTADAQH/MCwGCWCG +SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E +FgQU0X0XrEVCio75sBcl1TxymJ2IOiUwge4GA1UdIwSB5jCB44AUM3la5AFDTmB5 +BK2SzKDDAMxuEEShgbSkgbEwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxp +Zm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3 +dy5hbGVrc2V5LmNvbS94bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQD +Ew1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5j +b22CFHc17kh/aGLa8bOVbZYcyw+m809OMA0GCSqGSIb3DQEBCwUAA4IBAQAhrm/J +FdnYclb8HwQJdgGSYtUw2Wdrl1950H/ZUGwSKs6lGX8YT5xnj55AELLhbetTo+Be +Wwmg9kZbqnRC9tt0vIhFMko/uQZkn7vzrFEIfXgnEm2UGkkULfXH9pgtO4A9EQ2s +bbR4Oyi3n9q1w39aBdkUZnw3uthWKVHjcMW+n4m0RZBh4/snhHHlnxaIJzm4lB/s +DKNcXJTJHUbd1Kch5aOuSXCCmltwpEdEM9yaY1mr+jH9aD7lfo3FEJQxpO6M+AH6 +JDdmS2LzQUSXDO4fibegrI/IeTQeST92mZI4foLxqp6SG19WGs9sNFFDYCIl6lNq +LDAhZycGntLtGaZF + + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha512.tmpl b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha512.tmpl new file mode 100644 index 00000000..0062822d --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha512.tmpl @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + TestKeyName-rsa-4096 + + + some text + diff --git a/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha512.xml b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha512.xml new file mode 100644 index 00000000..65d0cccd --- /dev/null +++ b/tests/fixtures/xmldsig/aleksey-xmldsig-01/enveloping-rsa-pss-sha512.xml @@ -0,0 +1,122 @@ + + + + + + + + E2Jo801uUCgAIa65niLU7jPSWPWUbsgT+okPgBcw/h72V7bmI0J2faJ+8EbwVwah +XDnbRaf22WqerzX1vL0QzA== + + + Mga4B6OlT4eVMplXEAh9yFnUO2Tx6D67KZKfi1RwzIXLsNWRqMzNLwmRMQwBh+3K +7jChXcWHj+AEcEGEDlEcql+fFYrFe7ZJxGCxRswwRA4TsIGj2gXPKy5+4R3nyBJj +946P8Dd3PwfTqelxrPLNNpg8syOaJQ4UDcJflhsAKq4e9ht+qcCW6SLftZR7m3PZ +ero0hRyMFsqK4y1jP4rwOLtNuoNq0N73tm8PbV8d1lAiO7r0/QDzGYBBXGWZZRwe +g7BmZ69tUZ3sD6asovYJTI1UUaUkORuHIUjhFjYs+DV1CDtdrBkncwYhn2tYrQV/ +ko3XephUX+HAt3nFvN+xlTwMxz+wpi8V1vG92IB6HXBue0M0vCu9ExqnEG4UHVZP +OzQtGEta+he89Y1YadGqvFxO72qNXy74BZZ7dEm5L44go03b4CLFUfx/B9SRwgmU +mis2AagYOT0Zmp8y232xq+3Z80G74ITEfU2QsK1zbBfbnmTidK5Os1XZBIy+v+7b +NFj6D3NYRpktwEhZ+OZCKH1z7gDzSk9VWRyVAYDuNLumW7CFjBqBIYF9Bki3JOJw +YA0fKAC/hlNfi2RCpFNqjblRhG1kGXPb4tt3tINKG2v3+GPCp/ptg5Gdza7ivyXF +pEJpmfGSTHizYd94qzKzmhFSNEsH25u9cqZ+7CRc/rE= + + TestKeyName-rsa-4096 + +MIIGFjCCBP6gAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT1QwDQYJKoZIhvcNAQEL +BQAwgbYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRgwFgYDVQQLEw9TZWNvbmQgbGV2ZWwgQ0ExFjAUBgNVBAMTDUFsZWtz +ZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnhtbHNlY0BhbGVrc2V5LmNvbTAgFw0y +NjAzMDgyMjE0MjdaGA8yMTI2MDIxMjIyMTQyN1owfTELMAkGA1UEBhMCVVMxEzAR +BgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJyYXJ5 +IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxGjAYBgNVBAMTEVRlc3Qg +S2V5IHJzYS00MDk2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApFht +8oSsDMTV1GOWqg7o7NVllW2835GtOiLPJ/dnRy9vEQGYqB+KSSX9axIVyrFNfiS6 +SsH7Tam9A4bEHSBP6risPS9wyoTpyy7q2a31ZUETmI0pFej9db2vgAvpmx8DX3e8 +Y03SecMYqNLr2HLj7daWhu9/OY+xrd6q567NLFmG3335Hr8wHNwl/HbdCwmXBWaw +16D1g1RSV0kkFvD1gHMZqAjANJsqmuKJogMj2waXFAy/KAsUK3cPDCDKu7KHxtAT +LZ0UWqPNgz8GLBPI87vmyxSGgbtw1XQWQa4zxdknz80qRGExROc8DMszs575N7+Z +vjSusT+PT+CQxmDSyiqtp/v2OIQS3zAR7uFv0Xb3DS5Cs0VWkGU/N0mrdU1nd4WB +ecdTZCXbG959r1HKtqiWKa7nOOxKTrwHr9cDrlzSW2kyXb/1tvdEE5gy1HNOil07 +SVUv4Vi6CRvUa3Jv/B6ifb0lY9wp82gc42TOLv9Udx9xm7Barh8lfzqc4T+VR1ON +jbHzeLyMC6aG54rZZpcorUOT7f6SfPHcbx2Jmz3T4g3UaML4nlJkBfpBSkBRloRp +dKffhnpyru5OQEb7fLxlDePEAOkYrTNbBaHEXFqO1gKSxz3Mg+4gCA9mZOXP9yLC +Dz10S9vROUVSu9H4CT4ucUPT2cEg95X5H/2fqRMCAwEAAaOCAVAwggFMMAwGA1Ud +EwQFMAMBAf8wLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRp +ZmljYXRlMB0GA1UdDgQWBBTrTMwsoJ/NDeqdcDMAHNE2l2BDxDCB7gYDVR0jBIHm +MIHjgBTRfResRUKKjvmwFyXVPHKYnYg6JaGBtKSBsTCBrjELMAkGA1UEBhMCVVMx +EzARBgNVBAgTCkNhbGlmb3JuaWExPTA7BgNVBAoTNFhNTCBTZWN1cml0eSBMaWJy +YXJ5IChodHRwOi8vd3d3LmFsZWtzZXkuY29tL3htbHNlYykxEDAOBgNVBAsTB1Jv +b3QgQ0ExFjAUBgNVBAMTDUFsZWtzZXkgU2FuaW4xITAfBgkqhkiG9w0BCQEWEnht +bHNlY0BhbGVrc2V5LmNvbYIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcN +AQELBQADggEBAIlPInAPcM4cRhUqeRmWcwi4Ue5xkn5UL8hNPKsfbNDvRoa3aOKz +jc0WNd7LQZJzALP4Q+VoE9+TDYbM0fwIGpUr0RMcNUt1DzwVKyDKtbv/tOayIS2j +L8pI9AALHzjGdRjk713LuOd1ixwvEyaVBJtQ+vz39c3baSJQtSvXeVU0KLxJSqy8 +fgbBuiNx+hZiGsee9BzocAyCoSyKuyEqhxbvcBSDIIgLyCoroR/uXk+wsBgy/15X +QGa1GHVWwSLdaqACDlqvu5PYMMQq4IfY+fADf3tYl81ZiIJerRcHwZMa2zgof/lZ +0tzrqr9lKyHcVitF2kkwC50xi2hvkDrZhvI= + +MIIFEjCCA/qgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT04wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NDQ3WhgPMjEyNjAyMTIyMjA0NDdaMIGuMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEQMA4GA1UECxMHUm9vdCBDQTEWMBQG +A1UEAxMNQWxla3NleSBTYW5pbjEhMB8GCSqGSIb3DQEJARYSeG1sc2VjQGFsZWtz +ZXkuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtbKBr4EAoOm8 +zAW/RL8Wrd1+24EPUbz1RYQuSlcuHcyBwt3uGXVvXNQ6fCGLq5ikIi3NkMymecIB +9u1Jc96T0FkpSxQrqIIvlCP6gpaLBa+lz8ix8Xeb0uJ4Dg8RDmwTBfQU2ENagYLc +v0mpW7myAmqzGq1+xdgd2Cbt1FRB5t4YKqNl6+pFbeXL9EGbRoNPyuu+CfWrWVEe +JfWD1YzM6fhB0c/zqCxC32Y1h/sAzNFyYRmYUULh2MwVBVyt839h0jAUBzzBh0/q +EoVL5a9daDx3m6+PS1ACb+nXUSYaOu8lVM2rPxRjVITHBo+NHn012T8JNrwcExMn +FgeaVXo+NwIDAQABo4IBIjCCAR4wHQYDVR0OBBYEFDN5WuQBQ05geQStksygwwDM +bhBEMIHuBgNVHSMEgeYwgeOAFDN5WuQBQ05geQStksygwwDMbhBEoYG0pIGxMIGu +MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTE9MDsGA1UEChM0WE1M +IFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6Ly93d3cuYWxla3NleS5jb20veG1sc2Vj +KTEQMA4GA1UECxMHUm9vdCBDQTEWMBQGA1UEAxMNQWxla3NleSBTYW5pbjEhMB8G +CSqGSIb3DQEJARYSeG1sc2VjQGFsZWtzZXkuY29tghR3Ne5If2hi2vGzlW2WHMsP +pvNPTjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBVUqxGkYxvFZ7s +/Zkmjj1u88PvOjdj36LnGQCyVDwJPXXAXoqW9I3W3BPra/Xy1vjFo5erkdjvNh0f ++iyZVS/9EVdPKssPdZd39p0YIiUyG1RUYmN/IBDzSX/LwBTiLGlMBHFTRj6Lfs+e +Nfu6PISqABh+It3/3jlB882eixesdsjvtZc0J6sDka1byMoqe40twfI0tTMMv4Jr +QwGn7YeiVuWZ/GKUQxYrA+FfIWR5maBWtnhdmjaOBgmUhNtJB8yBcH82cRrxRIMX +f2quQrB3P4/WQC2bw3YPGxSv5wQoZwcwCn6f7g7oQFy6cANONMBG7GJpbw5B/8uB +S1a6d6Rg + +MIIFSDCCBDCgAwIBAgIUdzXuSH9oYtrxs5VtlhzLD6bzT08wDQYJKoZIhvcNAQEL +BQAwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMT0wOwYDVQQK +EzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3dy5hbGVrc2V5LmNvbS94 +bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmlu +MSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5jb20wIBcNMjYwMzA4MjIw +NzQyWhgPMjEyNjAyMTIyMjA3NDJaMIG2MQswCQYDVQQGEwJVUzETMBEGA1UECBMK +Q2FsaWZvcm5pYTE9MDsGA1UEChM0WE1MIFNlY3VyaXR5IExpYnJhcnkgKGh0dHA6 +Ly93d3cuYWxla3NleS5jb20veG1sc2VjKTEYMBYGA1UECxMPU2Vjb25kIGxldmVs +IENBMRYwFAYDVQQDEw1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxz +ZWNAYWxla3NleS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDw +fEPVxQD3TLiNRpoh7g1KRYODmnJcdJzi7FMXfKuAgkhNmQaoAHQd7/pcwtg3oNUH +QukupST89AC7/qakF7ykdEQnVzxggYgdXbhfDZhLcaVUuMtFGgM6lHL0hnSZo8U9 +LHKWOlPIhJemE/XziHqgAsQposis7IRhuUlSsDa2xFW7MfS2xF/+UhiclaHgyBZ/ +RDzn2b5K14VAJdt1xRaoMC5zVIzu1uk33+j97L78+z65VRG7fxGTau2c94Mcl2V+ +KjDulHAnxLVJkjczo0mVi+u0Vczq9VhUqbNlig9TERQAPBC3D4ZJHhJsBmJz+47i +7pNL/Pms8qr9U0PgbZaPAgMBAAGjggFQMIIBTDAMBgNVHRMEBTADAQH/MCwGCWCG +SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E +FgQU0X0XrEVCio75sBcl1TxymJ2IOiUwge4GA1UdIwSB5jCB44AUM3la5AFDTmB5 +BK2SzKDDAMxuEEShgbSkgbEwga4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxp +Zm9ybmlhMT0wOwYDVQQKEzRYTUwgU2VjdXJpdHkgTGlicmFyeSAoaHR0cDovL3d3 +dy5hbGVrc2V5LmNvbS94bWxzZWMpMRAwDgYDVQQLEwdSb290IENBMRYwFAYDVQQD +Ew1BbGVrc2V5IFNhbmluMSEwHwYJKoZIhvcNAQkBFhJ4bWxzZWNAYWxla3NleS5j +b22CFHc17kh/aGLa8bOVbZYcyw+m809OMA0GCSqGSIb3DQEBCwUAA4IBAQAhrm/J +FdnYclb8HwQJdgGSYtUw2Wdrl1950H/ZUGwSKs6lGX8YT5xnj55AELLhbetTo+Be +Wwmg9kZbqnRC9tt0vIhFMko/uQZkn7vzrFEIfXgnEm2UGkkULfXH9pgtO4A9EQ2s +bbR4Oyi3n9q1w39aBdkUZnw3uthWKVHjcMW+n4m0RZBh4/snhHHlnxaIJzm4lB/s +DKNcXJTJHUbd1Kch5aOuSXCCmltwpEdEM9yaY1mr+jH9aD7lfo3FEJQxpO6M+AH6 +JDdmS2LzQUSXDO4fibegrI/IeTQeST92mZI4foLxqp6SG19WGs9sNFFDYCIl6lNq +LDAhZycGntLtGaZF + + + + some text + diff --git a/tests/fixtures_smoke.rs b/tests/fixtures_smoke.rs index 28adf0c0..7b6b627e 100644 --- a/tests/fixtures_smoke.rs +++ b/tests/fixtures_smoke.rs @@ -198,7 +198,8 @@ fn fixture_file_count_matches_expected() { // Complete modern donor key directories add 11 files for each of // two EdDSA, three ML-DSA, and six SLH-DSA parameter sets (121 total). // Five DSA inputs cover reciprocal 1024/2048/3072-bit signing. - ("xmldsig", 333), + // All 17 upstream PSS cases include both signed XML and its template. + ("xmldsig", 367), ("saml", 2), ("xmlenc", 485), ]; diff --git a/tests/pkcs11.rs b/tests/pkcs11.rs index 3088a2e3..6b253be6 100644 --- a/tests/pkcs11.rs +++ b/tests/pkcs11.rs @@ -107,6 +107,47 @@ fn isolated_token_operations_and_failures() { let private = Arc::new(provider.rsa_private_key(&[1]).unwrap()); let public = provider.rsa_public_key(&[1]).unwrap(); let message = b"opaque key operation"; + // PSS parameters reach the token unchanged, rather than a software fallback. + for salt_len in [0, 32] { + let algorithm = SignatureAlgorithm::RsaPss(xml_sec::xmldsig::RsaPssParameters { + digest: DigestAlgorithm::Sha256, + mgf_digest: DigestAlgorithm::Sha256, + salt_len, + }); + let signature = provider.sign(private.as_ref(), algorithm, message).unwrap(); + assert!( + provider + .verify(&public, algorithm, message, &signature) + .unwrap() + ); + assert!( + !provider + .verify(&public, algorithm, b"changed", &signature) + .unwrap() + ); + let wrong = SignatureAlgorithm::RsaPss(xml_sec::xmldsig::RsaPssParameters { + digest: DigestAlgorithm::Sha256, + mgf_digest: DigestAlgorithm::Sha256, + salt_len: if salt_len == 0 { 32 } else { 0 }, + }); + assert!( + !provider + .verify(&public, wrong, message, &signature) + .unwrap() + ); + } + // SoftHSM rejects a different MGF hash: propagate the token failure and + // never silently sign with matching hashes or a software-held key. + let unsupported_tuple = SignatureAlgorithm::RsaPss(xml_sec::xmldsig::RsaPssParameters { + digest: DigestAlgorithm::Sha256, + mgf_digest: DigestAlgorithm::Sha384, + salt_len: 32, + }); + assert!( + provider + .sign(private.as_ref(), unsupported_tuple, message) + .is_err() + ); let signature = provider .sign(private.as_ref(), SignatureAlgorithm::RsaSha256, message) .unwrap(); diff --git a/tests/rsa_pss.rs b/tests/rsa_pss.rs new file mode 100644 index 00000000..d11ba3f6 --- /dev/null +++ b/tests/rsa_pss.rs @@ -0,0 +1,895 @@ +#![cfg(feature = "xmldsig")] + +//! RSA-PSS public pipeline, parameter grammar and independent primitive coverage. + +use rand_chacha::{ChaCha8Rng, rand_core::SeedableRng as _}; +use rsa::{pkcs8::DecodePrivateKey as _, traits::PublicKeyParts as _}; +use sha2::Digest as _; +use xml_sec::{ + XmlDomDocument, + c14n::{C14nAlgorithm, C14nMode}, + provider::{CryptoProvider, RustCryptoProvider}, + xmldsig::{ + DigestAlgorithm, DsigStatus, KeyValueInfoWriter, ReferenceBuilder, RsaPssParameters, + RsaSigningKey, SignContext, SignatureAlgorithm, SignatureBuilder, SigningKey, + find_signature_node, signature::verify_rsa_signature_pem, + }, +}; + +#[path = "support/cryptographic.rs"] +mod cryptographic; + +#[path = "common/xmlsec1.rs"] +mod xmlsec1; + +const PRIVATE: &str = include_str!("fixtures/keys/rsa/rsa-2048-key.pem"); +const PUBLIC: &str = include_str!("fixtures/keys/rsa/rsa-2048-pubkey.pem"); +const DS: &str = "http://www.w3.org/2000/09/xmldsig#"; +const PSS: &str = "http://www.w3.org/2007/05/xmldsig-more#"; + +fn parse_method(children: &str) -> Result { + let xml = format!( + r#"{children}"# + ); + let doc = XmlDomDocument::parse(&xml).expect("well-formed parameter test XML"); + let signed_info = find_signature_node(&doc) + .expect("Signature") + .first_element_child() + .expect("SignedInfo"); + xml_sec::xmldsig::parse::parse_signature_method( + signed_info + .children() + .find(|child| child.has_tag_name((DS, "SignatureMethod"))) + .unwrap(), + &xml_sec::policy::ResourcePolicy::default(), + ) + .map(|(method, _, _)| method) +} + +#[test] +fn pss_xs_int_accepts_negative_zero() { + // xs:int permits -0; the nonnegative salt value is zero, not a negative length. + let method = parse_method(&format!( + r#" -0 "# + )) + .expect("negative zero is zero"); + assert_eq!( + method, + SignatureAlgorithm::RsaPss(RsaPssParameters { + salt_len: 0, + ..RsaPssParameters::DEFAULT + }) + ); +} + +#[test] +fn pss_defaults_and_order_are_strict() { + // XML defaults are SHA-256, matching MGF1, digest-sized salt and trailer 1. + assert_eq!( + parse_method("").unwrap(), + SignatureAlgorithm::RsaPss(RsaPssParameters::DEFAULT) + ); + let digest = format!( + r#""# + ); + assert_eq!( + parse_method(&format!( + r#"{digest}"# + )) + .unwrap(), + SignatureAlgorithm::RsaPss(RsaPssParameters { + digest: DigestAlgorithm::Sha512, + mgf_digest: DigestAlgorithm::Sha512, + salt_len: 64 + }) + ); + assert_eq!( + parse_method(&format!( + r#"{digest}"# + )) + .unwrap(), + SignatureAlgorithm::RsaPss(RsaPssParameters { + digest: DigestAlgorithm::Sha512, + mgf_digest: DigestAlgorithm::Sha256, + salt_len: 64 + }) + ); + for children in [ + "-1", + "2147483648", + "1 2", + "+", + "2", + "00", + "10", + "", + "", + ] { + assert!( + parse_method(&format!( + r#"{children}"# + )) + .is_err(), + "{children}" + ); + } +} + +#[test] +fn pss_legacy_hash_permission_covers_message_and_mgf() { + // Capability is not permission: SHA-1 must be explicitly allowed even if + // it occurs only inside MGF1, and permission names the exact PSS tuple. + for parameters in [ + RsaPssParameters { + digest: DigestAlgorithm::Sha1, + ..RsaPssParameters::DEFAULT + }, + RsaPssParameters { + mgf_digest: DigestAlgorithm::Sha1, + ..RsaPssParameters::DEFAULT + }, + ] { + let method = SignatureAlgorithm::RsaPss(parameters); + let mut policy = xml_sec::policy::VerificationPolicy::default(); + assert!(policy.check_signature_algorithm(method).is_err()); + policy + .key_trust + .allowed_legacy_signature_algorithms + .insert(SignatureAlgorithm::RsaPssSha1); + assert!(policy.check_signature_algorithm(method).is_err()); + policy + .key_trust + .allowed_legacy_signature_algorithms + .insert(method); + assert!(policy.check_signature_algorithm(method).is_ok()); + } +} + +#[test] +fn pss_family_permission_preserves_independent_legacy_gate() { + // A family permission is chosen before XML input; it must not grant legacy trust. + let method = SignatureAlgorithm::RsaPss(RsaPssParameters { + mgf_digest: DigestAlgorithm::Sha1, + salt_len: 17, + ..RsaPssParameters::DEFAULT + }); + let mut policy = xml_sec::policy::VerificationPolicy::default(); + policy.parameterized_rsa_pss = xml_sec::policy::RsaPssPermission::AllSupported; + assert!(policy.check_signature_algorithm(method).is_err()); + policy.key_trust.parameterized_rsa_pss = xml_sec::policy::RsaPssPermission::AllSupported; + assert!(policy.check_signature_algorithm(method).is_ok()); + policy.signature_algorithms = Some(Default::default()); + assert!(policy.check_signature_algorithm(method).is_ok()); + policy.parameterized_rsa_pss = xml_sec::policy::RsaPssPermission::ExactOnly; + assert!(policy.check_signature_algorithm(method).is_err()); + let key = RsaSigningKey::from_pkcs8_pem(PRIVATE).unwrap(); + let builder = SignatureBuilder::new(C14nAlgorithm::new(C14nMode::Exclusive1_0, false), method) + .add_reference( + ReferenceBuilder::new(DigestAlgorithm::Sha256) + .uri("") + .transform(xml_sec::xmldsig::Transform::Enveloped), + ); + assert!(matches!( + SignContext::new(&key).sign_with_builder("", &builder), + Err(xml_sec::xmldsig::SigningError::Policy( + xml_sec::policy::PolicyViolation::Algorithm { .. } + )) + )); + let signing = xml_sec::policy::SigningPolicy { + parameterized_rsa_pss: xml_sec::policy::RsaPssPermission::AllSupported, + signature_algorithms: Some(Default::default()), + ..Default::default() + }; + let signed = SignContext::new(&key) + .policy(signing) + .sign_with_builder("", &builder) + .unwrap(); + policy.parameterized_rsa_pss = xml_sec::policy::RsaPssPermission::AllSupported; + let verification = xml_sec::xmldsig::VerificationKey { + algorithm: method, + public_key_bytes: pem::parse(PUBLIC).unwrap().into_contents(), + certificate_der: None, + name: None, + }; + let result = xml_sec::xmldsig::VerifyContext::new() + .policy(policy) + .key(&verification) + .verify(&signed) + .unwrap(); + assert_eq!(result.status, DsigStatus::Valid); +} + +#[test] +fn pss_signatures_cross_verify_with_dependency() { + // Independent sad-rsa padding checks our PSS implementation in both directions. + let private = rsa::RsaPrivateKey::from_pkcs8_pem(PRIVATE).unwrap(); + let public = rsa::RsaPublicKey::from(&private); + let key = RsaSigningKey::from_pkcs8_pem(PRIVATE).unwrap(); + for salt_len in [0, 1, 32, 222] { + let method = SignatureAlgorithm::RsaPss(RsaPssParameters { + salt_len, + ..RsaPssParameters::DEFAULT + }); + let signature = RustCryptoProvider + .sign(&key, method, b"PSS message") + .unwrap(); + public + .verify( + rsa::Pss::::new_with_salt(salt_len), + &sha2::Sha256::digest(b"PSS message"), + &signature, + ) + .unwrap(); + let signature = private + .sign_with_rng( + &mut ChaCha8Rng::seed_from_u64(17), + rsa::Pss::::new_with_salt(salt_len), + &sha2::Sha256::digest(b"PSS message"), + ) + .unwrap(); + assert!(verify_rsa_signature_pem(method, PUBLIC, b"PSS message", &signature).unwrap()); + assert!(!verify_rsa_signature_pem(method, PUBLIC, b"tampered", &signature).unwrap()); + let wrong_salt = SignatureAlgorithm::RsaPss(RsaPssParameters { + salt_len: if salt_len == 0 { 1 } else { 0 }, + ..RsaPssParameters::DEFAULT + }); + assert!(!verify_rsa_signature_pem(wrong_salt, PUBLIC, b"PSS message", &signature).unwrap()); + } + assert_eq!(public.size(), 256); +} + +#[test] +fn pss_rejects_modular_alias_of_valid_signature() { + // RSAVP1 must reject s+n, even when it fits the signature width and + // modular exponentiation would recover exactly the valid encoded message. + let private = rsa::RsaPrivateKey::from_pkcs8_pem(PRIVATE).unwrap(); + let public = rsa::RsaPublicKey::from(&private); + let modulus = public.n().to_be_bytes(); + let method = SignatureAlgorithm::RsaPss(RsaPssParameters { + salt_len: 0, + ..RsaPssParameters::DEFAULT + }); + let key = RsaSigningKey::from_pkcs8_pem(PRIVATE).unwrap(); + for counter in 0u32..128 { + let message = counter.to_be_bytes(); + let signature = key.sign(method, &message).unwrap(); + let mut alias = signature.clone(); + let mut carry = 0u16; + for (byte, modulus_byte) in alias.iter_mut().zip(modulus.iter()).rev() { + let sum = u16::from(*byte) + u16::from(*modulus_byte) + carry; + *byte = sum as u8; + carry = sum >> 8; + } + if carry != 0 { + continue; + } + assert!(verify_rsa_signature_pem(method, PUBLIC, &message, &signature).unwrap()); + assert!(!verify_rsa_signature_pem(method, PUBLIC, &message, &alias).unwrap()); + return; + } + panic!("test key did not produce a modulus-width alias"); +} + +#[test] +fn pss_rejects_malformed_encoded_messages_and_modulus_boundary() { + // RFC 8017 section 9.1.2 requires trailer, high bits, zero padding, + // separator and hash to agree; raw RSA gives independent malformed EMs. + let private = rsa::RsaPrivateKey::from_pkcs8_pem(PRIVATE).unwrap(); + let public = rsa::RsaPublicKey::from(&private); + let key = RsaSigningKey::from_pkcs8_pem(PRIVATE).unwrap(); + let algorithm = SignatureAlgorithm::RsaPssSha256; + let signature = key.sign(algorithm, b"padding").unwrap(); + let value = + crypto_bigint::BoxedUint::from_be_slice(&signature, public.n_bits_precision()).unwrap(); + let encoded = rsa::hazmat::rsa_encrypt(&public, &value) + .unwrap() + .to_be_bytes(); + for index in [0, 1, 200, 223, 255] { + let mut invalid = encoded.to_vec(); + if index == 0 { + invalid[index] = 0x80; + } else { + invalid[index] ^= 1; + } + let value = + crypto_bigint::BoxedUint::from_be_slice(&invalid, private.n_bits_precision()).unwrap(); + let signature = rsa::hazmat::rsa_decrypt_and_check( + &private, + Some(&mut ChaCha8Rng::seed_from_u64(3)), + &value, + ) + .unwrap() + .to_be_bytes(); + assert!( + !verify_rsa_signature_pem(algorithm, PUBLIC, b"padding", &signature).unwrap(), + "offset {index}" + ); + } + assert!(!verify_rsa_signature_pem(algorithm, PUBLIC, b"padding", &signature[..255]).unwrap()); + assert!( + !verify_rsa_signature_pem(algorithm, PUBLIC, b"padding", &public.n().to_be_bytes()) + .unwrap() + ); + let oversized = SignatureAlgorithm::RsaPss(RsaPssParameters { + salt_len: 223, + ..RsaPssParameters::DEFAULT + }); + assert!(key.sign(oversized, b"padding").is_err()); +} + +#[test] +fn pss_non_byte_aligned_modulus_preserves_representative_width() { + // For modBits == 1 mod 8, emLen is one octet smaller than the signature: + // RFC 8017 section 8.1.2 must reject a nonzero discarded leading octet. + use rsa::pkcs8::EncodePublicKey as _; + let private = rsa::RsaPrivateKey::new(&mut ChaCha8Rng::seed_from_u64(2049), 2049).unwrap(); + let public = rsa::RsaPublicKey::from(&private); + let method = SignatureAlgorithm::RsaPssSha256; + let signature = private + .sign_with_rng( + &mut ChaCha8Rng::seed_from_u64(6), + rsa::Pss::::new(), + &sha2::Sha256::digest(b"odd modulus"), + ) + .unwrap(); + let spki = public.to_public_key_der().unwrap(); + assert_eq!(signature.len(), 257); + assert!( + xml_sec::xmldsig::signature::verify_rsa_signature_spki( + method, + spki.as_bytes(), + b"odd modulus", + &signature + ) + .unwrap() + ); + let invalid = private.n().as_ref() + - &crypto_bigint::BoxedUint::one_with_precision(private.n_bits_precision()); + let signature = rsa::hazmat::rsa_decrypt_and_check( + &private, + Some(&mut ChaCha8Rng::seed_from_u64(5)), + &invalid, + ) + .unwrap() + .to_be_bytes(); + assert!( + !xml_sec::xmldsig::signature::verify_rsa_signature_spki( + method, + spki.as_bytes(), + b"odd modulus", + &signature + ) + .unwrap() + ); +} + +#[test] +fn pss_public_sign_and_verify_all_secure_methods() { + // All fixed secure URI variants and parameterized independent MGF run through + // builder -> signing provider -> KeyInfo resolution -> verification provider. + let key = RsaSigningKey::from_pkcs8_pem(PRIVATE).unwrap(); + let c14n = C14nAlgorithm::new(C14nMode::Exclusive1_0, false); + for method in [ + SignatureAlgorithm::RsaPssSha224, + SignatureAlgorithm::RsaPssSha256, + SignatureAlgorithm::RsaPssSha384, + SignatureAlgorithm::RsaPssSha512, + SignatureAlgorithm::RsaPssSha3_224, + SignatureAlgorithm::RsaPssSha3_256, + SignatureAlgorithm::RsaPssSha3_384, + SignatureAlgorithm::RsaPssSha3_512, + SignatureAlgorithm::RsaPss(RsaPssParameters { + digest: DigestAlgorithm::Sha512, + mgf_digest: DigestAlgorithm::Sha256, + salt_len: 0, + }), + ] { + let builder = SignatureBuilder::new(c14n.clone(), method) + .key_info(true) + .add_reference(ReferenceBuilder::new(DigestAlgorithm::Sha256).uri("#payload")); + let signed = SignContext::new(&key) + .key_info_writer(&KeyValueInfoWriter) + .sign_with_builder( + "value", + &builder, + ) + .unwrap(); + let resolver = xml_sec::xmldsig::DefaultKeyResolver::default(); + let result = cryptographic::context() + .key_resolver(&resolver) + .verify(&signed) + .unwrap(); + assert_eq!(result.status, DsigStatus::Valid, "{method:?}"); + } +} + +#[test] +fn pss_invalid_api_salt_is_not_a_provider_capability() { + // A caller-created parameter value cannot bypass XML's bounded integer contract. + let method = SignatureAlgorithm::RsaPss(RsaPssParameters { + salt_len: usize::MAX, + ..RsaPssParameters::DEFAULT + }); + assert!(!RustCryptoProvider.supports(xml_sec::provider::ProviderCapability::Sign(method))); + let key = RsaSigningKey::from_pkcs8_pem(PRIVATE).unwrap(); + assert!(key.sign(method, b"payload").is_err()); +} + +#[test] +fn pss_key_capacity_is_checked_before_signing_dispatch() { + // An oversized, but XML-representable salt must not invoke an opaque signer. + struct NeverSign(RsaSigningKey); + impl SigningKey for NeverSign { + fn sign( + &self, + _: SignatureAlgorithm, + _: &[u8], + ) -> Result, xml_sec::xmldsig::SigningKeyError> { + panic!("PSS capacity preflight must precede signing dispatch"); + } + fn public_key_info( + &self, + ) -> Result + { + self.0.public_key_info() + } + } + let key = NeverSign(RsaSigningKey::from_pkcs8_pem(PRIVATE).unwrap()); + let algorithm = SignatureAlgorithm::RsaPss(RsaPssParameters { + salt_len: 223, + ..RsaPssParameters::DEFAULT + }); + let builder = + SignatureBuilder::new(C14nAlgorithm::new(C14nMode::Exclusive1_0, false), algorithm) + .add_reference(ReferenceBuilder::new(DigestAlgorithm::Sha256).uri("")); + assert!( + SignContext::new(&key) + .sign_with_builder("", &builder) + .is_err() + ); +} + +#[test] +fn pss_restricted_spki_enforces_hashes_and_minimum_salt() { + // RFC 4055 section 3.3 permits a larger salt, but never another message + // hash/MGF hash or PKCS#1 v1.5 with a PSS-only public key. + use der::{Decode as _, Encode as _}; + use x509_cert::spki::{AlgorithmIdentifierOwned, ObjectIdentifier}; + let plain = pem::parse(PUBLIC).unwrap(); + let mut spki = x509_cert::SubjectPublicKeyInfo::from_der(plain.contents()).unwrap(); + let params = der::asn1::Any::from_der(&[ + 0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x01, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x20, + ]) + .unwrap(); + spki.algorithm = AlgorithmIdentifierOwned { + oid: ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10"), + parameters: Some(params), + }; + let encoded = spki.to_der().unwrap(); + let certificate = x509_cert::Certificate::from_der( + pem::parse(include_str!("fixtures/keys/rsa/rsa-2048-cert.pem")) + .unwrap() + .contents(), + ) + .unwrap(); + // This checks key extraction, not certificate-chain authentication. Replacing + // the SPKI OID keeps the RSA key while intentionally invalidating the issuer signature. + let old_spki = certificate + .tbs_certificate() + .subject_public_key_info() + .to_der() + .unwrap(); + let tbs = der::asn1::Any::from_der(&certificate.tbs_certificate().to_der().unwrap()).unwrap(); + let offset = tbs + .value() + .windows(old_spki.len()) + .position(|bytes| bytes == old_spki) + .unwrap(); + let mut tbs_bytes = tbs.value()[..offset].to_vec(); + tbs_bytes.extend_from_slice(&encoded); + tbs_bytes.extend_from_slice(&tbs.value()[offset + old_spki.len()..]); + let mut certificate_bytes = der::asn1::Any::new(der::Tag::Sequence, tbs_bytes) + .unwrap() + .to_der() + .unwrap(); + certificate_bytes.extend_from_slice(&certificate.signature_algorithm().to_der().unwrap()); + certificate_bytes.extend_from_slice(&certificate.signature().to_der().unwrap()); + let certificate = der::asn1::Any::new(der::Tag::Sequence, certificate_bytes).unwrap(); + use base64::Engine as _; + let certificate_info = format!( + "{}", + base64::engine::general_purpose::STANDARD.encode(certificate.to_der().unwrap()) + ); + let certificate_document = XmlDomDocument::parse(&certificate_info).unwrap(); + let certificate_info = + xml_sec::xmldsig::parse_key_info(certificate_document.root_element()).unwrap(); + let key = RsaSigningKey::from_pkcs8_pem(PRIVATE).unwrap(); + for salt_len in [32, 33] { + let method = SignatureAlgorithm::RsaPss(RsaPssParameters { + salt_len, + ..RsaPssParameters::DEFAULT + }); + let signature = key.sign(method, b"restricted").unwrap(); + let public = xml_sec::xmldsig::VerificationKey { + algorithm: method, + public_key_bytes: encoded.clone(), + certificate_der: None, + name: None, + }; + // Restricted SPKIs must survive both document and caller-store resolution, + // not merely the direct primitive verifier. + use xml_sec::xmldsig::{KeyInfo, KeyInfoSource, KeyResolver as _, KeyResolverConfig}; + let mut config = KeyResolverConfig::default(); + config + .named_keys + .insert("restricted".into(), public.clone()); + let resolver = xml_sec::xmldsig::DefaultKeyResolver::new(config); + for source in [ + KeyInfoSource::DerEncodedKeyValue(encoded.clone()), + KeyInfoSource::KeyName("restricted".into()), + certificate_info.sources[0].clone(), + ] { + let mut info = KeyInfo::default(); + info.sources.push(source); + let mut policy = xml_sec::policy::VerificationPolicy::default(); + policy.key_trust.mode = xml_sec::policy::VerificationTrustMode::CryptographicOnly; + let resolved = resolver + .resolve_with_policy(Some(&info), method, &policy) + .expect("restricted PSS key is valid") + .expect("restricted PSS key resolves"); + assert!(resolved.verify(method, b"restricted", &signature).unwrap()); + } + assert!( + RustCryptoProvider + .verify(&public, method, b"restricted", &signature) + .unwrap() + ); + #[cfg(feature = "aws-lc-fips")] + if salt_len == 32 { + assert!( + xml_sec::provider::AwsLcFipsProvider + .verify(&public, method, b"restricted", &signature) + .unwrap() + ); + } + } + for method in [ + SignatureAlgorithm::RsaSha256, + SignatureAlgorithm::RsaPssSha384, + SignatureAlgorithm::RsaPss(RsaPssParameters { + salt_len: 31, + ..RsaPssParameters::DEFAULT + }), + SignatureAlgorithm::RsaPss(RsaPssParameters { + mgf_digest: DigestAlgorithm::Sha384, + ..RsaPssParameters::DEFAULT + }), + ] { + let signature = key.sign(method, b"restricted").unwrap(); + let public = xml_sec::xmldsig::VerificationKey { + algorithm: method, + public_key_bytes: encoded.clone(), + certificate_der: None, + name: None, + }; + assert!( + RustCryptoProvider + .verify(&public, method, b"restricted", &signature) + .is_err() + ); + use xml_sec::xmldsig::{KeyInfo, KeyInfoSource, KeyResolver as _}; + let mut info = KeyInfo::default(); + info.sources + .push(KeyInfoSource::DerEncodedKeyValue(encoded.clone())); + let mut policy = xml_sec::policy::VerificationPolicy::default(); + policy.key_trust.mode = xml_sec::policy::VerificationTrustMode::CryptographicOnly; + assert!( + xml_sec::xmldsig::DefaultKeyResolver::default() + .resolve_with_policy(Some(&info), method, &policy) + .is_err() + ); + } +} + +#[test] +fn pss_spki_rejects_unrecognized_parameter_fields() { + // RFC 8017 appendix A.2.3 permits only the ordered [0]..[3] fields. + // Unknown fields must not be discarded and interpreted as SHA-1 defaults. + use der::{Decode as _, Encode as _}; + use x509_cert::spki::{AlgorithmIdentifierOwned, ObjectIdentifier}; + let public = pem::parse(PUBLIC).unwrap(); + let mut spki = x509_cert::SubjectPublicKeyInfo::from_der(public.contents()).unwrap(); + spki.algorithm = AlgorithmIdentifierOwned { + oid: ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10"), + parameters: Some( + der::asn1::Any::from_der(&[0x30, 0x05, 0xa4, 0x03, 0x02, 0x01, 0x00]).unwrap(), + ), + }; + let algorithm = SignatureAlgorithm::RsaPssSha1; + let signature = RsaSigningKey::from_pkcs8_pem(PRIVATE) + .unwrap() + .sign(algorithm, b"bad parameters") + .unwrap(); + let key = xml_sec::xmldsig::VerificationKey { + algorithm, + public_key_bytes: spki.to_der().unwrap(), + certificate_der: None, + name: None, + }; + assert!( + RustCryptoProvider + .verify(&key, algorithm, b"bad parameters", &signature) + .is_err() + ); +} + +#[test] +fn pss_independent_mgf_cross_verifies_with_openssl() { + use base64::Engine as _; + // Generated by OpenSSL 3.6.4: dgst -sha512 -sign rsa-2048-key.pem + // -sigopt rsa_padding_mode:pss -sigopt rsa_mgf1_md:sha256 + // -sigopt rsa_pss_saltlen:{0,17,64}, over exactly "independent MGF". + // These independent vectors always run, even on hosts without OpenSSL. + for (salt_len, encoded) in [ + ( + 0, + "b0Bp5/P3bbC9Bwl5fKkHRKoZJY4OekXDHNb/IhBculwfEtiGPZjq6OpBGV02YvKg5gnoki7EcGoO7ffxfAo6GNOpt4cL6AP8yseBp1F/ATuDAPEvJQHlxLt9bFbsscf7A8WGfj2Z2rmQBOyzgOJRf8xrodZb3XEif3QWUbEIpDbGeY+tL9lrsubtL0+0narA19SGVrZjBoLTdSiAyf4u3cyZ0Ij6VECjawF3ZQHWsu6mMga64Uj7+vBPY4hIRvPYKuGBw+0/EzDV/yFoeevVvskmT1ABmRSuQTnPVf+qQD6qEx//LkKBY717v6byOmyQQqzOpurUAmHmuEiWqttzyQ==", + ), + ( + 17, + "q2SyacHIO99s+kYTCpJ5fZRvNoMPgSjOkL6w1xRjkgHTwksxTCmc00iC+hXeKcyc9khTgslV+M7ueYB02Lo+tyXDkSrvr2X9sCwlTVL7XkZAy8VFE3l/RAh2q+OD0crqQDeTI3HUJLDYZXgJ0Ka+nssZOCF+lLnznAvOIeC9G+pXnQFW7+cHWL++d4Q2XBVrhefKPhHszWCxb4utnPuhFbFITd17V82bX/ysWWRorCgMFSy7rDBc9cZR6u+m57zbxSjTcKSLcydkrUgByXpconY8NDuLi8kN9kyug2y3P6xAr18Nb7DhfK7T3T2SVapNdBSHPBXPF7c52e5Z5ewqEg==", + ), + ( + 64, + "A9FfiAOy7OwsBg3oMJspE/Gr1e9w8x+olQ7gFfZRSD94qCwbetishFppbA2YanzVvg4OkdEfS/B5yBhI0qsyxRN4Hpk6h63SDQ6tk2nw8IBh2kVejqv/mYe0nN6Q+6HEjbMRSzvbs0o8DAPygMXum/C96zxUVBVpdVmrrw/1SAGPCafkYNIE34CxJ+jADnWEPKonAGzoDv16D/RzbzwDvSYj4A1+UTHM318bvpiO42b3VVepa+n13urPLqVICHOzlb9QaCH/aOm7hjxD+eWlU9/C7aGs0x9e/9jCmdKDS+/il4ZRbzt1MAm9T0jmhxGH01/UqGDWKTlDSuVV6tM3jg==", + ), + ] { + let method = SignatureAlgorithm::RsaPss(RsaPssParameters { + digest: DigestAlgorithm::Sha512, + mgf_digest: DigestAlgorithm::Sha256, + salt_len, + }); + let signature = base64::engine::general_purpose::STANDARD + .decode(encoded) + .unwrap(); + assert!(verify_rsa_signature_pem(method, PUBLIC, b"independent MGF", &signature).unwrap()); + assert!(!verify_rsa_signature_pem(method, PUBLIC, b"tampered", &signature).unwrap()); + assert!( + !verify_rsa_signature_pem( + SignatureAlgorithm::RsaPssSha512, + PUBLIC, + b"independent MGF", + &signature + ) + .unwrap() + ); + } + if let Some(binary) = std::env::var_os("OPENSSL_BIN") { + cross_verify_pss_with_openssl(&binary); + } +} + +fn cross_verify_pss_with_openssl(binary: &std::ffi::OsStr) { + // RFC 8017 permits different message/MGF hashes; OpenSSL is the independent + // oracle for both directions, including empty and non-digest-sized salts. + let directory = tempfile::tempdir().unwrap(); + let message = directory.path().join("message"); + let private = directory.path().join("private.pem"); + let public = directory.path().join("public.pem"); + let signature_path = directory.path().join("signature"); + std::fs::write(&message, b"independent MGF").unwrap(); + std::fs::write(&private, PRIVATE).unwrap(); + std::fs::write(&public, PUBLIC).unwrap(); + let key = RsaSigningKey::from_pkcs8_pem(PRIVATE).unwrap(); + for salt_len in [0, 17, 64] { + let method = SignatureAlgorithm::RsaPss(RsaPssParameters { + digest: DigestAlgorithm::Sha512, + mgf_digest: DigestAlgorithm::Sha256, + salt_len, + }); + std::fs::write( + &signature_path, + key.sign(method, b"independent MGF").unwrap(), + ) + .unwrap(); + for sign in [false, true] { + let mut command = std::process::Command::new(binary); + command.args(["dgst", "-sha512"]); + if sign { + command + .arg("-sign") + .arg(&private) + .arg("-out") + .arg(&signature_path); + } else { + command + .arg("-verify") + .arg(&public) + .arg("-signature") + .arg(&signature_path); + } + let output = command + .args([ + "-sigopt", + "rsa_padding_mode:pss", + "-sigopt", + "rsa_mgf1_md:sha256", + "-sigopt", + ]) + .arg(format!("rsa_pss_saltlen:{salt_len}")) + .arg(&message) + .output() + .expect("configured OPENSSL_BIN must execute; oracle failures are not skipped"); + assert!( + output.status.success(), + "{}", + String::from_utf8_lossy(&output.stderr) + ); + } + let signature = std::fs::read(&signature_path).unwrap(); + assert!(verify_rsa_signature_pem(method, PUBLIC, b"independent MGF", &signature).unwrap()); + assert!( + !verify_rsa_signature_pem( + SignatureAlgorithm::RsaPssSha512, + PUBLIC, + b"independent MGF", + &signature + ) + .unwrap() + ); + } +} + +#[test] +fn pss_donor_family_verifies_and_signs_every_template() { + // Execute every fixed-URI PSS signed document and template from upstream, + // using an independently pinned key rather than trusting document certificates. + let key = + RsaSigningKey::from_pkcs8_pem(include_str!("fixtures/keys/rsa/rsa-4096-key.pem")).unwrap(); + let spki = pem::parse(include_bytes!("fixtures/keys/rsa/rsa-4096-pubkey.pem")).unwrap(); + let signing = xml_sec::policy::SigningPolicy { + signature_algorithms: Some(SignatureAlgorithm::ALL.into_iter().collect()), + digest_algorithms: Some(DigestAlgorithm::ALL.into_iter().collect()), + ..xml_sec::policy::SigningPolicy::default() + }; + let mut count = 0; + for hash in [ + "sha1", "sha224", "sha256", "sha384", "sha512", "sha3_224", "sha3_256", "sha3_384", + "sha3_512", + ] { + for stem in [ + format!("enveloping-rsa-pss-{hash}"), + format!("enveloped-{hash}-rsa-pss-{hash}"), + ] { + if hash == "sha1" && stem.starts_with("enveloped-") { + continue; + } + let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("tests/fixtures/xmldsig/aleksey-xmldsig-01"); + let xml = std::fs::read_to_string(root.join(format!("{stem}.xml"))).unwrap(); + let document = XmlDomDocument::parse(&xml).unwrap(); + let info = xml_sec::xmldsig::parse_signed_info( + find_signature_node(&document) + .unwrap() + .first_element_child() + .unwrap(), + ) + .unwrap(); + let method = info.signature_method; + let public = xml_sec::xmldsig::VerificationKey { + algorithm: method, + public_key_bytes: spki.contents().to_vec(), + certificate_der: None, + name: None, + }; + let mut policy = xml_sec::policy::VerificationPolicy::default(); + policy + .key_trust + .allowed_legacy_signature_algorithms + .insert(SignatureAlgorithm::RsaPssSha1); + assert_eq!( + xml_sec::xmldsig::VerifyContext::new() + .key(&public) + .policy(policy.clone()) + .verify(&xml) + .unwrap() + .status, + DsigStatus::Valid, + "{stem}" + ); + let template = std::fs::read_to_string(root.join(format!("{stem}.tmpl"))).unwrap(); + let signed = SignContext::new(&key) + .policy(signing.clone()) + .sign_template(&template) + .unwrap(); + if std::env::var_os("XMLSEC1_BIN").is_some() { + assert!(xmlsec1::is_available(), "{}", xmlsec1::skip_reason()); + let directory = tempfile::tempdir().unwrap(); + let candidate = directory.path().join("signed.xml"); + std::fs::write(&candidate, &signed).unwrap(); + let output = xmlsec1::command() + .args(["--verify", "--pubkey-pem:TestKeyName-rsa-4096"]) + .arg( + std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("tests/fixtures/keys/rsa/rsa-4096-pubkey.pem"), + ) + .arg(&candidate) + .output() + .unwrap(); + assert!( + output.status.success(), + "{stem}: {}", + String::from_utf8_lossy(&output.stderr) + ); + } + assert_eq!( + xml_sec::xmldsig::VerifyContext::new() + .key(&public) + .policy(policy) + .verify(&signed) + .unwrap() + .status, + DsigStatus::Valid, + "{stem} template" + ); + count += 1; + } + } + assert_eq!(count, 17); +} + +#[cfg(feature = "aws-lc-fips")] +#[test] +fn pss_native_engines_interoperate_without_parameter_downgrades() { + // AWS-LC's supported PSS forms cross-verify; mixed hashes remain unsupported. + use xml_sec::provider::{AwsLcFipsProvider, AwsLcSigningKey, ProviderCapability}; + let private = pem::parse(PRIVATE).unwrap(); + let rust = RsaSigningKey::from_pkcs8_pem(PRIVATE).unwrap(); + for method in [ + SignatureAlgorithm::RsaPssSha256, + SignatureAlgorithm::RsaPssSha384, + SignatureAlgorithm::RsaPssSha512, + SignatureAlgorithm::RsaPss(RsaPssParameters::DEFAULT), + ] { + let aws = AwsLcSigningKey::from_pkcs8_der(method, private.contents()).unwrap(); + let public = xml_sec::xmldsig::VerificationKey { + algorithm: method, + public_key_bytes: pem::parse(PUBLIC).unwrap().into_contents(), + certificate_der: None, + name: None, + }; + for signature in [ + RustCryptoProvider + .sign(&rust, method, b"cross engine") + .unwrap(), + AwsLcFipsProvider + .sign(&aws, method, b"cross engine") + .unwrap(), + ] { + for provider in [ + &RustCryptoProvider as &dyn CryptoProvider, + &AwsLcFipsProvider, + ] { + assert!( + provider + .verify(&public, method, b"cross engine", &signature) + .unwrap() + ); + assert!( + !provider + .verify(&public, method, b"wrong", &signature) + .unwrap() + ); + } + } + } + let mixed = SignatureAlgorithm::RsaPss(RsaPssParameters { + mgf_digest: DigestAlgorithm::Sha384, + ..RsaPssParameters::DEFAULT + }); + assert!(!AwsLcFipsProvider.supports(ProviderCapability::Sign(mixed))); + assert!(!AwsLcFipsProvider.supports(ProviderCapability::Verify(mixed))); +} diff --git a/tools/xmlsec1/src/capabilities.rs b/tools/xmlsec1/src/capabilities.rs index 80365e52..a1501e56 100644 --- a/tools/xmlsec1/src/capabilities.rs +++ b/tools/xmlsec1/src/capabilities.rs @@ -74,6 +74,16 @@ pub const TRANSFORMS: &[&str] = &[ "rsa-sha256", "rsa-sha384", "rsa-sha512", + "rsa-pss", + "sha1-rsa-MGF1", + "sha224-rsa-MGF1", + "sha256-rsa-MGF1", + "sha384-rsa-MGF1", + "sha512-rsa-MGF1", + "sha3-224-rsa-MGF1", + "sha3-256-rsa-MGF1", + "sha3-384-rsa-MGF1", + "sha3-512-rsa-MGF1", "sha1", "sha224", "sha256", diff --git a/tools/xmlsec1/src/commands.rs b/tools/xmlsec1/src/commands.rs index e9e4a8b6..320469dd 100644 --- a/tools/xmlsec1/src/commands.rs +++ b/tools/xmlsec1/src/commands.rs @@ -927,6 +927,7 @@ fn xmlsec_compatibility_signing_policy(invocation: &Invocation) -> SigningPolicy // allowlists opt its sign command into every implemented libxmlsec1 method, // including legacy SHA-1, without weakening the core library defaults. let mut policy = SigningPolicy { + parameterized_rsa_pss: xml_sec::policy::RsaPssPermission::AllSupported, signature_algorithms: Some(HashSet::from(SignatureAlgorithm::ALL)), digest_algorithms: Some(HashSet::from(DigestAlgorithm::ALL)), manifest_processing: if invocation.flag("ignore-manifests") { @@ -1399,6 +1400,7 @@ fn xmlsec_compatibility_verification_policy(invocation: &Invocation) -> Verifica // boundary: both CLI signing and verification use the donor interpretation, // while the core library retains the XMLDSig binding by default. let mut policy = VerificationPolicy { + parameterized_rsa_pss: xml_sec::policy::RsaPssPermission::AllSupported, digest_algorithms: Some(HashSet::from(DigestAlgorithm::ALL)), // The compatibility executable explicitly permits every compiled XML // signature method, including experimental PQ methods. Library defaults @@ -1426,10 +1428,12 @@ fn xmlsec_compatibility_verification_policy(invocation: &Invocation) -> Verifica }; policy.key_trust.allowed_legacy_signature_algorithms = HashSet::from([ SignatureAlgorithm::RsaSha1, + SignatureAlgorithm::RsaPssSha1, SignatureAlgorithm::DsaSha1, SignatureAlgorithm::HmacSha1, SignatureAlgorithm::EcdsaSha1, ]); + policy.key_trust.parameterized_rsa_pss = xml_sec::policy::RsaPssPermission::AllSupported; // A compatibility boundary opts into provider-supported certificate/CRL // methods independently of XML methods. This includes every valid PSS // salt length without constructing an artificial finite parameter list. @@ -5318,6 +5322,10 @@ mod tests { // An explicit allowlist replaces, rather than extends, secure defaults. // Keep the CLI compatibility boundary complete when algorithms evolve. let policy = xmlsec_compatibility_signing_policy(&invocation(&["xmlsec1", "sign"])); + assert_eq!( + policy.parameterized_rsa_pss, + xml_sec::policy::RsaPssPermission::AllSupported + ); assert_eq!( policy.signature_algorithms, Some(HashSet::from([ @@ -5343,6 +5351,16 @@ mod tests { SignatureAlgorithm::RsaSha256, SignatureAlgorithm::RsaSha384, SignatureAlgorithm::RsaSha512, + SignatureAlgorithm::RsaPssSha1, + SignatureAlgorithm::RsaPssSha224, + SignatureAlgorithm::RsaPssSha256, + SignatureAlgorithm::RsaPssSha384, + SignatureAlgorithm::RsaPssSha512, + SignatureAlgorithm::RsaPssSha3_224, + SignatureAlgorithm::RsaPssSha3_256, + SignatureAlgorithm::RsaPssSha3_384, + SignatureAlgorithm::RsaPssSha3_512, + SignatureAlgorithm::RsaPss(xml_sec::xmldsig::RsaPssParameters::DEFAULT), SignatureAlgorithm::EcdsaSha1, SignatureAlgorithm::EcdsaSha224, SignatureAlgorithm::EcdsaSha256, @@ -6243,6 +6261,21 @@ mod tests { "verify", "input.xml", ])); + // Every tuple is authorized by the profile before any XML is parsed. + for salt_len in [0, 17, 32, 64] { + let method = SignatureAlgorithm::RsaPss(xml_sec::xmldsig::RsaPssParameters { + digest: DigestAlgorithm::Sha256, + mgf_digest: DigestAlgorithm::Sha1, + salt_len, + }); + assert!(policy.check_signature_algorithm(method).is_ok()); + assert!( + !policy + .key_trust + .allowed_legacy_signature_algorithms + .contains(&method) + ); + } assert_eq!( policy.transforms.xpath_here_semantics, xml_sec::xmldsig::XPathHereSemantics::XmlSecLegacy diff --git a/tools/xmlsec1/src/key_material.rs b/tools/xmlsec1/src/key_material.rs index da319079..94546105 100644 --- a/tools/xmlsec1/src/key_material.rs +++ b/tools/xmlsec1/src/key_material.rs @@ -230,7 +230,7 @@ pub fn signing_signature_metadata( xml_backend, )?; let signature = select_signature(&document, start_node_id, id_attributes)?; - let algorithm_uri = signature + let method = signature .children() .find(|node| node.has_tag_name(("http://www.w3.org/2000/09/xmldsig#", "SignedInfo"))) .and_then(|signed_info| { @@ -238,11 +238,10 @@ pub fn signing_signature_metadata( node.has_tag_name(("http://www.w3.org/2000/09/xmldsig#", "SignatureMethod")) }) }) - .and_then(|method| method.attribute("Algorithm")) .ok_or(KeyMaterialError::MissingSignedInfo)?; - let algorithm = SignatureAlgorithm::from_uri(algorithm_uri).ok_or_else(|| { - KeyMaterialError::Signature(format!("unsupported signature algorithm: {algorithm_uri}")) - })?; + let algorithm = xml_sec::xmldsig::parse::parse_signature_method(method, &policy.resources) + .map(|(algorithm, _, _)| algorithm) + .map_err(|error| KeyMaterialError::Signature(error.to_string()))?; let mut parsing = xml_sec::xmldsig::parse::KeyInfoParsingSession::new(&policy.resources) .map_err(|error| KeyMaterialError::Signature(error.to_string()))?; let mut key_info = signature_key_info(signature) diff --git a/tools/xmlsec1/tests/process_contract.rs b/tools/xmlsec1/tests/process_contract.rs index 862d4413..7123fb0a 100644 --- a/tools/xmlsec1/tests/process_contract.rs +++ b/tools/xmlsec1/tests/process_contract.rs @@ -47,6 +47,91 @@ fn project_root() -> &'static Path { Path::new(env!("CARGO_MANIFEST_DIR")) } +#[test] +fn parameterized_rsa_pss_cli_preserves_effective_parameters() { + // Real commands must read the full SignatureMethod, not recover the URI's + // defaults and silently replace a non-default MGF hash/salt length. + let temp = tempfile::tempdir().unwrap(); + let key = RsaSigningKey::from_pkcs8_pem(include_str!( + "../../../tests/fixtures/keys/rsa/rsa-2048-key.pem" + )) + .unwrap(); + // Compatibility permission must already cover legacy parameter tuples before + // metadata parsing, not be minted from the selected document afterward. + for (digest, mgf_digest) in [ + (DigestAlgorithm::Sha512, DigestAlgorithm::Sha256), + (DigestAlgorithm::Sha256, DigestAlgorithm::Sha1), + (DigestAlgorithm::Sha1, DigestAlgorithm::Sha256), + #[cfg(feature = "legacy-algorithms")] + (DigestAlgorithm::Md5, DigestAlgorithm::Ripemd160), + ] { + let algorithm = SignatureAlgorithm::RsaPss(xml_sec::xmldsig::RsaPssParameters { + digest, + mgf_digest, + salt_len: 17, + }); + let builder = + SignatureBuilder::new(C14nAlgorithm::new(C14nMode::Exclusive1_0, false), algorithm) + .add_reference( + ReferenceBuilder::new(DigestAlgorithm::Sha256) + .uri("") + .transform(Transform::Enveloped), + ); + let signed = SignContext::new(&key) + .policy(xml_sec::policy::SigningPolicy { + parameterized_rsa_pss: xml_sec::policy::RsaPssPermission::AllSupported, + ..Default::default() + }) + .sign_with_builder("CLI PSS", &builder) + .unwrap(); + let template = temp.path().join("template.xml"); + let output = temp.path().join("signed.xml"); + fs::write(&template, signed).unwrap(); + let result = Command::new(binary()) + .args(["sign", "--privkey-pem"]) + .arg(project_root().join("tests/fixtures/keys/rsa/rsa-2048-key.pem")) + .arg("--output") + .arg(&output) + .arg(&template) + .output() + .unwrap(); + assert!( + result.status.success(), + "{}", + String::from_utf8_lossy(&result.stderr) + ); + let result = Command::new(binary()) + .args(["verify", "--pubkey-pem"]) + .arg(project_root().join("tests/fixtures/keys/rsa/rsa-2048-pubkey.pem")) + .arg(&output) + .output() + .unwrap(); + assert!( + result.status.success(), + "{}", + String::from_utf8_lossy(&result.stderr) + ); + let mut policy = xml_sec::policy::VerificationPolicy::default(); + policy.parameterized_rsa_pss = xml_sec::policy::RsaPssPermission::AllSupported; + policy.key_trust.parameterized_rsa_pss = xml_sec::policy::RsaPssPermission::AllSupported; + let verified = VerifyContext::new() + .policy(policy) + .key(&xml_sec::xmldsig::VerificationKey { + algorithm, + public_key_bytes: pem::parse(include_str!( + "../../../tests/fixtures/keys/rsa/rsa-2048-pubkey.pem" + )) + .unwrap() + .into_contents(), + certificate_der: None, + name: None, + }) + .verify(&fs::read_to_string(output).unwrap()) + .unwrap(); + assert_eq!(verified.status, xml_sec::xmldsig::DsigStatus::Valid); + } +} + #[cfg(feature = "legacy-algorithms")] #[test] fn symmetric_recipient_wraps_are_executable_through_cli() {