我希望能够在 python 中单独从密码(和盐)生成并重新生成相同的RSA密钥。
目前我使用pycrypto进行此操作,但是,它似乎并不仅仅通过密码生成相同的确切密钥。原因似乎是当pycrypto生成RSA密钥时,它会在内部使用某种随机数。
目前我的代码如下:
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
我真的不在乎我是否必须不使用pycrypto,只要我能从密码和盐中生成这些RSA密钥。
感谢您的帮助。
仅供参考,这是dcCryptoLib.equalRSAKeys(key1,key2)函数的样子:
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)
注意:另外,我只使用RSA进行身份验证。因此,任何提供生成安全非对称签名/验证密码生成的方法的解决方案都是我的应用程序可接受的解决方案。虽然,从我认为的密码生成RSA密钥,这个问题也应该得到解答,因为如果正确使用它似乎很有用。
答案 0 :(得分:5)
如果您尝试使用共享密码实施authenticated encryption方案,则实际上并不需要RSA密钥:您只需要一个用于加密的AES密钥和一个HMAC密钥认证
如果您做需要生成非对称签名,而不知道密码可以验证,那么您将不得不以某种方式以确定的方式生成RSA(或DSA等)密钥基于密码。基于documentation,通过定义自定义randfunc
, 可以,如下所示:
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)
我已经对此进行了测试,它确实生成了确定性的RSA密钥(只要你记得重置计数器,至少)。但请注意,这不是100%面向未来的:如果pycrypto RSA密钥生成算法以某种方式更改,生成的密钥可能会更改。
在任何一种情况下,您几乎肯定都希望使用慢key-stretching KDF(例如PBKDF2)预处理您的密码,迭代次数可以合理容忍。这使得通过暴力密码猜测破坏您的系统相当简单。 (当然,您仍需要使用强密码;如果您的密码为abc123
,则无法提供任何密钥拉伸量。)
答案 1 :(得分:0)
Pass" randfunc"到RSA.generate,randfunc应按顺序返回一个众所周知的密钥派生函数的输出字节,该函数已经配置了足够的输出位,以便RSA始终完成"无需更多位。
Argon2,scrypt,PBKDF2是为此目的而设计的KDF的例子。
通过指定大量输出位,可以直接将Keccak用作KDF。
如果您的生成函数遵循一个众所周知的标准,它应该适用于多个实现。