提问者:小点点

如何在Node. js中获取RSA公钥的模和指数


我正在创建一个ACME客户端,我需要找到我的RSA公钥的模和指数,我使用以下代码生成:

crypto.generateKeyPairSync('rsa', {
    modulusLength: 4096,
    publicKeyEncoding: {
        type: 'spki',
        format: 'pem'
    },
    privateKeyEncoding: {
        type: 'pkcs8',
        format: 'pem'
    }
});

我需要模数和指数,以便我可以在JWS的JWK部分中使用它们:

alg: 'RS256',
jwk: {
    kty: 'RSA',
    e: '...',
    n: '...'
},
nonce,
url: directory.newAccount

我已经设法使用以下行将公钥从base64解码为十六进制,但我不确定下一步该做什么:

Buffer.from(publicKey, 'base64').toString('hex');

如何在Node. js中找到RSA公钥的模和指数?

我发现Node. js默认使用公共指数65537:Node.js留档。


共3个答案

匿名用户

这很容易;它不需要第三方库

import { createPublicKey } from 'crypto'

const pemPublicKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAphRAj+tRfbrYwnSFbWrj
...
vQIDAQAB
-----END PUBLIC KEY-----
`
const publicKey = createPublicKey(pemPublicKey)
console.log(publicKey.export({ format: 'jwk' }))

它将返回对象:

{
  kty: 'RSA',
  n: [modulus string],
  e: [exponent string]
}

匿名用户

扩展@Topaco给出的注释,像这样使用库pem-jwk:

const pem2jwk = require('pem-jwk').pem2jwk

console.log(pem2jwk(pemPublicKey));
OUTPUT:
{
  kty: '...',
  n: '...',
  e: '...'
}

console.log(pem2jwk(pemPrivateKey));
OUTPUT:
{
  kty: '...',
  n: '...',
  e: '...',
  d: '...',
  p: '...',
  q: '...',
  dp: '...',
  dq: '...',
  qi: '...'
}

匿名用户

有一些为浏览器和node. js编写的库非常好。你可以在这里找到它们。

包括文件并尝试此功能,

function RSAModulusAndExponent(pubkey) {
        var unarmor = /-----BEGIN PUBLIC KEY-----([A-Za-z0-9+\/=\s]+)-----END PUBLIC KEY-----/;
         try{
            var pubkeyAsn1 = ASN1.decode(Base64.decode(unarmor.exec(pubkey)[1]));
            var modulusRaw = pubkeyAsn1.sub[1].sub[0].sub[0];
            var modulusStart = modulusRaw.header + modulusRaw.stream.pos + 1;
            var modulusEnd = modulusRaw.length + modulusRaw.stream.pos + modulusRaw.header;
            var modulusHex = modulusRaw.stream.hexDump(modulusStart, modulusEnd);
            var modulus = Hex.decode(modulusHex);
            var exponentRaw = pubkeyAsn1.sub[1].sub[0].sub[1];
            var exponentStart = exponentRaw.header + exponentRaw.stream.pos;
            var exponentEnd = exponentRaw.length + exponentRaw.stream.pos + exponentRaw.header;
            var exponentHex = exponentRaw.stream.hexDump(exponentStart, exponentEnd);
            var exponent = Hex.decode(exponentHex);
            
            return { success:true, msg:{moduls: modulus, exponent: exponent}};
        }
        catch(err){ console.log(err)
            return { success:false, msg:"Failed validating RSA public key."};
        }
    }

这就是模数和指数。

对于节点上的公钥验证,我推荐
node-jose(或)NodeRSA

const key = new NodeRSA(pubKey);   

if(key.isPublic && !key.isEmpty() && key.getKeySize() > 0)
        return {error: false, msg : "RSA Public key validation success! (Reason, isPublic?"+key.isPublic()+", isEmpty?"+key.isEmpty()+", Key length : " + key.getKeySize()+" )"}
 else
        return {error: false, msg : "RSA Public key validation failed! (Reason, isPublic?"+key.isPublic()+", isEmpty?"+key.isEmpty()+", Key length : " + key.getKeySize()+" )"}

我只是提出了一个想法。库中还有其他功能足以确保公钥正常。

此外,您在命令行上有节点。您可以使用openssl看到原始格式。在这里查看更多,OpenSSL手册

openssl asn1parse -in your_public.key