Domanda

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

Currently I was doing it using pycrypto, however, it does not seem to generate the same exact keys from the password alone. The reason seems to be that when pycrypto generates a RSA key it uses some sort of random number internally.

Currently my code looks 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 really care if I have to not use pycrypto, as long as I can generate these RSA keys from passwords and salts alone.

Thanks for the help in advance.

Just for reference, this is how 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: Also, I am only using RSA for authentication. So any solution that provides a way of generating secure asymmetric signatures/verifying generated from passwords are acceptable solutions for my application. Though, generating RSA keys from passwords I feel, is a question that should also be answered as it seems useful if used correctly.

È stato utile?

Soluzione

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

If you do need to generate an asymmetric signature than can be verified without knowing the password, you're going to have to somehow generate RSA (or DSA, etc.) keys in a deterministic manner 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've tested this, and it does generate deterministic RSA keys (as long as you remember to reset the counter, at least). However, note that this is not 100% future-proof: the generated keys might change, if the pycrypto RSA key generation algorithm is changed in some way.

In either case, you'll almost certainly want to preprocess your password using a slow key-stretching KDF such as PBKDF2, with an iteration count as high as you can reasonably tolerate. This makes breaking your system by brute-force password guessing considerably less easy. (Of course, you still need to use strong passwords; no amount of key-stretching is going to help if your password is abc123.)

Altri suggerimenti

  • Pass "randfunc" to the RSA.generate, and randfunc should return the output bytes, in order, of a well-known key derivation function that has been configured with enough output bits for RSA to "always complete" without needing more bits.

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

  • It may be possible to use Keccak directly as a KDF by specifying a high number of output bits.

  • If your generation function follows a well known standard closely, it should work across multiple implementations.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top