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

解决Cryptico.js RSA私钥导入browser.subtle的JWK解码报错问题

解决Cryptico.js RSA私钥导入browser.subtle的问题

问题描述

尝试将Cryptico.js生成的RSA私钥提取后导入browser.subtle,已添加decimalToBase64url函数处理密钥参数,但控制台提示错误:

"The JWK member "n" could not be base64url decoded or contained padding"

错误原因

原decimalToBase64url函数存在两个关键问题:

  • 十六进制字符串长度可能为奇数,导致Uint8Array构造失败(最后一个单字符十六进制无法正确转成字节)
  • 转换后的base64url未移除末尾的填充字符=,而JWK规范要求base64url编码不能包含填充
  • 额外问题:JWK字段名不符合规范,原代码中dmp1/dmq1/coeff对应的标准字段名应为dp/dq/qi

解决方案

1. 修正decimalToBase64url函数

确保十六进制字符串长度为偶数,并移除base64的填充字符:

function decimalToBase64url(decimal) {
  // 将BigInteger转为十六进制字符串,补前导零确保长度为偶数
  let hexString = decimal.toString(16);
  if (hexString.length % 2 !== 0) {
    hexString = '0' + hexString;
  }

  // 十六进制转Uint8Array
  const uint8Array = new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));

  // Uint8Array转base64,再转base64url并移除填充
  const base64 = btoa(String.fromCharCode.apply(null, uint8Array));
  return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}

2. 完整修正后的转换函数

async function convertCrypticoToCryptoKeyPair(crypticoKey) {
  const n = decimalToBase64url(crypticoKey.n);
  const e = decimalToBase64url(crypticoKey.e);
  const d = decimalToBase64url(crypticoKey.d);
  const p = decimalToBase64url(crypticoKey.p);
  const q = decimalToBase64url(crypticoKey.q);
  const dp = decimalToBase64url(crypticoKey.dmp1);
  const dq = decimalToBase64url(crypticoKey.dmq1);
  const qi = decimalToBase64url(crypticoKey.coeff);

  const jwkPrivateKey = {
    kty: "RSA",
    n,
    e,
    d,
    p,
    q,
    dp,
    dq,
    qi,
  };

  const privateKey = await crypto.subtle.importKey(
    "jwk",
    jwkPrivateKey,
    { name: "RSA-PSS", hash: { name: "SHA-256" } },
    true,
    ["sign"]
  );

  const publicKey = await crypto.subtle.importKey(
    "jwk",
    { kty: "RSA", n, e },
    { name: "RSA-PSS", hash: { name: "SHA-256" } },
    true,
    ["verify"]
  );

  return { privateKey, publicKey };
}

// 测试代码
const PassPhrase = "your_passphrase";
const Bits = 2048;
const crypticoRSAKey = cryptico.generateRSAKey(PassPhrase, Bits);

convertCrypticoToCryptoKeyPair(crypticoRSAKey).then((keyPair) => {
  console.log("转换成功的CryptoKeyPair:", keyPair);
}).catch(err => {
  console.error("转换失败:", err);
});

3. Cryptico.js扩展代码(参考)

// Export RSA key@furkan-bilgin
my.exportRSAKey = function(rsaKey) 
{
    return JSON.stringify(rsaKey);
}

/*
method 2 Hex @zwisler-a 
function serializeRSAKey(key) {
    return JSON.stringify({
      coeff: key.coeff.toString(16),
      d: key.d.toString(16),
      dmp1: key.dmp1.toString(16),
      dmq1: key.dmq1.toString(16),
      e: key.e.toString(16),
      n: key.n.toString(16),
      p: key.p.toString(16),
      q: key.q.toString(16)
    })
  }
*/

内容的提问来源于stack exchange,提问作者Ka Fong

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 12:05:11