Generating Cryptography Keys in Python

March 27, 2012 at 09:18 AM | categories: Python, SSL, Howto | View Comments

PyOpenSSL may seem like the obvious option when working with cryptography keys in Python but i have found it to have some short coming such as the inability to save both the public and private key in a key pair.

M2Crypto on the other hand allows you to save both keys to either a file or store it in a buffer which is useful if you want to save the keys say to a database.

Examples of M2Crypto usage are hard to come by, hope my few examples will save someone else the effort of searching.

Examples

Generate Key pair in memory

import os

from M2Crypto import Rand, RSA, BIO

KEY_LENGTH = 1024

def blank_callback():
    "Replace the default dashes"
    return

# Random seed
Rand.rand_seed (os.urandom (KEY_LENGTH))
# Generate key pair
key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
# Create memory buffers
pri_mem = BIO.MemoryBuffer()
pub_mem = BIO.MemoryBuffer()
# Save keys to buffers
key.save_key_bio(pri_mem, None)
key.save_pub_key_bio(pub_mem)

# Get keys 
public_key = pub_mem.getvalue()
private_key = pri_mem.getvalue()

Generate Key pair to file

from M2Crypto import Rand, RSA

KEY_LENGTH = 1024

def blank_callback():
    "Replace the default dashes"
    return

# Random seed
Rand.rand_seed (os.urandom (KEY_LENGTH))
# Generate key pair
key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
# Non encrypted key
key.save_key('user-private.pem', None)
# Use a pass phrase to encrypt key
#key.save_key('user-private.pem')
key.save_pub_key('user-public.pem')

Encrypt a text using a public key

from M2Crypto import RSA

# Load the recipients public key
writer = RSA.load_pub_key('user-public.pem')
# Encrypt the message
cipher = writer.public_encrypt('Secret message', RSA.pkcs1_oaep_padding)
# store the encrypted message
msg = cipher.encode('base64')

Signing a message

from M2Crypto import RSA, EVP

# load private key
mykey = RSA.load_key('user-private.pem')
# generate a digest
thedigest = EVP.MessageDigest('sha1')
# update the cipher text
thedigest.update(cipher)
#sign the message
signature = mykey.sign_rsassa_pss(thedigest.digest())
# display the signature
print signature.encode('base64')

Decrypt a message

from M2Crypto import RSA

mykey = RSA.load_key ('user-private.pem')
plaintext = mykey.private_decrypt(cipher, RSA.pkcs1_oaep_padding)

Verify a message

from M2Crypto import RSA, EVP

senderkey = RSA.load_pub_key('sender-public.pem')
thedigest = EVP.MessageDigest('sha1')
thedigest.update(cipher)
senderkey.verify_rsassa_pss(thedigest.digest(), signature) == 1

References


blog comments powered by Disqus