Создание ключей RSA из пароля в python

Я хочу иметь возможность генерировать и re-generate те же ключи RSA от пароль (и соль) один в python.

В настоящее время я делал это с помощью 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 для аутентификации. Таким образом, любое решение, которое обеспечивает способ генерации secure асимметричная подписи / проверка, созданные из паролей, являются приемлемыми решениями для моего приложения. Хотя, генерируя ключи RSA из паролей, я чувствую, это вопрос, на который также следует ответить, поскольку он кажется полезным, если используется правильно.

2 ответов


Если вы пытаетесь реализовать аутентифицированного шифрования схема используя общий пароль, вам действительно не нужен ключ RSA: все, что вам нужно, это ключ AES для шифрования и HMAC ключ для проверки подлинности.

Если вы do необходимо создать асимметричную подпись, чем можно проверить, не зная пароля, вам придется каким-то образом генерировать RSA (или DSA и т. д.) ключи детерминированным образом на основе пароля. На основе документация этот должны можно определить пользовательский 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 изменен каким-то образом.

В любом случае, вы почти наверняка хотите предварительно обработать свой пароль, используя slow ключ-растяжение KDF, такие как PBKDF2 с, С число итераций так высоко, как вы можете разумно терпеть. Это делает ломать вашу систему путем грубой силы пароль угадывая значительно менее легким. (Конечно, вам все равно нужно использовать надежные пароли; никакое растяжение ключа не поможет, если ваш пароль abc123.)


  • передать "randfunc" в RSA.генерируйте, и randfunc должен возвращать выходные байты, по порядку, известной функции вывода ключа, которая была настроена с достаточным количеством выходных битов для RSA, чтобы "всегда завершать" без необходимости больше битов.

  • Argon2, scrypt, PBKDF2 являются примерами kdfs, предназначенных для этой цели.

  • возможно, можно использовать Keccak непосредственно в качестве KDF, указав большое количество выходных данных биты.

  • Если ваша функция генерации следует хорошо известному стандарту, она должна работать в нескольких реализациях.