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

Openssl RSA:获得给定公钥的指数和模,openssl,rsa,public-key,Openssl,Rsa,Public Key,我需要在JavaScript中使用RSA加密一些数据。周围所有的库都要求一个指数和一个模,但我从我的对手那里得到了一个public.key文件 如何从RSA文件中检索公共指数和模数部分?这取决于您可以使用的工具。我怀疑是否有JavaScript也可以直接在浏览器中实现这一点。这还取决于它是一次性的(总是相同的键),还是需要编写脚本 命令行/OpenSSL 如果您想在unix命令行上使用类似OpenSSL的东西,可以执行以下操作。 我假设您的public.key文件包含如下内容: -----BEG

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


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

这取决于您可以使用的工具。我怀疑是否有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-----
    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 
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.
}
然后,命令将是:

PUBKEY=`grep -v -- ----- public.key | tr -d '\n'`
然后,您可以查看ASN.1结构:

echo $PUBKEY | base64 -d | openssl asn1parse -inform DER -i
这应该会给你这样的东西:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmBAjFv+29CaiQqYZIw4P
J0q5Qz2gS7kbGleS3ai8Xbhu5n8PLomldxbRz0RpdCuxqd1yvaicqpDKe/TT09sR
mL1h8Sx3Qa3EQmqI0TcEEqk27Ak0DTFxuVrq7c5hHB5fbJ4o7iEq5MYfdSl4pZax
UxdNv4jRElymdap8/iOo3SU1RsaK6y7kox1/tm2cfWZZhMlRFYJnpoXpyNYrp+Yo
CNKxmZJnMsS698kaFjDlyznLlihwMroY0mQvdD7dCeBoVlfPUGPAlamwWyqtIU+9
5xVkSp3kxcNcNb/mePSKQIPafQ1sAmBKPwycA/1I5nLzDVuQa95ZWMn0JkphtFIh
HQIDAQAB
-----END PUBLIC KEY-----
    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 
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.
}
模数和公共指数位于最后一位字符串偏移量19中,因此使用
-strparse

 echo $PUBKEY | base64 -d | openssl asn1parse -inform DER -i -strparse 19
这将给出十六进制的模数和公共指数(两个整数):

如果始终使用同一个键,这可能很好,但这可能不太方便放入脚本

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

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

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

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmBAjFv+29CaiQqYZIw4P
J0q5Qz2gS7kbGleS3ai8Xbhu5n8PLomldxbRz0RpdCuxqd1yvaicqpDKe/TT09sR
mL1h8Sx3Qa3EQmqI0TcEEqk27Ak0DTFxuVrq7c5hHB5fbJ4o7iEq5MYfdSl4pZax
UxdNv4jRElymdap8/iOo3SU1RsaK6y7kox1/tm2cfWZZhMlRFYJnpoXpyNYrp+Yo
CNKxmZJnMsS698kaFjDlyznLlihwMroY0mQvdD7dCeBoVlfPUGPAlamwWyqtIU+9
5xVkSp3kxcNcNb/mePSKQIPafQ1sAmBKPwycA/1I5nLzDVuQa95ZWMn0JkphtFIh
HQIDAQAB
-----END PUBLIC KEY-----
    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 
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。)

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

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

示例模数包含257个字节,而不是256个字节,这是因为00,包括它是因为98中的9看起来像一个负号。

如果需要在脚本中解析ASN.1对象,有一个库:

对于数学运算,我发现jsbn很方便:


遍历ASN.1结构并提取exp/mod/subject/etc取决于您——我从来没有走那么远

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

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

当然,这只适用于私钥。

除了上述答案之外,我们还可以使用
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
我们需要得到位字符串部分,所以我们添加大小

深度0头(4)+深度1头(2+13)+容器1头(EOC)位+位字符串头(4)=24

如果将鼠标悬停在标记处,可以在以下位置更好地看到偏移


另一个惊人的资源:

我设法找到了这个问题的答案,必须为此进行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 );

+回答得好。查看PEMReader.java的源代码,它是一个真正的主力。它将检测和读取各种变体,并返回适当的对象。另一种可能的格式是X509EncodedKeySpec,它是由javaRSAPublicKey中的RSAPublicKey.getEncoded()返回的。getEncoded()将返回字节[]数组,该数组的内容与PEM格式的开始/结束公钥之间的内容相同,除了base64编码用于文本呈现。实际上,您可以在不使用BouncyCastle的情况下使用X509EncodedKeySpec,但您必须执行base64解码,然后使用java.security.KeyFactory来构建实际的RSAPublicKey。这是可行的,但我更喜欢使用BC。非常感谢布鲁诺。我将使用命令行版本…您可以对私钥执行类似的操作吗?得到指数了吗?谢谢(1) 您不需要自己为
openssl asn1parse
解码PEM,它可以处理PEM(这甚至是默认值);它甚至可以处理PEM主体(DER的base64带有换行符,但没有开始/结束线)。只是不要在PEM区块之外包含任何“评论”;许多其他的
openssl
命令可以处理这个问题,但不是
asn1parse
(2)自2012年1.47版本以来,BouncyCastle在
bcpkix
not
bcprov
中安装了PEMReader,自2013年1.50版本以来,它被重命名为PEMParser;对于返回
X509CertificateHolder
而不是
X509Certificate
的证书,对于返回
SubjectPublicKeyInfo
的公钥,您找到解决方案了吗?不是针对2014年6.5以来由
ssh keygen-o
生成的私钥,也不是从2018年7.8起默认(没有
-m pem
)生成的私钥;那些使用OpenSSH专有格式的
openssl
无法读取。OpenSSL也无法读取OpenSSH的
id_xxx.pub
,但
ssh-keygen-e-m pkcs8
,因为大约6.0会输出一个PEM公钥,可由
OpenSSL rsa-pubin-text-noout
读取(如Bruno很久以前的回答)