XML-Security / signxml

Python XML Signature and XAdES library
https://xml-security.github.io/signxml/
Apache License 2.0
137 stars 108 forks source link

invalid padding error when using signature_algorithm=SignatureMethod.SHA256_RSA_MGF1 #230

Open rahxam opened 1 year ago

rahxam commented 1 year ago

Hello,

When using signature_algorithm=SignatureMethod.SHA256_RSA_MGF1 the signature cannot be verified.

If I remove signature_algorithm=SignatureMethod.SHA256_RSA_MGF1 the signature can be validated fine.

import os
from lxml import etree
from signxml import XMLSigner, XMLVerifier, InvalidCertificate, SignatureMethod, DigestAlgorithm, CanonicalizationMethod

current_path = os.path.dirname(os.path.abspath(__file__))
ca_cert_file = os.path.join(current_path, "public_cert.pem")
cert = open(ca_cert_file).read()
key = open(os.path.join(current_path, "private_key.pem")).read()

data_to_sign = '<Test />'
root = etree.fromstring(data_to_sign)
signer = XMLSigner(signature_algorithm=SignatureMethod.SHA256_RSA_MGF1, digest_algorithm=DigestAlgorithm.SHA256, c14n_algorithm=CanonicalizationMethod.EXCLUSIVE_XML_CANONICALIZATION_1_0  )
signed_root = signer.sign(root, key=key, cert=cert)
try:
    verified_data = XMLVerifier().verify(signed_root, ca_pem_file=ca_cert_file)
except InvalidCertificate as e:
    print(e)
else:
    print('verified signature')

Error message:

Traceback (most recent call last):
  File "/home/k/.local/lib/python3.11/site-packages/signxml/verifier.py", line 398, in verify
    openssl_verify(signing_cert, raw_signature, signed_info_c14n, digest_alg_name)
  File "/usr/lib/python3/dist-packages/OpenSSL/crypto.py", line 3162, in verify
    _raise_current_error()
  File "/usr/lib/python3/dist-packages/OpenSSL/_util.py", line 57, in exception_from_error_queue
    raise exception_type(errors)
OpenSSL.crypto.Error: [('rsa routines', '', 'invalid padding'), ('rsa routines', '', 'padding check failed'), ('Provider routines', '', 'RSA lib')]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/mnt/hgfs/k-share/python/python.py", line 15, in <module>
    verified_data = XMLVerifier().verify(signed_root, ca_pem_file=ca_cert_file)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/k/.local/lib/python3.11/site-packages/signxml/verifier.py", line 404, in verify
    raise InvalidSignature(f"Signature verification failed: {reason}")
signxml.exceptions.InvalidSignature: Signature verification failed: invalid padding
RoryPTB commented 3 months ago

This issue is still present, one year later in version 3.2.2

from xml.etree import ElementTree as ET

from lxml import etree as lxml_ET
from signxml import XMLSigner, SignatureMethod

cap_cert_path = 'cert.pem'
cap_private_key_path = 'privkey.pem'
cap_signature_method = SignatureMethod.RSA_SHA256

def sign_cap_xml(xml_bytes):
    if not cap_cert_path or not cap_private_key_path:
        return None

    with open(cap_private_key_path, "rb") as key_file:
        key = key_file.read()

    with open(cap_cert_path, "rb") as cert_file:
        cert = cert_file.read()

    # register cap namespace¬
    ET.register_namespace("cap", "urn:oasis:names:tc:emergency:cap:1.2")
    root = ET.fromstring(xml_bytes)

    # specify location for enveloped signature
    # https://technotes.shemyak.com/posts/xml-signatures-with-python-elementtree/
    # https://xml-security.github.io/signxml/#signxml.XMLSigner
    ET.register_namespace("ds", "http://www.w3.org/2000/09/xmldsig#")
    ET.SubElement(root, "ds:Signature", {
                  "xmlns:ds": "http://www.w3.org/2000/09/xmldsig#", "Id": "placeholder"})

    signed_root = XMLSigner(signature_algorithm=cap_signature_method).sign(
        root, key=key, cert=cert)

    return lxml_ET.tostring(signed_root)

test = b'<Test />'

signed_xml = sign_cap_xml(test)
print(signed_xml)

Error:

File "...\venv\Lib\site-packages\signxml\signer.py", line 258, in sign
    signature = signing_settings.key.sign(signed_info_c14n, padding=PKCS1v15(), algorithm=hash_alg)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: ECPrivateKey.sign() got an unexpected keyword argument 'padding'
kislyuk commented 2 months ago

@RoryPTB your issue is unrelated to the original issue. You are trying to use an ECDSA private key with an RSA signing method. Please specify the correct signing method.

I filed a separate issue (#262) to make sure the error in your case is easier to understand.

kislyuk commented 2 months ago

@rahxam thank you for reporting; I am still looking into why this happens with MGF1.

RoryPTB commented 2 months ago

@kislyuk Thanks for the feedback. Would it be possible for the error to be more helpful, such as Please ensure the signing method is correct and try again?

kislyuk commented 2 months ago

@RoryPTB yes, that is what #262 is about.