I am using linux version openssl req to generate a csr with challenge password, everything goes fine, except it can not print this attribute:
# openssl req -new -key private.key -out server.csr
# openssl req -in server.csr -noout -text
Certificate Request: ...
Attributes:
challengePassword :unable to print attribute ...
I tested with OpenSSL 1.0.1j in fedora, and OpenSSL 1.0.1 in ubuntu, both can not write challengePassword into csr file.
But if I use windows version, it can work:
# openssl req -in test.csr -noout -text
Certificate Request:
...
Attributes:
challengePassword :00F7FC7937B5366F2231AC891472998C
...
I am using the 64bit openssl from the SCEP tool:
Then I searched openssl document, and found this sentence:
attributes
this specifies the section containing any request attributes: its
format is the same as distinguished_name. Typically these may contain
the
challengePassword or unstructuredName types. They are currently ignored by OpenSSL's request signing utilities but some CAs might want
them.
Yes, some CAs might want them. I am using NDES windows 2008 r2, it needs challenge password, it looks like it can not be generated by openssl req application, can I use openssl C API or python/perl? Or do I need to fix the openssl code?
I also asked this question on the sscep issue list, they told me I need to encode challenge password to BMPString. But I don't know how to encode it. Can someone give me guide?
Let me answer my question by myself.
To enable challenge password attribute in the CSR, we need to write ASN printable string, but the openssl req utility by default writes MBSTRING_ASC string, so it always return ":unable to print attribute ..."
Here is the C code sample:
Convert MBSTRING_ASC string to ASN1_PRINTABLESTRING:
ASN1_STRING *tmp_os = M_ASN1_PRINTABLESTRING_new();
tmp_os->type = V_ASN1_PRINTABLESTRING;
int password_length = strlen(challenge_password);
ASN1_STRING_set(tmp_os, (const unsigned char *)challenge_password, password_length);
Add attributes to the request:
X509_REQ_add1_attr_by_NID(req, NID_pkcs9_challengePassword, tmp_os->type, tmp_os->data, password_length);
Related
using OpenSSL, i can extract the modulus of the public key from various objects with these commands:
openssl rsa -noout -modulus -in {KEY}
openssl req -noout -modulus -in {CSR}
openssl x509 -noout -modulus -in {CERT}
I am trying to replicate this within python, using cryptography or the pyopenssl package.
I can extract the public key from all of these objects in Python, but I can not figure out how to encode the modulus to match the OpenSSL commandline output -- which appears to be a base64 encoded version of a format that I can't figure out from the docs or source code of any of the 3 projects.
The RSAPublicNumbers class (link) in cryptography has what you are looking for. You can get it using to_cryptography_key method (link) of PKey class in pyopenssl.
from OpenSSL.crypto import load_certificate
from OpenSSL.crypto import FILETYPE_PEM
with open(certfile, 'rb') as fp:
cert = load_certificate(FILETYPE_PEM, fp.read())
# This gives you the modulus in integer form
modn = cert.get_pubkey().to_cryptography_key().public_numbers().n
# Convert it to hex
print('{:X}'.format(modn))
In Python's urllib3 under Client Certificates there is an option for key_password.
Currently, I have the key info in plaintext and I want to encrypt it before storing it on the disk.
Here is the implementation:
http = urllib3.PoolManager(
... cert_file='/path/to/your/client_cert.pem',
... cert_reqs='CERT_REQUIRED',
... key_file='/path/to/your/client.key',
... key_password='keyfile_password')
However, I have not been able to find any documentation around what kind of encryption is supported for the key.
Okay. I figured it out.
I used AES symmetric encryption to encrypt the key.
Here is the command:
# openssl rsa -aes256 -in <key-file-in-plaintext> -out <key-file-encrypted>
> openssl rsa -aes256 -in key.pem -out key.pem.encrypted
This will ask you to enter a passphrase and it'll create an RSA key for you.
You can use this passphrase and pass it to the key_password named parameter.
Disclaimer: key_password is only supported in 1.25 and above versions of urllib3
Say that I have a cer file called symantec-class3.cer, this is what I'm trying:
headers = {"content-type": "application/json"}
api_url = "https://www.someurl.com/search"
pprint.pprint(requests.post(api_url, auth=HTTPBasicAuth(username, password), verify="symantec-class3.cer", data=json.dumps(payload), headers=headers).json())
This is not liking it and spews out the following error:
requests.exceptions.SSLError: [Errno 0] _ssl.c:344: error:00000000:lib(0):func(0):reason(0)
It works fine if I turn verify False, but I'm trying to use a cert file in my local directory.
Python expect cert in PEM format.
So you should extract the public key component from the X509 certificate using the openssl x509 command.
.cer extension often means a binary DER format, so this command should extract the public key in a form that can be used by pycrypto:
openssl x509 -inform der -pubkey -noout -in you.cer >public_key.pem
I have a .cer file containing public key. I need to use this file to verify signature signed by corresponding private key.
I have the signature and public key. I need to verify the signature.
I'm getting result as false.
Below is the code:
def verify_sign(public_key_loc, signature, data):
'''
Verifies with a public key from whom the data came that it was indeed
signed by their private key
param: public_key_loc Path to public key
param: signature String signature to be verified
return: Boolean. True if the signature is valid; False otherwise.
'''
#pdb.set_trace()
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from base64 import b64decode
try:
pub_key = open(public_key_loc, "r").read()
rsakey = RSA.importKey(pub_key)
signer = PKCS1_v1_5.new(rsakey)
digest = SHA256.new()
# Assumes the data is base64 encoded to begin with
digest.update(b64decode(data))
if signer.verify(digest, b64decode(signature)):
return True
return False
except Exception as e:
print e
I tried to use method here to convert .cer file to .pem. How do I use a X509 certificate with PyCrypto?
Is the method used here is correct? or does python has better libraries. Because as far as i know, python does not support X.509Certificate.
Bear my english.
Appreciate any help.
Thanks.
Edit:
As of now, i'm trying to use Pycrypto.
Do i need to use any other libraries or method in the same pycrypto?
You should be able to extract the public key component from the X509 certificate using the openssl x509 command. You say that your certificate file has a .cer extension which often means a binary DER format, so this command should extract the public key in a form that can be used by pycrypto:
openssl x509 -inform der -pubkey -noout -in certificate.cer >public_key.pem
Although, it's possible that your .cer file is already in PEM format (I suspect that it is because in C# you needed to base64 decode this certificate), in which case this command should get the public key:
openssl x509 -pubkey -noout -in certificate.cer >public_key.pem
Either way you should end up with a file public_key.pem that resembles this PEM format key:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq8ZtNvMVc3iDc850hdWu
7LLw4CQfE4O4IKy7mv6Iu6uhHQsfRQCqSbc1Nwxq70dMudG+41cSBI2Sx7bsAby2
2seBOCCtcoXmDvyBbAetaHY4xUTXzMZKxZc+ZPRR5vB+suxW9yWCTUmYyxaY3SPx
iZHRF5dAmSbW4qIrXt+9ifIbGlMtzFBBetA9KgxVcBQB6VhJEHoLk4KL4R7tOoAQ
gs6WijTwzNfTubRQh1VUCbidQihVAOWMNVS/3SWRRrcN5V2DqOWL+4TkPK522sRD
K1t0C/i+XWjxeFu1zn3xXZlA2sruOIFQvpihbLgkrfOvjA/XESgshBhMfbXZjzC1
GwIDAQAB
-----END PUBLIC KEY-----
Now you can load this using Crypto.PublicKey.RSA.importKey().
You also should double check the encoding of data and signature; make sure that these are base64 encoded as you assume, although this is probably correct since you have it working in C#.
Other options exist:
Use good old pyOpenSSL - see module OpenSSL.crypto:
import OpenSSL
cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1,
open('certificate.cer').read())
try:
OpenSSL.crypto.verify(cert, signature, data, 'sha256')
print "Signature verified OK"
except Exception as e:
print "Signature verification failed: {}".format(e)
Use M2Crypto (Python 3 not supported):
import M2Crypto
cert = M2Crypto.X509.load_cert('certificate.cer', M2Crypto.X509.FORMAT_DER)
pubkey = cert.get_pubkey()
pubkey.reset_context('sha256')
pubkey.verify_init()
pubkey.verify_update(content)
verified = pubkey.verify_final(signature)
I want to access a web service over HTTPS.
I have been given a client certificate (p12 file) in order to access it.
Previously we were using basic authentication.
Using python I am unsure how to access it.
I want to use httplib2
h = Http()
#h.add_credentials("testuser", "testpass")
#h.add_certificate(keyfile, certfile, '')
resp, content = h.request("https://example.com/webservice", "POST", xml_data)
print content
Now, I am quite new to SSL, Can I just call add_cert or somethign similar and give it the p12 file.
Do I need to convert it to a PEM file?
The answer to my question was IN my question
h.add_certificate(keyfile, certfile, '')
I had a pkcs12 file, I just needed to extract out the key and cert from the p12 file.
openssl pkcs12 -in file.p12 -out key.pem -nodes -nocerts
openssl pkcs12 -in file.p12 -out cert.pem -nodes -nokeys