如何在Node.js中使用C#生成的XML格式RSA公钥加密字符串?
在Node.js中使用C#生成的XML格式RSA公钥加密字符串
我来帮你搞定这个需求——Node.js本身不直接支持C#那种XML格式的RSA公钥,所以核心步骤是先把XML密钥转成Node.js crypto模块能识别的PEM格式,再用标准的RSA加密流程处理字符串。下面是具体实现方案:
步骤1:将XML公钥转换为PEM格式
C#生成的XML RSA公钥包含Modulus和Exponent两个核心字段,我们需要把这两个字段提取出来,按照PKCS#1的标准组装成PEM格式的公钥。
写个通用的转换函数:
const crypto = require('crypto'); function xmlRsaPublicKeyToPem(xmlKey) { // 从XML中提取Modulus和Exponent const modulusMatch = xmlKey.match(/<Modulus>([^<]+)<\/Modulus>/); const exponentMatch = xmlKey.match(/<Exponent>([^<]+)<\/Exponent>/); if (!modulusMatch || !exponentMatch) { throw new Error('无效的XML格式RSA公钥'); } // 将base64编码的Modulus和Exponent转为Buffer const modulus = Buffer.from(modulusMatch[1], 'base64'); const exponent = Buffer.from(exponentMatch[1], 'base64'); // 组装PKCS#1标准的ASN.1结构(RSA公钥的序列格式) const totalLength = 6 + modulus.length + exponent.length; const buffer = Buffer.alloc(8 + modulus.length + exponent.length); buffer.writeUInt8(0x30, 0); // ASN.1 SEQUENCE标签 buffer.writeUInt16BE(totalLength, 1); // 序列总长度 buffer.writeUInt8(0x02, 3); // INTEGER标签(对应Modulus) buffer.writeUInt16BE(modulus.length, 4); // Modulus的长度 modulus.copy(buffer, 6); // 写入Modulus内容 buffer.writeUInt8(0x02, 6 + modulus.length); // INTEGER标签(对应Exponent) buffer.writeUInt16BE(exponent.length, 7 + modulus.length); // Exponent的长度 exponent.copy(buffer, 9 + modulus.length); // 写入Exponent内容 // 转换为PEM格式,按64字符换行 const pemContent = buffer.toString('base64').match(/.{1,64}/g).join('\n'); return `-----BEGIN RSA PUBLIC KEY-----\n${pemContent}\n-----END RSA PUBLIC KEY-----`; }
步骤2:使用PEM公钥加密字符串
拿到PEM格式的公钥后,就可以用crypto.publicEncrypt方法加密字符串了。注意要和C#默认的填充方式保持一致(PKCS#1 v1.5),这样加密后的内容才能被C#正确解密。
加密函数示例:
function encryptWithRsaPublicKey(plainText, pemPublicKey) { const encryptedBuffer = crypto.publicEncrypt( { key: pemPublicKey, padding: crypto.constants.RSA_PKCS1_PADDING // 和C#默认的RSA填充方式匹配 }, Buffer.from(plainText, 'utf8') ); // 返回base64编码的加密结果 return encryptedBuffer.toString('base64'); }
完整使用示例
把上面的函数结合起来,测试你的公钥:
// 你的C#生成的XML公钥 const xmlPublicKey = `<RSAKeyValue><Modulus>mlDk9dIwcGJ+sS7kCOiG/xr/1RkM7v7/bUExalwSj7Q/Ul575l4cUGR1ZjC3BtEgmMZjW6xSRTCkgp0WMpdnXGmygV0mQbrAP32NTGoMoWgjTIevBbd+yOMfY8E87bUG0sYUA8+Wk55iEPk3O0Ua5FiLNWIqGTbrF2A5iSp1voc=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>`; try { // 转换XML公钥到PEM const pemKey = xmlRsaPublicKeyToPem(xmlPublicKey); // 要加密的字符串 const plainText = '这是需要加密的测试内容'; // 执行加密 const encryptedText = encryptWithRsaPublicKey(plainText, pemKey); console.log('加密结果:', encryptedText); } catch (error) { console.error('加密过程出错:', error.message); }
重要提示
- 长文本加密:RSA加密有明文长度限制(一般是密钥长度/8 - 11,比如2048位密钥最多加密245字节),如果要加密长文本,建议使用混合加密:先生成随机AES密钥,用AES加密长文本,再用RSA加密AES密钥,最后把加密后的AES密钥和AES加密文本一起传输。
- 填充方式一致性:如果你的C#代码使用了OAEP填充(比如
RSAEncryptionPadding.OaepSHA1),那么Node.js里需要把padding参数改成crypto.constants.RSA_PKCS1_OAEP_PADDING,同时指定哈希算法,比如:{ key: pemPublicKey, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, oaepHash: 'sha1' }
内容的提问来源于stack exchange,提问作者Kastet
相关产品推荐
相关产品推荐

