NodeJS中使用证书公钥调用Crypto.publicEncrypt()报错求助
Node.js v16/v17中使用证书公钥调用crypto.publicEncrypt()报错的解决方法
问题场景
使用Node.js v16/v17版本,尝试通过PEM格式的证书公钥调用crypto.publicEncrypt()加密数据,两段测试代码均报错:
- 测试代码1:
const pkey = '-----BEGIN CERTIFICATE-----\n <Encoding>\n -----END CERTIFICATE-----' const pubPemKey = crypto.createPublicKey(pkey) const pubPemKeyStr = pubPemKey.export({ type: 'spki', format: 'pem' }) console.log(pubPemKeyStr) const encryptedData = crypto.publicEncrypt(pubPemKeyStr, Buffer.from('test'))
- 测试代码2:
const encryptedKey = crypto.publicEncrypt({ key: pkey, padding: crypto.constants.RSA_PKCS1_PADDING }, Buffer.from(plainText))
报错信息:
node:internal/crypto/cipher:79 return method(data, format, type, passphrase, buffer, padding, oaepHash, ^ Error: error:0608B096:digital envelope routines:EVP_PKEY_encrypt_init:operation not supported for this keytype at Object.publicEncrypt (node:internal/crypto/cipher:79:12) at Object.<anonymous> (/home/jdoodle.js:28:30) at Module._compile (node:internal/modules/cjs/loader:1097:14) at Object.Module._extensions..js (node:internal/modules/cjs/loader:1149:10) at Module.load (node:internal/modules/cjs/loader:975:32) at Function.Module._load (node:internal/modules/cjs/loader:822:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) at node:internal/main/run_main_module:17:47 { library: 'digital envelope routines', function: 'EVP_PKEY_encrypt_init', reason: 'operation not supported for this keytype', code: 'ERR_OSSL_EVP_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE' }
解决方法
核心原因
PEM格式的证书并非直接可用于加密的公钥,它包含公钥、身份信息及签名等额外数据。直接传入证书会导致Node.js无法识别正确的加密密钥类型,因此触发报错。
步骤与修正代码
- 从证书中提取出可用于加密的纯公钥
- 使用提取后的公钥执行加密操作
修正后的示例代码:
const crypto = require('crypto'); // 替换为你的实际证书PEM内容 const certPem = `-----BEGIN CERTIFICATE----- <你的证书编码内容> -----END CERTIFICATE-----`; // 从证书创建KeyObject const certKey = crypto.createPublicKey(certPem); // 导出SPKI格式的纯公钥(可直接用于加密) const publicKey = certKey.export({ type: 'spki', format: 'pem' }); // 执行加密,根据需求指定合适的padding规则 const encryptedData = crypto.publicEncrypt( { key: publicKey, padding: crypto.constants.RSA_PKCS1_PADDING }, Buffer.from('test') ); // 输出加密后的base64格式内容 console.log(encryptedData.toString('base64'));
额外注意事项
- 确认证书公钥算法支持加密:可以通过
certKey.asymmetricKeyType查看密钥类型,rsa类型默认支持加密;若为ec(椭圆曲线)类型,需确保使用的EC算法支持加密操作(部分EC密钥仅用于签名)。 - 若直接使用KeyObject加密,需确保该对象对应的是提取后的纯公钥而非原始证书容器,避免再次触发类型不兼容报错。
内容的提问来源于stack exchange,提问作者Sree
相关产品推荐
相关产品推荐

