Creating RSA keys with password in python

I want to be able to generate and generate the same RSA keys from a password (and salt) only in python .

I am currently doing this using pycrypto, however it does not seem to generate the exact same exact password keys only. The reason is that when pycrypto generates an RSA key, it uses some kind of random number inside.

Currently my code is as follows:

import DarkCloudCryptoLib as dcCryptoLib #some costume library for crypto from Crypto.PublicKey import RSA password = "password" new_key1 = RSA.generate(1024) #rsaObj exportedKey1 = new_key1.exportKey('DER', password, pkcs=1) key1 = RSA.importKey(exportedKey1) new_key2 = RSA.generate(1024) #rsaObj exportedKey2 = new_key2.exportKey('DER', password, pkcs=1) key2 = RSA.importKey(exportedKey2) print dcCryptoLib.equalRSAKeys(key1, key2) #wish to return True but it doesn't 

I don't care if pycrypto should be used as long as I can only generate these RSA keys from passwords and salts.

Thanks for the help in advance.

Just for reference, here is what the dcCryptoLib.equalRSAKeys (key1, key2) function looks like:

 def equalRSAKeys(rsaKey1, rsaKey2): public_key = rsaKey1.publickey().exportKey("DER") private_key = rsaKey1.exportKey("DER") pub_new_key = rsaKey2.publickey().exportKey("DER") pri_new_key = rsaKey2.exportKey("DER") boolprivate = (private_key == pri_new_key) boolpublic = (public_key == pub_new_key) return (boolprivate and boolpublic) 

NOTE. In addition, I use only RSA for authentication. Thus, any solution that provides a way to create secure asymmetric signatures / verifications generated by passwords is an acceptable solution for my application. Although generating RSA keys from passwords that I feel is a question that should also be answered, as it seems useful when used correctly.

+6
source share
2 answers

If you are trying to implement an authenticated encryption scheme using a common password, you really don't need an RSA key: all you need is an AES key for encryption and an HMAC for authentication.

If you need to create an asymmetric signature that can be verified without knowing the password, you will have to somehow generate RSA keys (or DSA, etc.) in a deterministic way based on the password. Based on the documentation , this should be possible by defining a custom randfunc , something like this:

 from Crypto.Protocol.KDF import PBKDF2 from Crypto.PublicKey import RSA password = "swordfish" # for testing salt = "yourAppName" # replace with random salt if you can store one master_key = PBKDF2(password, salt, count=10000) # bigger count = better def my_rand(n): # kluge: use PBKDF2 with count=1 and incrementing salt as deterministic PRNG my_rand.counter += 1 return PBKDF2(master_key, "my_rand:%d" % my_rand.counter, dkLen=n, count=1) my_rand.counter = 0 RSA_key = RSA.generate(2048, randfunc=my_rand) 

I tested this and it generates deterministic RSA keys (if you remember, at least, reset the counter). However, note that this is not 100% more reliable: the generated keys can change if the Pycrypto RSA key generation algorithm has somehow changed.

In any case, you will almost certainly want to pre-process your password by slowly stretching the KDF key , such as PBKDF2 , with the number of iterations as high as you can reasonably carry. This greatly reduces your system by guessing your password using bulkheads. (Of course, you still need to use strong passwords, no amount of key stretching will help if your password is abc123 .)

+3
source
  • Pass "randfunc" to RSA.generate, and randfunc should return the output bytes in the order of the well-known key derivation function, which was configured with enough output bits for RSA to "always complete" without requiring more bits.

  • Argon2, scrypt, PBKDF2 are examples of KDF designed for this purpose.

  • Perhaps Keccak can be used directly as KDF by specifying a large number of output bits.

  • If your generation function closely follows a well-known standard, it should work with several implementations.

0
source

All Articles