Python Cryptography module save/load RSA keys to/from file

16,162

Your method of saving the private key throws away the newlines which load_pem_private_key() expects to see. I have modified your example slightly to illustrate this. The method save_key_bad() is your method, and the method save_key() shows a simple correct method.

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.serialization import load_pem_private_key


def gen_key():
    private_key = rsa.generate_private_key(
        public_exponent=65537, key_size=2048, backend=default_backend()
    )
    return private_key


def save_key(pk, filename):
    pem = pk.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.NoEncryption()
    )
    with open(filename, 'wb') as pem_out:
        pem_out.write(pem)


def save_key_bad(pk, filename):
    pem = pk.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.NoEncryption()
    )
    pem_data = pem.splitlines()
    with open(filename, 'wb') as pem_out:
        for line in pem_data:
            pem_out.write(line)


def load_key(filename):
    with open(filename, 'rb') as pem_in:
        pemlines = pem_in.read()
    private_key = load_pem_private_key(pemlines, None, default_backend())
    return private_key


if __name__ == '__main__':
    pk = gen_key()
    filename = 'privkey.pem'
    save_key(pk, filename)
    pk2 = load_key(filename)
    save_key_bad(pk, filename)
    pk3 = load_key(filename)
Share:
16,162

Related videos on Youtube

Ludisposed
Author by

Ludisposed

from stealer import authstealer

Updated on September 15, 2022

Comments

  • Ludisposed
    Ludisposed almost 2 years

    Using the Cryptography module for Python,

    I want to save my generated private key in a file, to use it later on.

    But from the docs I was unable to find the method needed for this.

    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives.asymmetric import rsa
    from cryptography.hazmat.primitives import serialization
    from cryptography.hazmat.primitives import hashes
    from cryptography.hazmat.primitives.asymmetric import padding
    
    # Working RSA encryption you can run for yourself
    MESSAGE = 'I am a very secret message'
    
    # Create private key
    private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
        backend=default_backend()
    )
    
    # Create public key
    public_key = private_key.public_key()
    
    # Encrypt
    ciphertext = public_key.encrypt(
        MESSAGE,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA1()),
            algorithm=hashes.SHA1(),
            label=None
        )
    )
    
    # Encrypted text
    print ciphertext
    
    # Decrypt
    plaintext = private_key.decrypt(
        ciphertext,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA1()),
            algorithm=hashes.SHA1(),
            label=None
        )
    )
    
    # Decrypted text
    print plaintext
    
    # Print human readable key
    pem = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.NoEncryption()
    )
    pem_data = pem.splitlines()
    print pem_data
    
    
    # How to Save//Load
    

    I know how to generate keys, but how can I save correctly to a file. By just storing the pem_data in a file and later on loading from that file with load_pem_public_key?

    Since Cryptography is still new for me, I would like to know the correct way of storing RSA keys in a file.

    This is my current try, but I get an error.

    ValueError: Could not deserialize key data.

    if os.path.exists('key.pem'):
        print 'file exist'
    else:
        f = open(os.path.join(__location__, 'key.pem'), 'w')
        for i in pem_data:
           f.write(i)
        f.close()
    
    with open(os.path.join(__location__, 'key.pem'), "rb") as key_file:
       private_key = serialization.load_pem_private_key(
            key_file.read(),
            password=None,
            backend=default_backend()
        )
    
  • President James K. Polk
    President James K. Polk over 3 years
    @BenDavis: Please run the changed code before making an edit. The pemlines is already a bytes object, therefore there is nothing to encode. Thanks for reading the answer thoroughly and I'm always glad to have someone find my bugs or improve my answers.