bentonstark / py-hsm

Python module for accessing PKCS#11 compliant HSMs
Other
57 stars 18 forks source link

Code example to use stored certificate #11

Closed serafdev closed 5 years ago

serafdev commented 5 years ago

Hi guys,

I am trying to create a session with an external API which requires me to show my client certificate. I tried with pycryptoki but I wasn't able to use the library to "bind" a private key certificate to the socket for the SSL handshake.

Do any of you have an example code using the request library with certificates stored in an HSM?

Here's my code:

from pyhsm.hsmclient import HsmClient
from requests import Session
from zeep import Client
from zeep.transports import Transport

from app.settings import BASE_DIR

import os

c = HsmClient(pkcs11_lib="/usr/lib/libCryptoki2_64.so")
c.open_session(slot=0)
c.login(pin="some-code")

session: Session = Session()

"""
Normally I should pass the key here too, but I have no idea how.
Also it can't find the path to the company1.pem associated key automatically even if I opened an HsmClient session

It should be: session.cert = ("/path/to/company1.pem", "/path/to/company1.key")
"""
session.cert = "/path/to/company1.pem" 
session.verify = os.path.join(
    BASE_DIR, os.path.join("run", "company2.pem")
)
client: Client = Client(
    f"https://company2.com/api/v9/connector.cgi",
    transport=Transport(session=session),
)
client.settings(raw_response=True)

c.logout()
c.close_session()

If there is no way to solve this, if you can point me to the right direction it would be great! I am open for suggestions or implementations with any language.

Thank you in advance!

bentonstark commented 5 years ago

Assuming a few things here: (1) You are attempting to connect to a TLS server using a TLS capable client (e.g. web server with HTTPS). (2) You are wanting to store a TLS private key and public X.509 client certificate (e.g. RSA or EC key and X.509 client TLS cert) in a HSM. (3) You are using TLS mutual-authentication and therefore are required to present a client X.509 certificate to a server.

If the above assumptions are correct, this library is not going to provide you any way to automatically bind a private RSA or EC key stored on an HSM with a TLS client or present a X.509 public certificate stored on an HSM to a TLS client. The pyhsm client is a low level API that interacts with the PKCS#11 API which most HSM vendors support.

serafdev commented 5 years ago

Thank you so much for your quick answer, all of your assumptions are correct.

I see, so basically I need to write a socket wrapper that validates the certificate with the HSM right?

I am trying to find an example of an implementation (using any language) if you've seen one somewhere it would be great if you could point me to it!

bentonstark commented 5 years ago

What you might try is a engine plugin for openssl that integrates with whatever HSM you plan to use. There is a generic engine I know that integrates with smart cards. Just keep in mind a smart card is not a HSM so you have to first load OpenSC which translates a smart card ADPU commands to the PKCS#11 HSM API. The translation is not perfect. I know SafeNet which was bought by Gemalto and most recently bought by Thales (and I am leaving off the Chrysalis acquisition!) has a openssl plugin that might do what you want for their HSMs. Utimaco also has one. Thales (nCipher) also has a openssl engine plugin for use with their HSMs but you will need to talk to them first before they will share their documentation. Each vendor has different levels of support for Java and other languages but that also be an option if you don't want to integrate with openssl or the openssl API. If speed is not an issue you might be able to use the cheaper but super slow Yubico HSM. Also Stackoverflow has a general discussion about openssl engines.