mvantellingen / python-zeep

A Python SOAP client
http://docs.python-zeep.org
Other
1.9k stars 586 forks source link

zeep Signature Clarification request #1152

Open dfashimpaur opened 4 years ago

dfashimpaur commented 4 years ago

I am trying to use zeep to send SOAP messages to a server that requires x509 certificates. I am confused with the Signature object for the wsse attribute. What is meant by a private key path versus a public key path? I generated a key in a keystore using keytool. I exported a certificate but I do not see how to find the public key and private key and to separate them into a file.

Petru-Tanas-ProcessITCS commented 4 years ago

This helper function might help, using OpenSSL:


import OpenSSL
from OpenSSL import crypto
from zeep.wsse.signature import Signature
from zeep import Client as cl

# helper funtion to generate certificate and keys
def create_csr(common_name, country=None, state=None, city=None,
               organization=None, organizational_unit=None,
               email_address=None):

    key = crypto.PKey()
    key.generate_key(crypto.TYPE_RSA, 2048)

    req = crypto.X509()
    req.get_subject().CN = common_name
    if organizational_unit:
        req.get_subject().OU = organizational_unit
    if organization:
        req.get_subject().O = organization
    if city:
        req.get_subject().L = city
    if state:
        req.get_subject().ST = state
    if country:
        req.get_subject().C = country
    if email_address:
        req.get_subject().emailAddress = email_address

    req.set_serial_number(1000)
    req.gmtime_adj_notBefore(0)
    req.gmtime_adj_notAfter(10*365*24*60*60)

    req.set_issuer(req.get_subject())
    req.set_pubkey(key)

    req.sign(key, 'sha256')

    private_key = crypto.dump_privatekey(
        crypto.FILETYPE_PEM, key)
    public_key = crypto.dump_publickey(crypto.FILETYPE_PEM, key)

    csr = crypto.dump_certificate(
               crypto.FILETYPE_PEM, req)

    out_keys = {
        "private key" : private_key,
        "public key": public_key,
        "certificate": csr,
        "reqest": req
    }
    return out_keys

# call the function
certificate = create_csr(common_name="somename",
                         organizational_unit="someunit",
                         organization="someorganiaton",
                         city="somecity",
                         state="somestate",
                         country="country in ISO format (ex: DK, FR, UK, DE)"
                         )

# now you have keys and certificate in a dictionary, just write them to files
with open('cert.pem', "wb") as f:
    f.write(certificate['certificate'])

with open('public.pem', "wb") as f:
    f.write(certificate['public key'])

with open('private.pem', "wb") as f:
    f.write(certificate['private key'])

# then do your signed request
url = "http://example.com"
client = cl(url, wsse=Singnature("private.pem", "cert.pem"))

Hope this helps

ffrank commented 2 months ago

Keystore and keytool are Java specific tooling. You will need to extract your cert and key in PEM format using keytool. Zeep can work with PEM formatted certificates and keys.