Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How add/change password for RSA priv key using PyCrypto

maybe somebody be able to help me. I'm using PyCrypto to generate a pair of RSA keys. The public key and private key. I try to add/change a password to the private key, and I do not know how to do it.

This is a piece of my code.

#encoding:utf-8
from Crypto.PublicKey import RSA

pass_alice='ala'
private_alice_key = RSA.generate(1024)
public_alice_key  = private_alice_key.publickey()

str_priv = private_alice_key.exportKey()
str_pub  = public_alice_key.exportKey()

print str_priv
print str_pub

# HOW ADD OR CHANGE PASSWORD FOR private_alice_key

In M2Crypt the function generate pair key RSA.gen_key take give function callback argument and I can return my own password.

#example in M2Crypt:
from M2Crypto import RSA
key = RSA.gen_key(1024, 6528, lambda pass:'my_password')

How to do it in PyCrypto. Thanks for the reply

like image 381
Grzegorz Avatar asked Aug 01 '11 11:08

Grzegorz


2 Answers

PyCrypto has no function, which can manage RSA passphrase.

Instead, You can use ezPyCrypto (homepage) module, which is built top of PyCrypto module. It has simpler interface and lets you:

  • Generate, export and import public and private keys
  • Encrypt and decrypt strings with ease
  • Optionally create encrypted data as email-friendly text
  • Sign and verify strings (incl. documents)
  • Protect your private key with a passphrase
  • Create 'streams', for sending data through secured sockets
  • Choose any public key size you like (2048-bit recommended)
  • Choose between RSA and ElGamal for public key, and IDEA, DES3, Blowfish, ARC4, IDEA for session key
  • Rest in the comfort of security, with 256-bit session keys and defences against common RSA and ElGamal attacks, which will painfully frustrate anyone seeking to violate your privacy.

Usage:

"""
example7.py
Demonstrate the use of passphrases with private keys
"""
import ezPyCrypto

mysecret = "Don't look at this!!!"
raw = "Here is a string to encrypt"

# Create a key object
k = ezPyCrypto.key(passphrase=mysecret)

# Export public/private key
publicAndPrivateKey = k.exportKeyPrivate()

# Encrypt against this keypair
enc = k.encString(raw)

# Create a new key object, and import keys (with passphrase)
k1 = ezPyCrypto.key(publicAndPrivateKey, passphrase=mysecret)

# Decrypt text
dec = k.decString(enc)

# test
if dec == raw:
    print "Successful decryption using correct passphrase"
else:
    print "Failed somewhere"

print "Trying now with a bad passphrase"
try:
    k2 = ezPyCrypto.key(publicAndPrivateKey, passphrase="cracking attempt")
except ezPyCrypto.CryptoKeyError:
    print "Oops - our feeble cracking attempt failed (which is a good thing)."
else:
    print "Cracking attempt succeeded - we're not safe"
    # We're in - let's plunder
    dec2 = k2.decString(enc)

Build it

If you look into ezCryptoPy source,then you'll see key is actually encrypted/decrypted by using BlueFish algorithm:

   # decrypt against passphrase
        blksiz = 8 # lazy of me

        # create temporary symmetric cipher object for passphrase - 
        #hardwire to Blowfish
        ppCipher = Blowfish.new(passphrase,
                                Blowfish.MODE_CFB,
                                self._passIV[0:blksiz])
        enclen = len(keyobj)
        decpriv = ''
        i = 0
        while i < enclen:
            decbit = ppCipher.decrypt(keyobj[i:i+blksiz])
            decpriv += decbit
            i += blksiz
        keyobj = decpriv[0:size]

That means, you can write your own passphrase handler by using previous code example without installing ezPyCrypto. Here can you find many code examples, how do to it yourself: Nullege code search

My first and alternative solution:

You can use python exec() function and commandline function "ssh-keygen"(doc):

ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile].

like image 132
timgluz Avatar answered Nov 15 '22 00:11

timgluz


For loading key with phrase look at description of Module RSA

Description of importKey

importKey(externKey, passphrase=None)

Import an RSA key (public or private half), encoded in standard form.

See RSAImplementation.importKey.

Parameters:

  • externKey (string) - The RSA key to import, encoded as a string.

    An RSA public key can be in any of the following formats:

    • X.509 subjectPublicKeyInfo DER SEQUENCE (binary or PEM encoding)
    • PKCS#1 RSAPublicKey DER SEQUENCE (binary or PEM encoding)
    • OpenSSH (textual public key only)

    An RSA private key can be in any of the following formats:

    • PKCS#1 RSAPrivateKey DER SEQUENCE (binary or PEM encoding)
    • PKCS#8 PrivateKeyInfo DER SEQUENCE (binary or PEM encoding)
    • OpenSSH (textual public key only)

    For details about the PEM encoding, see RFC1421/RFC1423.

    In case of PEM encoding, the private key can be encrypted with DES or 3TDES according to a certain pass phrase. Only OpenSSL-compatible pass phrases are supported.

  • passphrase (string) - In case of an encrypted PEM key, this is the pass phrase from which the encryption key is derived.

Returns:

An RSA key object (_RSAobj).

Raises:

  • ValueError/IndexError/TypeError - When the given key cannot be parsed (possibly because the pass phrase is wrong).

Example:

from Crypto import RSA

key = RSA.generate(1024)
exportedKey = key.exportKey('PEM', 'my secret', pkcs=1)

For saving key with phrase look at description of object _RSAobj.

Description of exportKey

exportKey(self, format='PEM', passphrase=None, pkcs=1)

Export this RSA key.

Parameters:

  • format (string) - The format to use for wrapping the key.
    • 'DER'. Binary encoding, always unencrypted.
    • 'PEM'. Textual encoding, done according to RFC1421/RFC1423. Unencrypted (default) or > encrypted.
    • 'OpenSSH'. Textual encoding, done according to OpenSSH specification. Only suitable for public keys (not private keys).
  • passphrase (string) - In case of PEM, the pass phrase to derive the encryption key from.
  • pkcs (integer) - The PKCS standard to follow for assembling the key. You have two choices:

    • with 1, the public key is embedded into an X.509 SubjectPublicKeyInfo DER SEQUENCE. The private key is embedded into a PKCS#1 RSAPrivateKey DER SEQUENCE. This mode is the default.
    • with 8, the private key is embedded into a PKCS#8 PrivateKeyInfo DER SEQUENCE. This mode is not available for public keys. PKCS standards are not relevant for the OpenSSH format.

Returns:

A byte string with the encoded public or private half.

Raises:

  • ValueError - When the format is unknown.

Example:

from Crypto.PublicKey import RSA

with open("key.pem", "r") as privatekey:
    encryptor = RSA.importKey(privatekey, passphrase="my secret")
like image 34
MegaDiablo Avatar answered Nov 15 '22 00:11

MegaDiablo