如何在内置加密模块中从 n、e 创建 pkcs8-public-pem rsa 公钥

问题描述 投票:0回答:1

我有一个第三方 api,它返回 rsa 公钥的 n 和 e 值。我必须从 n,e 创建 rsa 公钥,然后用它来加密一些数据。

但是我找不到任何可以在节点的加密模块中创建 pkcs8-public-pem 形式的 rsa 公钥的 api。

https://nodejs.org/api/crypto.html#cryptocreatepublickeykey.

现在我必须使用像

node-rsa
这样的第三方库来创建公钥。

const NodeRSA = require('node-rsa');
const crypto = require('crypto');

// create an empty key
const key = new NodeRSA();
// create special public key from n and e
key.importKey({
    n: Buffer.from('0086fa9ba066685845fc03833a9699c8baefb53cfbf19052a7f10f1eaa30488cec1ceb752bdff2df9fad6c64b3498956e7dbab4035b4823c99a44cc57088a23783', 'hex'),
    e: 0x10001,
}, 'components-public');
publicKey = key.exportKey('pkcs8-public-pem');

// TODO: use crypto.createPublicKey() instead of NodeRSA
// crypto.createPublicKey()

const data = '123';
encryptedText = crypto.publicEncrypt(publicKey, Buffer.from(data))
console.info(`Encrypted text: ${encryptedText.toString('base64')}`);
node.js cryptography rsa public-key-encryption
1个回答
0
投票

我创建了一个js函数来实现这个。


function create_crypto_public_key(n, e) {
    // The n hex value is always prefixed 00, why?
    if (!n.startsWith('00')) {
        n = `00${n}`
    }
    const hex_length = (hex_str) => {
        // fix the data if the length is even
        if (hex_str.length % 2 == 1) {
            hex_str = `0${hex_str}`
        }
        calculated_length = (hex_str.length / 2).toString(16)
        // if the length is even like '101', then the expected returns should be '0101'
        if (calculated_length.length % 2 == 1) {
            calculated_length = `0${calculated_length}`
        }
        // extra length byte is needed if the length is larger than 127
        // see http://luca.ntop.org/Teaching/Appunti/asn1.html
        if (calculated_length.length / 2 > 1) {
            calculated_length = `${(0x80 | calculated_length.length / 2).toString(16)}${calculated_length}`
        }
        return calculated_length
    }
    // https://polarssl.org/kb/cryptography/asn1-key-structures-in-der-and-pem/
    // The ASN.1 structure for a public key is:
    // RSAPublicKey ::= SEQUENCE {
    //     modulus           INTEGER,  -- n
    //     publicExponent    INTEGER   -- e
    // }
    asn1_part_n_hex_string = `02${hex_length(n)}${n}`
    asn1_part_e_hex_string = `02${hex_length(e)}${e}`
    asn1_hex_string = `30${hex_length(asn1_part_n_hex_string + asn1_part_e_hex_string)}${asn1_part_n_hex_string}${asn1_part_e_hex_string}`
    public_key_pkcs1_der = Buffer.from(asn1_hex_string, 'hex');
    return crypto.createPublicKey({ key: public_key_pkcs1_der, format: 'der', type: 'pkcs1' });
}
n = 'B347A3185DE515D6E123A94CDA2DB2884892A7F27D40B536A8E258F4DF8531029A2997F37994940E1CBAE09E96975482CCB99C37E71E6B83E86EEE1AC82F73CA084D3354765EE9B671DAB0E9DE5F2EDB798DF88CFA4C6586F84440A66AEEAD352901BE9CE8F49872E9DA53A9329F2197128F097CD3ECA99C91B93032F3D30F655C1C540BC71BD53DA7BE933433367FFE247BC0D51CF5905395589079B6B98AC5826741BF08762937F4B56C30669778E2EFE58565D029040E96579488468693A81B85FBC29641DD55A39254FBB7E1DF9F4F1540125C233758DB3C0BCFADEFF7A9FC3CAE2366B419776B35BE60CE8BBE1460F84C74AC068951FD26AD5EE6EB6BE1'
e = '010001'

key_object = create_crypto_public_key(n, e)

publicKey = key_object.export({ type: 'spki', format: 'pem' })
console.info(`publicKey: ${publicKey}`)

encryptedText = crypto.publicEncrypt(publicKey, Buffer.from(data))
console.info(`Encrypted text: ${encryptedText.toString('base64')}`);
© www.soinside.com 2019 - 2024. All rights reserved.