6

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

Grzegorz
  • 61
  • 1
  • 2

2 Answers2

2

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].

timgluz
  • 1,054
  • 11
  • 14
  • Seems that the link to the ezPyCrypto now redirects to some delicious Spam. – Rubén Cabrera Dec 07 '17 at 11:20
  • 1
    Good catch, i just updated it; I think this answer should regarded as out-of-date anyway as it was first responded in 2011, soon almost 7years ago and there should be much better libraries now; – timgluz Dec 07 '17 at 11:49
1

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")
MegaDiablo
  • 11
  • 2