'How do I use a X509 certificate with PyCrypto?

I want to encrypt some data in python with PyCrypto.

However I get an error when using key = RSA.importKey(pubkey):

RSA key format is not supported

The key was generated with:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout mycert.key -out mycert.pem

The code is:

def encrypt(data):
    pubkey = open('mycert.pem').read()
    key = RSA.importKey(pubkey)
    cipher = PKCS1_OAEP.new(key)
    return cipher.encrypt(data)


Solution 1:[1]

PyCrypto does not support X.509 certificates. You must first extract the public key with the command:

openssl x509 -inform pem -in mycert.pem -pubkey -noout > publickey.pem

Then, you can use RSA.importKey on publickey.pem.


If you don't want or cannot use openssl, you can take the PEM X.509 certificate and do it in pure Python like this:

from Crypto.Util.asn1 import DerSequence
from Crypto.PublicKey import RSA
from binascii import a2b_base64

# Convert from PEM to DER
pem = open("mycert.pem").read()
lines = pem.replace(" ",'').split()
der = a2b_base64(''.join(lines[1:-1]))

# Extract subjectPublicKeyInfo field from X.509 certificate (see RFC3280)
cert = DerSequence()
cert.decode(der)
tbsCertificate = DerSequence()
tbsCertificate.decode(cert[0])
subjectPublicKeyInfo = tbsCertificate[6]

# Initialize RSA key
rsa_key = RSA.importKey(subjectPublicKeyInfo)

Solution 2:[2]

Here's a good example: https://www.dlitz.net/software/pycrypto/api/2.6/Crypto.Cipher.PKCS1_OAEP-module.html

from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA

# sender side
message = 'To be encrypted'
key = RSA.importKey(open('pubkey.der').read())
cipher = PKCS1_OAEP.new(key)
ciphertext = cipher.encrypt(message)

# receiver side
key = RSA.importKey(open('privkey.der').read())
cipher = PKCS1_OAEP.new(key)
message = cipher.decrypt(ciphertext)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Kevin