使用故意弱的私钥解密邮件会无限期挂起

ALK

从私钥生成公钥时遇到了问题,该私钥已被故意削弱,并且在使用PyCryptoDome时尝试对消息进行加密/解密。解密似乎无限期地挂起。

注意:显然这不是我真正的私钥故意削弱以下密钥:

-----BEGIN RSA PRIVATE KEY-----
MIIFJAIBAAKCAQEAzdoCzKqtgJs+n66H89khIqgqg4LxAq56FkU0wP9TgcStI0R8
lswVoAep0bC+2Hs1gwwZJBPH1UHn9NcmYHcxUCboemEZGCdfw+3jBGd7EPJx02Av
0QVSHmKTyOh9e/Cc1z+lyI4042T3Tm2Q6xFQOtunzSKrgViN2zMD2sCar7lBM6Kd
5ckBiHs/etgT+mZAW7QkSNb/jOz3Uuhw4z7vey5YewtekfVpGcdkI/XsyVc7TSqk
iBLd8bNyE0XebAp27yB7/RoUf2yPQ0jrIk4IRk7ecWESSgeDswa28a7Np8OGPGtu
Z2ev4SQOQEbbXFEofIjDcxJZvhvVPiNeVI9WIwIDAQABAoIBAQCRUVIHAbllJjLz
SKMY9Zl6sC4y+mdn3Gi7YZrek/oNJenD3j+ShMgCjOZiug8MuKdyHg9+QUIhvidT
1+TaCWRHXPAvVG4B3lBKLgLEKfkRLm93jlnmVYc/HZmOWItQYokvoVlIJEiALqQw
oKn2B+bg/6eM6bWBCu6f/q3xHP6v0ziM890O4vNK630VgrlRXCKBM/S/2jPVXIOZ
HhYMyXHUcUc56MpkgSAmeEF6HjKzGZP3fOvH7VAlphp/ZVduYrf+eRD0zOOjgK0y
DQvqaVCJS0WlBg3ozNBs7yFYdzpSY3XwuTZ0yrG4+I16ISTbt6W8V4Y1rPXfF7u8
Ssn3KXWpAoIBACkrmiju74AfDIZWGzDFBqCICICzyc1WGGrapCaZdxn0IqCnTB4o
0SABiF0jWV5/CrPPODpqWyqmx/3EoUZ+PRAHyBh50dGheY2V+jQUsjaW45Cs1l0B
EGx6HY6U5eWWhcSmVFtPpC16l9x8UC8DdnIr7lw6Ik0RtfijzZImhVZYQD2G7GEo
M4GyP+VeamVHpni9oNteMxwvZKoufPo/yX8JROVorIOXe2uORzpkYo6rC9w7uoGd
X5a9fTcN+UjO5JY5smXSBBl8HKcOlW1CznR2LH0Tag7OTYo0iv0i9e5aTgwVfHsU
vMagz6Z0kkWp1OW08+PQeFk4xD+grHdP3gcCAQUCggEAFc6DjDTq5MkNYEZRhqaF
mRgUsN8J/9ofetGuaseUv0mB4ehbOApUoohNS1AC8TuHVrBmzwIwocnPWooBBo6t
F0WX5eb4jPnjoWwUJ+vibWnExYfWz1JV+a9A4pnZn5734a5cNjVb977cmyu5aP2D
invceDtOmdXMthNFOqlurMp31F8X62pYxdS9ZWd6IYUvFvsSLb+agM5VmpKfHgoV
V1V4ia7E2bqt481ryvELBxhwYsm8QxUxYW2i2jtrk/YKO8v5w1bXVwxXPOFLoqDl
K+jALcvPvGHnzlGAYQ5Yh1SLzHjBA4x7ZRYehsNuCronCziqijuM021u/WjEkTnb
lwIBAQKCAQAg766HJYxmfz04ROKNamuzoAbNXKFxEa0iSINSFF9H9oIaH3AYIKdM
zgaw6RRLmNVcpcaVIeKIhWzLA7Q4ZP2mbKATlKfa55RxRMgpqigrq+lAikUXNA0j
lORyELfq3tFqHqniphzxLt/jlqaMAsUoIyUWlOg9p8TG6XFBuGqrecz+BYnnU1xn
wcy3fruEOVH6MU18S1wWjFCIJTDIMweY1Dcd7VbPrGK8cdKVHRulVaMWli7OF3+r
ysqScZQ6Px1E+vUeQZzhMBbsC6q9zwuQXon9qSGlcdehw6JkG/fx4dgJqsn8EJcF
TXLrkHUEh92EkMMcpsatxwNmGiOSpks5
-----END RSA PRIVATE KEY-----

以下代码段用于读取私钥,派生公钥,加密消息然后再次对其解密:

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import Crypto.Util
from base64 import *

def encryptMsg(rsakey, message):
    cipher = PKCS1_OAEP.new(rsakey)
    ct = cipher.encrypt(message)
    return ct

def decryptMsg(rsakey, message):
    cipher = PKCS1_OAEP.new(rsakey)
    pt = cipher.decrypt(message)
    return pt

key = RSA.importKey(open('private.key').read())
testpk = key.publickey()
message = b64encode(encryptMsg(testpk, b"test message"))
print(message)
print(decryptMsg(key, b64decode(message)))

呼叫时似乎挂起了decryptMsg()

马丁·彼得斯(Martijn Pieters)

您正在给PyCryptodome一个私钥,该私钥具有极不相称的质数,因此,此密钥的安全性实际上被破坏了。您在问题中注意到了这一点,但在这里很重要,因为PyCryptodome似乎对素数的大小进行了假设。

为了安全起见,RSA公钥加密通常需要使用两个数量级接近的素数

为了安全起见,应该随机选择整数pq,并且它们的大小应相似,但长度相差数位,以使分解更加困难。

您似乎通过使第二个质数为一位数字值来削弱了该键:

$ openssl rsa -in private.key -text -noout | sed '/prime1:/,/prime2:/!d;/prime2:/q'
prime1:
    29:2b:9a:28:ee:ef:80:1f:0c:86:56:1b:30:c5:06:
    a0:88:08:80:b3:c9:cd:56:18:6a:da:a4:26:99:77:
    19:f4:22:a0:a7:4c:1e:28:d1:20:01:88:5d:23:59:
    5e:7f:0a:b3:cf:38:3a:6a:5b:2a:a6:c7:fd:c4:a1:
    46:7e:3d:10:07:c8:18:79:d1:d1:a1:79:8d:95:fa:
    34:14:b2:36:96:e3:90:ac:d6:5d:01:10:6c:7a:1d:
    8e:94:e5:e5:96:85:c4:a6:54:5b:4f:a4:2d:7a:97:
    dc:7c:50:2f:03:76:72:2b:ee:5c:3a:22:4d:11:b5:
    f8:a3:cd:92:26:85:56:58:40:3d:86:ec:61:28:33:
    81:b2:3f:e5:5e:6a:65:47:a6:78:bd:a0:db:5e:33:
    1c:2f:64:aa:2e:7c:fa:3f:c9:7f:09:44:e5:68:ac:
    83:97:7b:6b:8e:47:3a:64:62:8e:ab:0b:dc:3b:ba:
    81:9d:5f:96:bd:7d:37:0d:f9:48:ce:e4:96:39:b2:
    65:d2:04:19:7c:1c:a7:0e:95:6d:42:ce:74:76:2c:
    7d:13:6a:0e:ce:4d:8a:34:8a:fd:22:f5:ee:5a:4e:
    0c:15:7c:7b:14:bc:c6:a0:cf:a6:74:92:45:a9:d4:
    e5:b4:f3:e3:d0:78:59:38:c4:3f:a0:ac:77:4f:de:
    07
prime2: 5 (0x5)

prime1(该p值)是使用617位的“适当的”大素,而第二q素是一个单一的数字值,因此p是约大10 ^ 616倍。然后,使用此密钥会触发PyCryptodome处理RSA解密的最坏情况。

在解密过程中,实现尝试通过重复添加第二个质数来使负数为正

m1 = pow(cp, self._d % (self._p - 1), self._p)
m2 = pow(cp, self._d % (self._q - 1), self._q)
h = m2 - m1
while h < 0:
    h += self._q

在上面的代码中,_p_q属性是两个素数,并且_d是私钥指数

由于您给定的私钥使用的是两个这样的极不相称的素数(1位和616位),所以for的m2值为3,而m1短为616位。结果,尝试将q(5)加到616位数的负整数将花费很长时间在我老化的Macbook Pro笔记本电脑上,PyCryptodome使用的GMP包装器可以在大约6秒钟内将一个小整数添加到该大整数一百万次:

timeit("a + b", "from Crypto.Math._IntegerGMP import IntegerGMP as H; a = H(-529888206800322351142280698970509553244088870105926093960960600839997948364537263924658051221855219286822834908160253952313431263065035892252247530580840707934254014192645042780064071400938165792458671917549294961637063901428635522475550885330295366860440266592481901428697979715456902249133738633092402578072834537512045684962133176512203248846326955899359525113708331947304401283815041620003402445741404924361709787545141518988924507726836779489762118740731196007268258996956015186886831392340919980371282865371496239488099989353283964607756716132847721450221986689589881754517900556993453537792486255692015472770); b = H(5)")
5.970772444999966

要完成该while循环,还必须重复执行10 ^ 609次,而我的笔记本电脑将花费的总时间将需要603位数字才能表示所需的数百万年。我不希望宇宙持续这么长时间,更不用说我的笔记本电脑了。

它应该只使用模运算;您可以在while h < 0: h += self._q此处用模运算替换循环:

if h < 0:
    h %= self._q

这是Crypto/PublicKey/RSA.pydef _decrypt(self, cyphertext):,线162在3.9.3版本。有了这种更改,解密几乎又立即完成了。

我已将此问题提交给PyCryptodome项目(现已关闭,已固定修复)中的一个错误,该项目发布了3.9.4版,其中的循环已替换为模运算。

如果您不想更改已安装的PyCryptodome副本并被阻止,则可以使用该cryptography项目,因为它没有此问题。PyCryptodome本身实现RSA算法,同时cryptography将解密委托给openssl库。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章