I have an web server set up that denies connections without a valid .p12 certificate. I need to access a REST API that is running on the server in a Python script, but I can't find anything about how to do it. If anyone has a good tutorial on how to perform an SSL handshake using .p12 certificates in Python, please let me know.
The same methods described in the answers to this question, which asks about verifying a server certificate during the HTTPS connection (this is not done at all by default by urllib or httplib) should allow you to specify a client-certificate in addition to the CA certificate lists.
If you choose the option based on ssl.wrap_socket, pass a cerfile/keyfile parameter as described in the documentation.
Using PycURL, you should be able to call setopt(pycurl.SSLCERT, "/path/to/cert.pem") and setopt(pycurl.SSLKEY, "/path/to/key.pem"). The option names are based on the SSL and SECURITY OPTIONS section of the cURL documentation (there's an option for the password too).
It's likely that you will have to convert your PKCS#12 (.p12) file into PEM format. To do so:
# Extract the certificate:
openssl pkcs12 -in filename.p12 -nokeys -out certificate.pem
# Extract the private key:
openssl pkcs12 -in filename.p12 -nocerts -out privkey.pem
Related
Using OpenSSL I can check the validity of user X.509 certificates through the following command:
openssl verify -crl_check -CAfile $CRL_chain_path $PEM_path
with:
$CRL_chain_path: the path of a base64 file containing the trusted certificate chain and the CRL entries
$PEM_path: the path of my base64 certificate to be checked.
How could the same thing be achieved with Python3? So far I'm using the cryptography library. Unfortunately, according to this issue, the functionality is not yet included. Moreover, I would like to avoid bash command usage (subprocess, os, etc.).
This question only covers the chain of trust topic (which is unfortunately not enough). This one checks SSL/TLS sessions, which cannot be used in my context due to the fact that I focus on user PKI public keys.
Is there a simple way with Python to check the validity of X.509 certificates (date ok, chain of trust, no revocation, any other check performed by OpenSSL?, etc.)?
We have a service that requires a client certificate to be presented with the request or the call will be rejected. For our .NET components, we have the certificate installed in the local Windows cert store. At runtime we can get the certificate by thumbprint and include that with our request.
For our python component, I am able to get the certificate from the store, but only the public data. I can't seem to access the private key. To get around this I have a pem file with the certificate data that python uses. We are cleaning all secrets out of our source repository, so I need to remove this file.
Does anyone have a suggesiton on how I can access the private key for the certificate without checking it in with my code? Things I am exploring are:
Get the private key with the certificate from the windows cert store
Continue to use the pem file, but encrypt it somehow
Something else?
Thanks,
~john
I'm using Python's requests library to perform client side authentication with certificates. The scenario is the following: CA1 has issued a certificate for an intermediate CA (CA2) and CA2 has issued my client's certificate CLIENT. The server I'm connecting to trusts CA1's cert (but does not have CA2's cert). When I use:
requests.get('https:..', cert=('/path/CLIENT.cert', '/path/CLIENT.key'))
I get an error "certificate verify failed". I assumed that's because the server can not retrieve CA2's cert.
However, I'm unable to find a way to send CA2's cert to the server. If I include it in CLIENT, I get an error about private key and cert mismatch. I have also tried to include the chain of certificates in the verify parameter but there does not seem to be any difference on the result (as far as I understand, certs in the verify parameter are used for server side authentication).
Although I think this must be a quite common scenario, I'm unable to find a solution...
PD: If I verify CLIENT's cert with openssl and the full chain of certificates the validation is successful (so there is no problem with the certificates themselves).
Requests recommends using certifi as a CA bundle. Have you tried installing certifi, adding CA1, and passing the certifi bundle path to requests?
Question
How can I verify that an X.509 certificate is signed by another certificate using PyOpenSSL or Twisted? I want a client to verify that the received server certificate is the one that signed its client certificate.
I've looked through the PyOpenSSL documentation and can't seem to find anything on how to verify a certificate separately from the establishing the SSL connection.
I found a reference to OpenSSL.crypto:X509.verify() in twisted.internet._sslverify:PublicKey.verifyCertificate() , but the twisted method is commented out (in Twisted 13.0) and the X509 method does not exist (in PyOpenSSL 0.13).
pyOpenSSL has no support for verifying a certificate describes a bug for not being able to manually verify a certificate chain, but I'm not entirely sure if that's what I'm trying to do.
Use Case
Certificates:
Generated self-signed CA certificate with openssl.
Generated server certificate signed by CA certificate.
Generated client certificate signed by server certificate.
Setup:
The server is using Twisted's CertificateOptions with its server cert. The CA certs are the CA and server certs to setup a chain where the server cert verifies the received client cert, and the CA cert verifies the server cert (all built-in functionality).
The client is also using CertificateOptions for the client cert. The CA certs only contains the CA cert.
This all works fine (both sides verify each other) but I want to perform an additional step:
In the client set_verify() callback, verify that the client cert is signed by the server cert.
You should be able to do it with something like written here:
http://www.yothenberg.com/validate-x509-certificate-in-python/
which is basically:
load your certificates in PyOpenSSL with load_certificate()
create a X509Store() object
use add_cert() to add your intermediate certificate in the store
create a X509StoreContext() object, initializing it with both your store object and your end certificate
call verify_certificate() on your store context object
In practice, I was unable to make that part, and I think it is for the reasons explained here: https://mail.python.org/pipermail/cryptography-dev/2016-August/000676.html
In short, even in 2016, there still does not seem to be a correct wait to check certificates in PyOpenSSL, which is very sad. Note that the consensus seem to be that if you operate inside a TLS connection, the things are better checked by the connection routine instead of offline through check_certificate()
Is there some way to wrap a socket connection with SSL using python's ssl module in python 2.6 using a pkcs#12 file? The file contains a private key and certificate. I want to use them for the client side of the connection. This post seems to hint that it may be possible but doesn't give a real definitive answer.
Not with python's ssl module. M2Crypto can't do this also at the moment, nor does python-gnutls. If you've got openssl command available on your client machine, you can re-export that pkcs12 to pem format running the openssl command, and use the results, something like:
openssl pkcs12 -in your_pkcs.p12 -out client_certs.pem -clcerts -nokeys [password options]
openssl pkcs12 -in your_pkcs.p12 -out keys.pem -nocerts [password options]
However PKCS12 is utterly broken by design, while still popular, you should avoid it if possible.