I generated a self-siged certificate like so:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365
The file cert.pem contains my public key. I wish to extract this public key from this file.
The way I tried to do is:
f = open('cert.pem', "rb")
pem_data = f.read()
f.close()
print(pem_data)
key = serialization.load_pem_public_key(pem_data, backend=default_backend())
However, after running the code, I get this error:
ValueError: Could not deserialize key data.
As a result I unable to extract the public key.
How do I fix this in order to extract the public key?
Note in the document
A PEM block which starts with -----BEGIN CERTIFICATE----- is not a public or private key, it’s an X.509 Certificate. You can load it using load_pem_x509_certificate() and extract the public key with Certificate.public_key.
Just try this:
from cryptography.hazmat.backends import default_backend
from cryptography import x509
f = open('cert.pem', "rb")
pem_data = f.read()
f.close()
key = x509.load_pem_x509_certificate(pem_data, backend=default_backend())
public_key = key.public_key()
In the first place check cryptography library is installed if it's no like that so:
pip install cryptography
You have to create your RSA keys with OpenSSL:
openssl genrsa -out jwt-key 4096
openssl rsa -in jwt-key -pubout > jwt-key.pub
reference : enter link description here
Related
I am integrating with EBS-EDT SOAP which uses wsse. I can successfully send XML envelope and receive an encrypted response. As I am making use of custom python code I decide I would manually try to decrypt the response first before implementing the wrapper code.
Based on the spec the following happens
Encryption key is encrypted with the public key from the original request contained in EncryptedKey tag.
This stage needs to be decoded as its base64.
This encryption key is then used in an AES 128 encryption to decrypt the XML body content.
P.S I looked at this blog with code snippets(not in python) and the process seems the same as what I am doing (http://webservices20.blogspot.com/2013/12/consuming-ebs-edt-soap-service-from-wcf.html)
I wrote the following python code snippet to decode the encryption key, but keep getting an error ValueError: Ciphertext with incorrect length (not 512 bytes). I am guessing it has to do with padding or that the certificate key use isn't correct, but unfortunately, the spec doesn't indicate what the padding would be and I have tried multiple key usages with no success.
My decryption code sample
import base64
from Cryptodome.Cipher import PKCS1_v1_5
from Cryptodome.PublicKey import RSA
from Cryptodome.Random import get_random_bytes
private_key_pem = "-----BEGIN PRIVATE KEY-----
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
PURtfoyDKlUpHmoJ+ruyu0bHpE4W
-----END PRIVATE KEY-----"
s = "gJvJjWEsmTcGzDvmYhVsheWR234xfo6lXx+cJCsTTy6tUwSBR+l5qqEFVpGohiSJhwa5IsRBDiJ28dOOnz0T6J3MSq82q34R0n8hJ80Hz37HL4KlVsygcdGceDbSYsIrPQRrMKTc2HB79r8/CqnQw2K5e71Gkw44soEtyzeldQ5hQFtsGkM1jkA40Xdu7mAjzUQ1REAVvR1fb0nLi6LRPZq+wnfMajLy1+8y+pCcQpsFBA5BD8j8EgHCLnpQE6GiRE6CLQNOa3s8/bnF1iGDfpJzAT8qJWZVpfQ4SuAhS6HRLe/TpXe5cDXnbWZxtkjMggAvkhR18bVXC8F0Pg81lQ=="
code_bytes = s.encode('UTF-8')
print(s)
print(code_bytes)
by = base64.b64decode(code_bytes)
print(by)
print(len(by))
private_key = RSA.import_key(private_key_pem)
cipher = PKCS1_v1_5.new(private_key)
sentinel = get_random_bytes(16)
#rsadecrypt = cipher.decrypt(by[3: 3 + 256], sentinel)
rsadecrypt = cipher.decrypt(by, sentinel)
if rsadecrypt == sentinel:
print('failure')
else:
print(f'success: {rsadecrypt.hex(" ")}')
For completeness here is the commands I use to generate the server keys used for xml encryption.
openssl x509 -req -sha256 -extfile x509.ext -extensions ca -in CA.csr -signkey CA.key -days 1095 -out CA.pem
openssl req -new -sha256 -nodes -newkey rsa:4096 -keyout ohip.key -out ohip.csr
openssl x509 -req -sha256 -CA CA.pem -CAkey CA.key -days 730 -CAcreateserial -CAserial CA.srl -extfile x509.ext -extensions server -in ohip.csr -out ohip_crt.pem```
In pyOpenSSL i haven't been able to find a way to encrypt a RSA private key with AES 256 just yet, been looking all over the place for this but cant seem to find a way.
Before i used OpenSSL to get the key and ca/cl certificates but now im opting to make an application where i need to handle the pfx-file in certain ways.
In OpenSSL i used to do the following:
openssl pkcs12 -in file.pfx -nocerts -out key.key
after that i did:
openssl rsa -aes256 -key.key -out encrypted.key
is there anything similar in pyOpenSSL using crypto?
I believe I solved this. But for anyone wondering, this is what I did:
import os
import shutil
from Crypto.PublicKey import RSA
def encrypt(old_key, new_key, passphrase):
key = RSA.importKey(open(old_key, 'rb').read())
with open(new_key, 'wb') as f:
pem_key = key.export_key(format='PEM', passphrase=passphrase, pkcs=8, protection='PBKDF2WithHMAC-SHA1AndAES256-CBC')
f.write(pem_key)
f.close()
if os.path.exists(old_key):
os.remove(old_key)
encryptAES('path_to_old_key', 'path_to_new:key.key', 'supersecretpassword')
One question still remaining is if there's anyway to output the encryption info done in python similar to OpenSSL?
If you run openssl rsa -aes256 -in old.key -out new.key
The key will return attributes in the beginning like such:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC
Key here...
-----END RSA PRIVATE KEY-----
However when I export the private key in Python I just get:
-----BEGIN ENCRYPTED PRIVATE KEY-----
Key here...
-----END ENCRYPTED PRIVATE KEY-----
Is there anyway to display these attributes with pycryptodome?
I'm trying to generate the same SHA1 fingerprint for a X509 certificate using pycryptodome that I get from the openssl command:
openssl x509 -noout -fingerprint -sha1 -inform pem -in certificate.crt
My certificate is in PEM format on disk
However, the code snippet below gives me a different value.
from Crypto.PublicKey import RSA
import hashlib
contents = open("/home/ubuntu/certificate.crt", "r").read().encode()
certificate = RSA.import_key(contents)
bytes = certificate.export_key("DER")
hashlib.sha1(bytes).hexdigest()
Anyone any idea what I'm doing wrong?
Still don't know how to do it using Pycryptodome, but I found there's no need for it at all. The following code fragment generates the same fingerprint as openssl does
pem = open("/home/ubuntu/certificate.crt", "r").read().encode()
pem = pem.removeprefix("-----BEGIN CERTIFICATE-----\n")
pem = pem.removesuffix("-----END CERTIFICATE-----\n")
public_bytes = base64.b64decode(pem)
sha1digest = hashlib.sha1(public_bytes).hexdigest()
fingerprint = ":".join(sha1digest[i : i + 2] for i in range(0, len(sha1digest), 2))
I'm using pyopenssl lib and I want to generate a p12 file using their crypto.PKCS12 object apis.
so this certificate value is obtained from an API and saved in a file as below:
echo -e "-----cert text with begin & end-----" > cert.crt
which creates the file and when I run below command, there's a proper output and even when I verify it online, it shows all good:
openssl x509 -in cert.crt -text -noout
now the problem is when used the below to set the certificate to PKCS12 object, it gives an error:
from OpenSSL import crypto
p12 = crypto.PKCS12()
p12.set_certificate("/home/someuser/Documents/path/to/cert.crt")
then it throws an error:
File
"/home/someuser/.local/lib/python3.6/site-packages/OpenSSL/crypto.py",
line 2429, in set_certificate
raise TypeError("cert must be an X509 instance")
I can't understand why the lib is complaining about the certificate. Is there anything I'm missing here?
It's required to load the certificate as an X509 object before setting it to a PKCS12 container.
So in the first place you should:
Read the content of the certificate file into a buffer
Create an X509 from the buffer using load_certificate
As a result it may look like as follows:
from OpenSSL import crypto
with open("/home/someuser/Documents/path/to/cert.crt", "r") as file:
data = file.read()
x509 = crypto.load_certificate(crypto.FILETYPE_PEM, data);
p12 = crypto.PKCS12()
p12.set_certificate(x509)
I did a Google search but I didn't find anything that would help me on that.I'm trying to authenticate my app in Microsoft Azure, so I created some self signed certificates. They give a tutorial of how to parse the crt however it's in PowerShell. I use only Ubuntu / OS X. Here's the code:
$cer = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cer.Import("mycer.cer")
$bin = $cer.GetRawCertData()
$base64Value = [System.Convert]::ToBase64String($bin)
$bin = $cer.GetCertHash()
$base64Thumbprint = [System.Convert]::ToBase64String($bin)
$keyid = [System.Guid]::NewGuid().ToString()
How would I go about writing the same code in Python? I have the .crt, .key, .csr, .pass.key and pkcs8_key files.
Update:
I want to extract the keyId and customKeyIdentifier from the certificates.
#philippe,
According to your description, if you want to get the certificate information using python, please refer to this simple code. I used the .cer as testing file:
import OpenSSL.crypto
f=open("tested.cer", "rb")
der = f.read()
x509=OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1, der)
print("serial number",x509.get_serial_number());
print("Issue Name",x509.get_issuer());
print("subject_name_hash",x509.subject_name_hash());
idif=x509.get_extension(0)
print("extension",x509.get_extension(0))
print("id",idif.get_data(),idif.get_short_name())
print("get_subject",x509.get_subject());
pkey = x509.get_pubkey()
print("Public Key ",pkey)
listdir=dir(pkey)
print(listdir)
print(pkey.bits())
print(pkey.type())
print(pkey._pkey)
Meanwhile, if you want to get a certificate information as keyId and customKeyIdentifier , I recommend you refer to the define of these properties of certificate and this sample. You can find the corresponding properties on that page. With these properties, you can get your certificate and its extension information. And you also can refer to this API documents. If I misunderstood, please feel free to let me know.
You don’t need neither python or powershell to parse certificates for Microsoft Azure.
The documentation describe 3 properties that are needed :
"keyCredentials": [
{
"customKeyIdentifier": "$base64Thumbprint_from_above",
"keyId": "$keyid_from_above",
"type": "AsymmetricX509Cert",
"usage": "Verify",
"value": "$base64Value_from_above"
}],
$base64Thumbprint is the base64 encoding of the sha1 hash of the certificate (in der format)
$keyid is just a random guuid
$base64Value is the base64 encoding of the whole certificate (in der format)
Generate the certificate
To generate a self-signed certificate (x509 with rsa 2048)
$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.key -out certificate.crt
Compute the base64 thumbprint
$ openssl x509 -outform der -in certificate.crt | openssl dgst -binary -sha1 | openssl base64
Compute the base64
$ openssl x509 -outform der -in certificate.crt | openssl base64 -A
Generate a random uuid
$ python -c "import uuid; print(uuid.uuid4())"
I checked against results generated with powershell and there are the same