Sign hashed data with a PCKS12 certificate

43 Views Asked by At

I need to send requests to a SOAP API, and as part of that process, I need to hash my XML request using SHA256 and then sign it with an RSA key (which I have in the form of a PCKS12 certificate). I've tried using the Crypto library like this:

from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15

with open("/my/cert/file.p12", "rb") as f:
    cert_data = f.read()

private_key = RSA.import_key(cert_data, passphrase="some_passphrase")
signer = pkcs1_15.new(private_key)

hash = SHA256.new(xml_data)
signature = signer.sign(hashed)

However, when I try testing this code, I always get the following error from the Crypto library:

security/crypto.py:25: in __init__
    private_key = RSA.import_key(cert.certificate, passphrase=cert.passphrase)
/Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/PublicKey/RSA.py:851: in import_key
    return _import_keyDER(extern_key, passphrase)
/Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/PublicKey/RSA.py:746: in _import_keyDER
    return decoding(extern_key, passphrase)
/Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/PublicKey/RSA.py:697: in _import_pkcs1_private
    der = DerSequence().decode(encoded, nr_elements=9, only_ints_expected=True)
/Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/Util/asn1.py:610: in decode
    result = DerObject.decode(self, der_encoded, strict=strict)
/Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/Util/asn1.py:228: in decode
    self._decodeFromStream(s, strict)
/Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/Util/asn1.py:623: in _decodeFromStream
    DerObject._decodeFromStream(self, s, strict)
/Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/Util/asn1.py:245: in _decodeFromStream
    length = self._decodeLen(s)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <Crypto.Util.asn1.DerSequence object at 0x7f03288f97d0>
s = <Crypto.Util.asn1.BytesIO_EOF object at 0x7f0328890310>

    def _decodeLen(self, s):
            """Decode DER length octets from a file."""

            length = s.read_byte()

            if length > 127:
                encoded_length = s.read(length & 0x7F)
>               if bord(encoded_length[0]) == 0:
E               IndexError: index out of range

/Yv1Cv_rJ-py3.11/lib/python3.11/site-packages/Crypto/Util/asn1.py:205: IndexError

It's clear that I'm not importing this certificate correctly but I'm not sure how, because I can successfully import it with the cryptography library:


import cryptography.hazmat.primitives.serialization.pkcs12

with open("/my/cert/file.p12", "rb") as f:
    private_key, certificate, additional = pkcs12.load_key_and_certificates(
        f.read(), b"some_passphrase",
    )

I notice that the private_key here also has a sign method, but calling it is more complicated so I'd rather avoid it if possible.

TL;DR: What's the "proper" way to use a PCKS12 key to produce a signature from a data hash in Python?

0

There are 0 best solutions below