RSA:获取给定公钥的指数和模数

发布于 2024-09-07 12:33:03 字数 152 浏览 12 评论 0原文

我需要在 JavaScript 中使用 RSA 加密一些数据。周围的所有库都要求提供指数和模数,但我从对手那里得到了一个 public.key 文件。

如何从 RSA 文件中检索公共指数部分?

I need to encrypt some data using RSA in JavaScript. All of the libraries around ask for an exponent and a modulus, yet I get a single public.key file from my opponent.

How do you retrieve the public exponent and modulus part from an RSA file?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

兔姬 2024-09-14 12:33:03

这取决于您可以使用的工具。我怀疑是否有 JavaScript 可以直接在浏览器中执行此操作。它还取决于它是否是一次性的(始终相同的密钥)或是否需要编写脚本。

命令行/OpenSSL

如果您想在 unix 命令行上使用 OpenSSL 之类的东西,您可以执行以下操作。
我假设您的 public.key 文件包含类似这样的内容:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmBAjFv+29CaiQqYZIw4P
J0q5Qz2gS7kbGleS3ai8Xbhu5n8PLomldxbRz0RpdCuxqd1yvaicqpDKe/TT09sR
mL1h8Sx3Qa3EQmqI0TcEEqk27Ak0DTFxuVrq7c5hHB5fbJ4o7iEq5MYfdSl4pZax
UxdNv4jRElymdap8/iOo3SU1RsaK6y7kox1/tm2cfWZZhMlRFYJnpoXpyNYrp+Yo
CNKxmZJnMsS698kaFjDlyznLlihwMroY0mQvdD7dCeBoVlfPUGPAlamwWyqtIU+9
5xVkSp3kxcNcNb/mePSKQIPafQ1sAmBKPwycA/1I5nLzDVuQa95ZWMn0JkphtFIh
HQIDAQAB
-----END PUBLIC KEY-----

然后,命令将是:

PUBKEY=`grep -v -- ----- public.key | tr -d '\n'`

然后,您可以查看 ASN.1 结构:

echo $PUBKEY | base64 -d | openssl asn1parse -inform DER -i

这应该给您类似这样的内容:

    0:d=0  hl=4 l= 290 cons: SEQUENCE          
    4:d=1  hl=2 l=  13 cons:  SEQUENCE          
    6:d=2  hl=2 l=   9 prim:   OBJECT            :rsaEncryption
   17:d=2  hl=2 l=   0 prim:   NULL              
   19:d=1  hl=4 l= 271 prim:  BIT STRING 

模数和公共指数位于最后位字符串,偏移量 19,因此使用 -strparse

 echo $PUBKEY | base64 -d | openssl asn1parse -inform DER -i -strparse 19

这将为您提供十六进制的模数和公共指数(两个整数):

    0:d=0  hl=4 l= 266 cons: SEQUENCE          
    4:d=1  hl=4 l= 257 prim:  INTEGER           :98102316FFB6F426A242A619230E0F274AB9433DA04BB91B1A5792DDA8BC5DB86EE67F0F2E89A57716D1CF4469742BB1A9DD72BDA89CAA90CA7BF4D3D3DB1198BD61F12C7741ADC4426A88D1370412A936EC09340D3171B95AEAEDCE611C1E5F6C9E28EE212AE4C61F752978A596B153174DBF88D1125CA675AA7CFE23A8DD253546C68AEB2EE4A31D7FB66D9C7D665984C951158267A685E9C8D62BA7E62808D2B199926732C4BAF7C91A1630E5CB39CB96287032BA18D2642F743EDD09E0685657CF5063C095A9B05B2AAD214FBDE715644A9DE4C5C35C35BFE678F48A4083DA7D0D6C02604A3F0C9C03FD48E672F30D5B906BDE5958C9F4264A61B452211D
  265:d=1  hl=2 l=   3 prim:  INTEGER           :010001

如果它始终是相同的密钥,那可能没问题,但这是放入脚本可能不太方便。

或者(这可能更容易放入脚本中),

openssl rsa -pubin -inform PEM -text -noout < public.key

将返回:

Modulus (2048 bit):
    00:98:10:23:16:ff:b6:f4:26:a2:42:a6:19:23:0e:
    0f:27:4a:b9:43:3d:a0:4b:b9:1b:1a:57:92:dd:a8:
    bc:5d:b8:6e:e6:7f:0f:2e:89:a5:77:16:d1:cf:44:
    69:74:2b:b1:a9:dd:72:bd:a8:9c:aa:90:ca:7b:f4:
    d3:d3:db:11:98:bd:61:f1:2c:77:41:ad:c4:42:6a:
    88:d1:37:04:12:a9:36:ec:09:34:0d:31:71:b9:5a:
    ea:ed:ce:61:1c:1e:5f:6c:9e:28:ee:21:2a:e4:c6:
    1f:75:29:78:a5:96:b1:53:17:4d:bf:88:d1:12:5c:
    a6:75:aa:7c:fe:23:a8:dd:25:35:46:c6:8a:eb:2e:
    e4:a3:1d:7f:b6:6d:9c:7d:66:59:84:c9:51:15:82:
    67:a6:85:e9:c8:d6:2b:a7:e6:28:08:d2:b1:99:92:
    67:32:c4:ba:f7:c9:1a:16:30:e5:cb:39:cb:96:28:
    70:32:ba:18:d2:64:2f:74:3e:dd:09:e0:68:56:57:
    cf:50:63:c0:95:a9:b0:5b:2a:ad:21:4f:bd:e7:15:
    64:4a:9d:e4:c5:c3:5c:35:bf:e6:78:f4:8a:40:83:
    da:7d:0d:6c:02:60:4a:3f:0c:9c:03:fd:48:e6:72:
    f3:0d:5b:90:6b:de:59:58:c9:f4:26:4a:61:b4:52:
    21:1d
Exponent: 65537 (0x10001)

Java

这取决于输入格式。如果它是密钥库中的 X.509 证书,请使用 (RSAPublicKey)cert.getPublicKey():此对象有两个用于模数和指数的 getter。

如果它的格式如上,您可能需要使用 BouncyCastle 及其 PEMReader阅读它。我还没有尝试过以下代码,但这或多或少看起来像这样:(

PEMReader pemReader = new PEMReader(new FileReader("file.pem"));
Object obj = pemReader.readObject();
pemReader.close();
if (obj instanceof X509Certificate) {
   // Just in case your file contains in fact an X.509 certificate,
   // useless otherwise.
   obj = ((X509Certificate)obj).getPublicKey();
}
if (obj instanceof RSAPublicKey) {
   // ... use the getters to get the BigIntegers.
}

您也可以在 C# 中类似地使用 BouncyCastle。)

It depends on the tools you can use. I doubt there is a JavaScript too that could do it directly within the browser. It also depends if it's a one-off (always the same key) or whether you need to script it.

Command-line / OpenSSL

If you want to use something like OpenSSL on a unix command line, you can do something as follows.
I'm assuming you public.key file contains something like this:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmBAjFv+29CaiQqYZIw4P
J0q5Qz2gS7kbGleS3ai8Xbhu5n8PLomldxbRz0RpdCuxqd1yvaicqpDKe/TT09sR
mL1h8Sx3Qa3EQmqI0TcEEqk27Ak0DTFxuVrq7c5hHB5fbJ4o7iEq5MYfdSl4pZax
UxdNv4jRElymdap8/iOo3SU1RsaK6y7kox1/tm2cfWZZhMlRFYJnpoXpyNYrp+Yo
CNKxmZJnMsS698kaFjDlyznLlihwMroY0mQvdD7dCeBoVlfPUGPAlamwWyqtIU+9
5xVkSp3kxcNcNb/mePSKQIPafQ1sAmBKPwycA/1I5nLzDVuQa95ZWMn0JkphtFIh
HQIDAQAB
-----END PUBLIC KEY-----

Then, the commands would be:

PUBKEY=`grep -v -- ----- public.key | tr -d '\n'`

Then, you can look into the ASN.1 structure:

echo $PUBKEY | base64 -d | openssl asn1parse -inform DER -i

This should give you something like this:

    0:d=0  hl=4 l= 290 cons: SEQUENCE          
    4:d=1  hl=2 l=  13 cons:  SEQUENCE          
    6:d=2  hl=2 l=   9 prim:   OBJECT            :rsaEncryption
   17:d=2  hl=2 l=   0 prim:   NULL              
   19:d=1  hl=4 l= 271 prim:  BIT STRING 

The modulus and public exponent are in the last BIT STRING, offset 19, so use -strparse:

 echo $PUBKEY | base64 -d | openssl asn1parse -inform DER -i -strparse 19

This will give you the modulus and the public exponent, in hexadecimal (the two INTEGERs):

    0:d=0  hl=4 l= 266 cons: SEQUENCE          
    4:d=1  hl=4 l= 257 prim:  INTEGER           :98102316FFB6F426A242A619230E0F274AB9433DA04BB91B1A5792DDA8BC5DB86EE67F0F2E89A57716D1CF4469742BB1A9DD72BDA89CAA90CA7BF4D3D3DB1198BD61F12C7741ADC4426A88D1370412A936EC09340D3171B95AEAEDCE611C1E5F6C9E28EE212AE4C61F752978A596B153174DBF88D1125CA675AA7CFE23A8DD253546C68AEB2EE4A31D7FB66D9C7D665984C951158267A685E9C8D62BA7E62808D2B199926732C4BAF7C91A1630E5CB39CB96287032BA18D2642F743EDD09E0685657CF5063C095A9B05B2AAD214FBDE715644A9DE4C5C35C35BFE678F48A4083DA7D0D6C02604A3F0C9C03FD48E672F30D5B906BDE5958C9F4264A61B452211D
  265:d=1  hl=2 l=   3 prim:  INTEGER           :010001

That's probably fine if it's always the same key, but this is probably not very convenient to put in a script.

Alternatively (and this might be easier to put into a script),

openssl rsa -pubin -inform PEM -text -noout < public.key

will return this:

Modulus (2048 bit):
    00:98:10:23:16:ff:b6:f4:26:a2:42:a6:19:23:0e:
    0f:27:4a:b9:43:3d:a0:4b:b9:1b:1a:57:92:dd:a8:
    bc:5d:b8:6e:e6:7f:0f:2e:89:a5:77:16:d1:cf:44:
    69:74:2b:b1:a9:dd:72:bd:a8:9c:aa:90:ca:7b:f4:
    d3:d3:db:11:98:bd:61:f1:2c:77:41:ad:c4:42:6a:
    88:d1:37:04:12:a9:36:ec:09:34:0d:31:71:b9:5a:
    ea:ed:ce:61:1c:1e:5f:6c:9e:28:ee:21:2a:e4:c6:
    1f:75:29:78:a5:96:b1:53:17:4d:bf:88:d1:12:5c:
    a6:75:aa:7c:fe:23:a8:dd:25:35:46:c6:8a:eb:2e:
    e4:a3:1d:7f:b6:6d:9c:7d:66:59:84:c9:51:15:82:
    67:a6:85:e9:c8:d6:2b:a7:e6:28:08:d2:b1:99:92:
    67:32:c4:ba:f7:c9:1a:16:30:e5:cb:39:cb:96:28:
    70:32:ba:18:d2:64:2f:74:3e:dd:09:e0:68:56:57:
    cf:50:63:c0:95:a9:b0:5b:2a:ad:21:4f:bd:e7:15:
    64:4a:9d:e4:c5:c3:5c:35:bf:e6:78:f4:8a:40:83:
    da:7d:0d:6c:02:60:4a:3f:0c:9c:03:fd:48:e6:72:
    f3:0d:5b:90:6b:de:59:58:c9:f4:26:4a:61:b4:52:
    21:1d
Exponent: 65537 (0x10001)

Java

It depends on the input format. If it's an X.509 certificate in a keystore, use (RSAPublicKey)cert.getPublicKey(): this object has two getters for the modulus and the exponent.

If it's in the format as above, you might want to use BouncyCastle and its PEMReader to read it. I haven't tried the following code, but this would look more or less like this:

PEMReader pemReader = new PEMReader(new FileReader("file.pem"));
Object obj = pemReader.readObject();
pemReader.close();
if (obj instanceof X509Certificate) {
   // Just in case your file contains in fact an X.509 certificate,
   // useless otherwise.
   obj = ((X509Certificate)obj).getPublicKey();
}
if (obj instanceof RSAPublicKey) {
   // ... use the getters to get the BigIntegers.
}

(You can use BouncyCastle similarly in C# too.)

弄潮 2024-09-14 12:33:03

使用时请注意模数中可能出现的前导 00:

openssl rsa -pubin -inform PEM -text -noout < public.key

示例模数包含 257 字节而不是 256 字节,因为 00 被包含在内,因为 98 中的 9 看起来像负号数字。

Beware the leading 00 that can appear in the modulus when using:

openssl rsa -pubin -inform PEM -text -noout < public.key

The example modulus contains 257 bytes rather than 256 bytes because of that 00, which is included because the 9 in 98 looks like a negative signed number.

眼泪淡了忧伤 2024-09-14 12:33:03

主要供我自己参考,以下是如何从 ssh-keygen 生成的私钥中获取它

openssl rsa -text -noout -in ~/.ssh/id_rsa

当然,这仅适用于私钥。

Mostly for my own reference, here's how you get it from a private key generated by ssh-keygen

openssl rsa -text -noout -in ~/.ssh/id_rsa

Of course, this only works with the private key.

日暮斜阳 2024-09-14 12:33:03

您可以通过

openssl rsa -pubin -in public_key.pem -noout -modulus

Bonus 直接打印模数:在末尾添加“| openssl md5”以获得更小的字符串以便于比较

you can directly print modulus by

openssl rsa -pubin -in public_key.pem -noout -modulus

Bonus: add " | openssl md5" at the end to get a smaller string to compare easily

野生奥特曼 2024-09-14 12:33:03

除了上面的答案之外,我们还可以使用 asn1parse 来获取值

$ openssl asn1parse -i -in pub0.der -inform DER -offset 24
0:d=0  hl=4 l= 266 cons: SEQUENCE
4:d=1  hl=4 l= 257 prim:  INTEGER           :C9131430CCE9C42F659623BDC73A783029A23E4BA3FAF74FE3CF452F9DA9DAF29D6F46556E423FB02610BC4F84E19F87333EAD0BB3B390A3EFA7FB392E935065D80A27589A21CA051FA226195216D8A39F151BD0334965551744566AD3DAEB53EBA27783AE08BAAACA406C27ED8BE614518C8CD7D14BBE7AFEBE1D8D03374DAE7B7564CF1182A7B3BA115CD9416AB899C5803388EE66FA3676750A77AC870EDA027DC95E57B9B4E864A3C98F1BA99A4726C085178EA8FC6C549BE5EDF970CCB8D8F9AEDEE3F5CFDE574327D05ED04060B2525FB6711F1D78254FF59089199892A9ECC7D4E4950E0CD2246E1E613889722D73DB56B24E57F3943E11520776BC4F
265:d=1  hl=2 l= 3 prim:  INTEGER           :010001

现在,为了获取此偏移量,我们尝试默认的 asn1parse

$ openssl asn1parse -i -in pub0.der -inform DER
 0:d=0  hl=4 l= 290 cons: SEQUENCE
 4:d=1  hl=2 l=  13 cons:  SEQUENCE
 6:d=2  hl=2 l=   9 prim:   OBJECT            :rsaEncryption
17:d=2  hl=2 l=   0 prim:   NULL
19:d=1  hl=4 l= 271 prim:  BIT STRING

我们需要获取 BIT 字符串部分,因此我们添加大小

< code>depth_0_header(4) + height_1_full_size(2 + 13) + Container_1_EOC_bit + BIT_STRING_header(4) = 24

这可以在以下位置更好地可视化:ASN.1 Parser, if you hover at tags, you will see the offsets

Another amazing resource: Microsoft 的 ASN.1 文档

Apart from the above answers, we can use asn1parse to get the values

$ openssl asn1parse -i -in pub0.der -inform DER -offset 24
0:d=0  hl=4 l= 266 cons: SEQUENCE
4:d=1  hl=4 l= 257 prim:  INTEGER           :C9131430CCE9C42F659623BDC73A783029A23E4BA3FAF74FE3CF452F9DA9DAF29D6F46556E423FB02610BC4F84E19F87333EAD0BB3B390A3EFA7FB392E935065D80A27589A21CA051FA226195216D8A39F151BD0334965551744566AD3DAEB53EBA27783AE08BAAACA406C27ED8BE614518C8CD7D14BBE7AFEBE1D8D03374DAE7B7564CF1182A7B3BA115CD9416AB899C5803388EE66FA3676750A77AC870EDA027DC95E57B9B4E864A3C98F1BA99A4726C085178EA8FC6C549BE5EDF970CCB8D8F9AEDEE3F5CFDE574327D05ED04060B2525FB6711F1D78254FF59089199892A9ECC7D4E4950E0CD2246E1E613889722D73DB56B24E57F3943E11520776BC4F
265:d=1  hl=2 l= 3 prim:  INTEGER           :010001

Now, to get to this offset,we try the default asn1parse

$ openssl asn1parse -i -in pub0.der -inform DER
 0:d=0  hl=4 l= 290 cons: SEQUENCE
 4:d=1  hl=2 l=  13 cons:  SEQUENCE
 6:d=2  hl=2 l=   9 prim:   OBJECT            :rsaEncryption
17:d=2  hl=2 l=   0 prim:   NULL
19:d=1  hl=4 l= 271 prim:  BIT STRING

We need to get to the BIT String part, so we add the sizes

depth_0_header(4) + depth_1_full_size(2 + 13) + Container_1_EOC_bit + BIT_STRING_header(4) = 24

This can be better visialized at: ASN.1 Parser, if you hover at tags, you will see the offsets

Another amazing resource: Microsoft's ASN.1 Docs

仙女山的月亮 2024-09-14 12:33:03

如果您需要解析脚本中的 ASN.1 对象,可以使用一个库: https://github.com /lapo-luchini/asn1js

为了进行数学计算,我发现 jsbn 很方便: http://www-cs-students.stanford.edu/~tjw/jsbn/

遍历 ASN.1 结构并提取 exp/mod/subject/etc。取决于你——我从来没有走到这一步!

If you need to parse ASN.1 objects in script, there's a library for that: https://github.com/lapo-luchini/asn1js

For doing the math, I found jsbn convenient: http://www-cs-students.stanford.edu/~tjw/jsbn/

Walking the ASN.1 structure and extracting the exp/mod/subject/etc. is up to you -- I never got that far!

清浅ˋ旧时光 2024-09-14 12:33:03

我设法找到这个解决方案的答案,必须执行javascript注入以安装 atob

const atob:any = require('atob');
asn1(pem: any){
      asn1parser.Enc.base64ToBuf = function (b64:any) {
    return asn1parser.Enc.binToBuf(atob(b64));
  };
  const dertest = asn1parser.PEM.parseBlock(pem).der;
   var hex = asn1parser.Enc.bufToHex(asn1parser.PEM.parseBlock(pem).der)
   var buf = asn1parser.ASN1.parse(dertest);
  var asn1 = JSON.stringify(asn1parser.ASN1.parse(dertest), asn1parser.ASN1._replacer, 2 );

I manage to find the answer for this solution, have to do javascript injection for this to install atob

const atob:any = require('atob');
asn1(pem: any){
      asn1parser.Enc.base64ToBuf = function (b64:any) {
    return asn1parser.Enc.binToBuf(atob(b64));
  };
  const dertest = asn1parser.PEM.parseBlock(pem).der;
   var hex = asn1parser.Enc.bufToHex(asn1parser.PEM.parseBlock(pem).der)
   var buf = asn1parser.ASN1.parse(dertest);
  var asn1 = JSON.stringify(asn1parser.ASN1.parse(dertest), asn1parser.ASN1._replacer, 2 );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文