使用Python从公钥获取RSA指数和模数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Python从公钥获取RSA指数和模数相关的知识,希望对你有一定的参考价值。

我知道如何使用openssl从公钥获取RSA模数和指数,但现在我尝试用Python做。我见过this并遵循步骤。

假设这是公钥:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdZGziIrJOlRomzh7M9qzo4ibw
QmwORcVDI0dsfUICLUVRdUN+MJ8ELd55NKsfYy4dZodWX7AmdN02zm1Gk5V5i2Vw
GVWE205u7DhtRe85W1oR9WTsMact5wuqU6okJd2GKrEGotgd9iuAJm90N6TDeDZ4
KHEvVEE1yTyvrxQgkwIDAQAB
-----END PUBLIC KEY-----

首先,从base64解码公钥:

import base64
bytearray = base64.b64decode("""MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdZGziIrJOlRomzh7M9qzo4ibw
QmwORcVDI0dsfUICLUVRdUN+MJ8ELd55NKsfYy4dZodWX7AmdN02zm1Gk5V5i2Vw
GVWE205u7DhtRe85W1oR9WTsMact5wuqU6okJd2GKrEGotgd9iuAJm90N6TDeDZ4
KHEvVEE1yTyvrxQgkwIDAQAB""")
print(bytearray)

输出:

0x81x9f0 x06 *x86Hx86xf7 x01x01x01x05x00x03x81x8dx000x81x89x02x81x81x00x9ddlxe2"xb2Nx95x1a&xcex1exccxf6xacxe8xe2&xf0Blx0eExc5C#Gl}Bx02-EQuC~0x9fx04-xdey4xabx1fc.x1dfx87V_xb0&txdd6xcemFx93x95yx8bepx19Ux84xdbNnxec8mExef9[Zx11xf5dxec1xa7-xe7x0bxaaSxaa$%xddx86*xb1x06xa2xd8x1dxf6+x80&ot7xa4xc3x6x(q/TA5xc9<xafxafx14 x93x02x03x01x00x01

然后,字节数组转换为base 16(十六进制)字符串:

bytearray.encode('hex')

输出:

30819f300d06092a864886f70d010101050003818d00308189028181009d646ce222b24e951a26ce1eccf6ace8e226f0426c0e45c54323476c7d42022d455175437e309f042dde7934ab1f632e1d6687565fb02674dd36ce6d469395798b6570195584db4e6eec386d45ef395b5a11f564ec31a72de70baa53aa2425dd862ab106a2d81df62b80266f7437a4c378367828712f544135c93cafaf1420930203010001

对于设计,让我们在字符串中的每两个字符之间添加“:”:

':'.join([ i+j for i,j in zip(bytearray[::2],bytearray[1::2])])

输出:

30:81:9f:30:0d:06:09:2a:86:48:86:f7:0d:01:01:01:05:00:03:81:8d:00:30:81:89:02:81:81:00:9d:64:6c:e2:22:b2:4e:95:1a:26:ce:1e:cc:f6:ac:e8:e2:26:f0:42:6c:0e:45:c5:43:23:47:6c:7d:42:02:2d:45:51:75:43:7e:30:9f:04:2d:de:79:34:ab:1f:63:2e:1d:66:87:56:5f:b0:26:74:dd:36:ce:6d:46:93:95:79:8b:65:70:19:55:84:db:4e:6e:ec:38:6d:45:ef:39:5b:5a:11:f5:64:ec:31:a7:2d:e7:0b:aa:53:aa:24:25:dd:86:2a:b1:06:a2:d8:1d:f6:2b:80:26:6f:74:37:a4:c3:78:36:78:28:71:2f:54:41:35:c9:3c:af:af:14:20:93:02:03:01:00:01

但是,不幸的是,我无法理解最后一步。我知道输出包括指数和模数,但还有其他字符要过滤掉(因为它们不能转换回基数10)。我也知道上面的十六进制表示基于ASN.1语法,因此在十六进制表示中应该有一些特定的偏移量,这两个值将出现。

从这个结果中获得模数和指数需要做些什么?

谢谢!

答案

公钥是ASN.1 SubjectPublicKeyInfo格式,在Java世界中也称为X509EncodedKeySpec。许多加密包可以直接导入这样的对象。

例如,使用PyCryptoCryptography.io,以下代码段

from Crypto.PublicKey import RSA
key_encoded='''-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdZGziIrJOlRomzh7M9qzo4ibw
QmwORcVDI0dsfUICLUVRdUN+MJ8ELd55NKsfYy4dZodWX7AmdN02zm1Gk5V5i2Vw
GVWE205u7DhtRe85W1oR9WTsMact5wuqU6okJd2GKrEGotgd9iuAJm90N6TDeDZ4
KHEvVEE1yTyvrxQgkwIDAQAB
-----END PUBLIC KEY-----'''


pubkey = RSA.importKey(key_encoded)
print(pubkey.n)
print(pubkey.e)

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization

pubkey2 = serialization.load_pem_public_key(
    key_encoded.encode('ascii'),
    backend=default_backend()
)

print(pubkey2.public_numbers().n)
print(pubkey2.public_numbers().e)

产生

110524622184298189406696366981362867320131527048683492811128204661745388510505145389459518039217549444918405620726988722254633562452576638635488354260221598432448974859895979017211032905988949400704082939941050902513120244660937339078367607684436944094809985731012813959774525636937965082155868293686780764307
65537
110524622184298189406696366981362867320131527048683492811128204661745388510505145389459518039217549444918405620726988722254633562452576638635488354260221598432448974859895979017211032905988949400704082939941050902513120244660937339078367607684436944094809985731012813959774525636937965082155868293686780764307
65537
另一答案

我不是这方面的专家,但我认为......

十六进制表示中的最后6个字节用于计算指数。

'02' - >此字节用于声明指数类型,即INTEGER。

'03' - >这个字节表示它是3字节长的数字。

'01:00:01' - >这3个字节代表指数。

以上是关于使用Python从公钥获取RSA指数和模数的主要内容,如果未能解决你的问题,请参考以下文章

从模数和指数生成 RSA 公钥

.net 中 RSA 公钥模数和指数的格式是啥?

在 Objective-c 中从模数和指数以字节为单位生成 RSA 公钥

如何验证 Apple 登录的 Jwt 令牌(后端验证)。如何从 Java 中的模数和指数 (n,e) 生成 RSA 公钥

RSA 使用 iOS 和 C# 实现

使用模数和公共指数的 C# RSA 加密