Skip to content

Commit

Permalink
Restore compatibility with DSA and EC keys
Browse files Browse the repository at this point in the history
  • Loading branch information
kislyuk committed Aug 11, 2024
1 parent 1192410 commit 953a0c5
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
strategy:
max-parallel: 8
matrix:
os: [ubuntu-20.04, ubuntu-22.04, macos-12]
os: [ubuntu-20.04, ubuntu-24.04, macos-12]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
Expand Down
30 changes: 16 additions & 14 deletions signxml/verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,16 @@ def _apply_transforms(self, payload, *, transforms_node: etree._Element, signatu
def get_cert_chain_verifier(self, ca_pem_file, ca_path):
return X509CertChainVerifier(ca_pem_file=ca_pem_file, ca_path=ca_path)

def _verify_signature_with_public_key_impl(self, *, signature, data, public_key, signature_alg_impl):
verify_args = dict(signature=signature, data=data)
if isinstance(public_key, rsa.RSAPublicKey):
verify_args.update(padding=PKCS1v15(), algorithm=signature_alg_impl)
elif isinstance(public_key, dsa.DSAPublicKey):
verify_args.update(algorithm=signature_alg_impl)
elif isinstance(public_key, ec.EllipticCurvePublicKey):
verify_args.update(signature_algorithm=ec.ECDSA(signature_alg_impl))
public_key.verify(**verify_args)

def verify(
self,
data,
Expand Down Expand Up @@ -397,24 +407,16 @@ def verify(
raise InvalidSignature("Certificate subject common name mismatch")

if signature_alg.name.startswith("ECDSA"):
# FIXME: test coverage and replace public_key().bits() with public_key().public_bytes()
raw_signature = self._encode_dss_signature(raw_signature, signing_cert.public_key().bits())
raw_signature = self._encode_dss_signature(raw_signature, signing_cert.public_key().key_size)

cert_public_key = signing_cert.public_key()
signature_alg_impl = digest_algorithm_implementations[signature_alg]()
# FIXME: this is for RSA only; use listing below to make compatible with other public key types
cert_public_key.verify(
signature=raw_signature, data=signed_info_c14n, padding=PKCS1v15(), algorithm=signature_alg_impl
self._verify_signature_with_public_key_impl(
signature=raw_signature,
data=signed_info_c14n,
public_key=cert_public_key,
signature_alg_impl=signature_alg_impl,
)
"""
RSAPublicKey.verify(signature, data, padding, algorithm)
DSAPublicKey.verify(signature, data, algorithm)
EllipticCurvePublicKey.verify(signature, data, signature_algorithm)
Ed25519PublicKey.verify(signature, data)
Ed448PublicKey.verify(signature, data)
X25519PublicKey - no verify - DO NOT SUPPORT
X448PublicKey - no verify - DO NOT SUPPORT
"""

# If both X509Data and KeyValue are present, match one against the other and raise an error on mismatch
if key_value is not None:
Expand Down
4 changes: 3 additions & 1 deletion signxml/xades/xades.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,9 @@ def _verify_cert_digest(self, signing_cert_node, expect_cert):

def _verify_cert_digests(self, verify_result: VerifyResult):
x509_data = verify_result.signature_xml.find("ds:KeyInfo/ds:X509Data", namespaces=namespaces)
cert_from_key_info = load_pem_x509_certificate(add_pem_header(self._find(x509_data, "X509Certificate").text))
cert_from_key_info = x509.load_pem_x509_certificate(
add_pem_header(self._find(x509_data, "X509Certificate").text)
)
signed_signature_props = self._find(verify_result.signed_xml, "xades:SignedSignatureProperties")
signing_cert = self._find(signed_signature_props, "xades:SigningCertificate", require=False)
signing_cert_v2 = self._find(signed_signature_props, "xades:SigningCertificateV2", require=False)
Expand Down

0 comments on commit 953a0c5

Please sign in to comment.