You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中用Forge库按指定RSA填充加密AES密钥遇异常求助

加解密问题排查:RSA-OAEP加密后输出乱码

问题背景

从Java后端获取Base64格式的RSA公钥,需采用RSA/ECB/OAEPWithSHA-256AndMGF1Padding算法加密AES密钥,使用node-forge库实现后,得到的加密结果为乱码数据。

现有实现代码

const getPEMPublicKey = (publicKey) => {
  const pubKeyArr = publicKey.match(/.{1,64}/g)
  return '-----BEGIN PUBLIC KEY-----\n' + join(pubKeyArr, "\n") + '\n-----END PUBLIC KEY-----'
}

const encryptAESKey = (AESKey, publicKey) => {
  // encrypt data with a public key using RSAES-OAEP/SHA-256/MGF1-SHA-1
  // compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Padding
  const publicKeyPem = forge.pki.publicKeyFromPem(getPEMPublicKey(publicKey));
  const rsaEncryptedAesKey = publicKeyPem.encrypt(forge.util.encodeUtf8(AESKey), 'RSA-OAEP', {
    md: forge.md.sha256.create(),
    mgf1: {
      md: forge.md.sha1.create()
    }
  });
  return rsaEncryptedAesKey
}

异常输出

1]*Q^?o>Ãn±Ýut¼dªjfôUc$ÃÆ|&¾ZTW2
    ×é_Í>ú;î¥äÊæ[jU.<¡X3ßöAsÑg½LD¥º&ÍaÎòuHÍGHóº@|YÀWÇöõ<ðªK Î¶uäÚ³©Ëò­øUj·töTa:/Çý/L4x]äiXéqÅAFÓÌKwL B3$aÍB>ÕwÉÿ<[ò
    x"ÞåXàh\÷p;w<§÷RyÈL¬ð5EÁ9¿´,_Ö½<Áy×ÇÁÖ6

后端提供的Base64公钥示例

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm+m0v4JKo5lb6f6pypFG/xS4wzJEJ80m3SbXs7sTQtvgblrczyjKYm5oYOVG1onWJ8XmbEdDts/sIYBArc37xLtaOgYr480YU8aqj026qc2mblpTLkGJiye0z0LmpsoQXvqZ49UD+ZHG7PetkLgIW5H+ffw2vW4fdBi9fZU6jJ9z8dkv0PLtAZ2LEuVLAqEE6rHzmEc5EmfMy70/FCRZZShS2Yq76/qGgTzlVpzV4r4d0D83Zz+ZWIL1MISGk8x86moYzM2w+8o2N0V0cDayCQKnoEiNxSKXw3+uIyoqjR7gcdlqgWfl/Wb8G5W8TemnFkOMTuUq9tZlgoadyqxjtQIDAQAB

错误分析与解决思路

核心问题

node-forge的encrypt方法返回的是原始二进制字节流,直接输出或返回会显示为乱码,而Java后端通常期望接收Base64编码后的加密结果。此外代码中存在未定义函数的隐患。

具体修复步骤

  1. 修复PEM转换函数的语法错误
    代码中join(pubKeyArr, "\n")的join未定义,需改为数组原生的join方法:

    const getPEMPublicKey = (publicKey) => {
      const pubKeyArr = publicKey.match(/.{1,64}/g) || []; // 兼容公钥长度不足64的情况
      return '-----BEGIN PUBLIC KEY-----\n' + pubKeyArr.join("\n") + '\n-----END PUBLIC KEY-----';
    }
    
  2. 对加密结果进行Base64编码
    将加密后的二进制字节流转换为Base64字符串,确保和Java后端的格式兼容:

    const encryptAESKey = (AESKey, publicKey) => {
      const publicKeyPem = forge.pki.publicKeyFromPem(getPEMPublicKey(publicKey));
      // 注意:如果AESKey是Base64格式,需先解码为字节:const aesKeyBytes = forge.util.decode64(AESKey);
      const aesKeyBytes = forge.util.encodeUtf8(AESKey); // 若AESKey是明文字符串则用此,否则替换为decode64
      const rsaEncryptedBytes = publicKeyPem.encrypt(aesKeyBytes, 'RSA-OAEP', {
        md: forge.md.sha256.create(),
        mgf1: {
          md: forge.md.sha1.create()
        }
      });
      // 转换为Base64格式返回
      return forge.util.encode64(rsaEncryptedBytes);
    }
    
  3. 验证AES密钥输入格式
    确认传入的AESKey格式:如果是Base64编码的密钥,需先用forge.util.decode64解码为字节再加密;如果是明文密钥字符串,用forge.util.encodeUtf8转换为字节即可。

兼容性验证

Java的RSA/ECB/OAEPWithSHA-256AndMGF1Padding默认MGF1散列算法为SHA-1,和代码中的配置一致,这部分无需调整;示例公钥为标准PKCS#8格式,PEM转换逻辑正确。

内容的提问来源于stack exchange,提问作者Barbara Rekowska

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 14:20:48