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

使用node-forge解析DER格式公钥文件,EDDSA/ECDSA算法报Unknown OID错误的问题

node-forge解析DER格式公钥文件,EDDSA/ECDSA算法报Unknown OID错误的问题

你碰到的这个问题我之前也遇到过——forge.pki.publicKeyFromAsn1()这个方法其实是专门为RSA公钥设计的,它只能识别RSA对应的算法OID,ECDSA和EDDSA的公钥结构与OID不在它的默认处理逻辑里,所以直接调用就会抛出"Unknown OID"的错误。

解决思路很明确:我们需要先解析DER文件的ASN.1结构,识别出公钥的算法类型,再针对不同算法调用node-forge提供的对应解析方法。下面是修改后的完整函数,我会逐点解释关键变化:

const uploadDer = (file: any): boolean => {
  const fileReader = new FileReader();

  fileReader.onload = () => {
    const arrayBuffer = fileReader.result as ArrayBuffer;

    try {
      const uint8Array = new Uint8Array(arrayBuffer);
      const byteBuffer = forge.util.createBuffer(uint8Array);
      const asnObject = forge.asn1.fromDer(byteBuffer);
      
      // 关键:先解析公钥的算法OID,判断公钥类型
      let publicKeyObject;
      // 标准DER公钥的结构是SubjectPublicKeyInfo,是一个ASN.1序列
      if (forge.asn1.isSequence(asnObject)) {
        // 序列的第一个元素是算法标识序列,里面包含算法OID
        const algorithmSeq = asnObject.value[0];
        const algorithmOid = algorithmSeq.value[0].value;
        
        // 根据OID匹配不同的公钥算法
        switch (algorithmOid) {
          // RSA算法对应的OID
          case '1.2.840.113549.1.1.1':
            publicKeyObject = forge.pki.publicKeyFromAsn1(asnObject);
            break;
          // ECDSA(椭圆曲线公钥算法)对应的OID
          case '1.2.840.10045.2.1':
            publicKeyObject = forge.pki.ec.publicKeyFromAsn1(asnObject);
            break;
          // Ed25519(EDDSA的常用曲线)对应的OID
          case '1.3.101.112':
            // EDDSA的公钥在ASN.1里是BIT STRING,需要提取原始字节(跳过第一个bit长度字节)
            const eddsaPubKeyBitString = asnObject.value[1];
            const eddsaRawBytes = eddsaPubKeyBitString.value.slice(1);
            publicKeyObject = forge.eddsa.publicKeyFromRaw('Ed25519', eddsaRawBytes);
            break;
          // 如果是Ed448曲线,可以添加这个case
          // case '1.3.101.113':
          //   const ed448RawBytes = asnObject.value[1].value.slice(1);
          //   publicKeyObject = forge.eddsa.publicKeyFromRaw('Ed448', ed448RawBytes);
          //   break;
          default:
            throw new Error(`不支持的公钥算法OID: ${algorithmOid}`);
        }
      } else {
        throw new Error('无效的DER公钥结构');
      }

      // 转换为PEM格式(node-forge的publicKeyToPem已支持EC和EDDSA)
      const fileContent = forge.pki.publicKeyToPem(publicKeyObject);
      console.log('fileContent-->', fileContent);

      const pemSections = forge.pem.decode(fileContent);
      const lastPemSection = pemSections[pemSections.length - 1];
      const publicKey = forge.util.encode64(lastPemSection.body);
      props.change('publicKey', publicKey);
    } catch (error) {
      props.change('publicKey', '');

      return dispatch(
        showNotification({
          id: uuidv1(),
          title: 'statusTitle',
          message: 'uploadKeypairFailedMessage',
          type: NotificationTypes.error,
        })
      );
    }
  };

  fileReader.onerror = (error) => {
    console.error('文件读取错误:', error);
  };

  fileReader.readAsArrayBuffer(file);

  return false;
};

关键变化解释:

  1. 识别算法OID:
    标准的DER公钥采用SubjectPublicKeyInfo结构,这是一个ASN.1序列,第一个子元素是算法标识序列,里面的第一个值就是算法的OID。我们通过这个OID来区分RSA、ECDSA、EDDSA。
  2. 对应解析方法:
    • RSA:继续使用原来的forge.pki.publicKeyFromAsn1()
    • ECDSA:调用node-forge专门的EC公钥解析方法forge.pki.ec.publicKeyFromAsn1()
    • EDDSA:需要从ASN.1的BIT STRING中提取原始公钥字节(跳过第一个表示bit长度的字节),再用forge.eddsa.publicKeyFromRaw()构造公钥对象
  3. 版本兼容:
    确保你的node-forge版本是v0.10.0及以上,早期版本对EDDSA的支持可能不完善,建议升级到最新稳定版。

如果还是遇到问题,可以在解析ASN.1后打印结构,确认公钥格式是否符合预期:

console.log('ASN.1公钥结构:', forge.asn1.toPretty(asnObject));

备注:内容来源于stack exchange,提问作者phoenix567sid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 13:39:32