【问题标题】:How to export Web Crypto key to jsrsasign如何将 Web Crypto 密钥导出到 jsrsasign
【发布时间】:2015-11-16 15:34:15
【问题描述】:

我尝试用Web Crypto 生成一个RSA 密钥,并用它用jsrsasign (Firefox does not support RSA-PSS) 对一个字符串进行签名。因此,我导出 Web Crypto 密钥并将其转换为 PKCS8-PEM,但是当我调用 KEYUTIL.getKeyFromPlainPrivatePKCS8PEM 将密钥导入 jsrsasign 时,会引发错误:malformed plain PKCS8 private key(code:001)

我做错了什么? JSBin

window.crypto.subtle.generateKey(
  {
    name: "RSA-OAEP",
    modulusLength: 2048,
    publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
    hash: {name: "SHA-256"},
  },
  true,
  ["encrypt", "decrypt"]
)
.then(keyPair => window.crypto.subtle.exportKey("pkcs8", keyPair.privateKey))
.then(arrayBufferToBase64String)
.then(toPem)
.then(pem => {
  var rsa = KEYUTIL.getKeyFromPlainPrivatePKCS8PEM(pem); // throws: malformed plain PKCS8 private key(code:001)
  var sig = rsa.signStringPSS('text', 'sha256', 32);
  console.log('signature', sig);
})
.catch(::console.error)

function arrayBufferToString(arrayBuffer) {
  var byteArray = new Uint8Array(arrayBuffer)
  var byteString = '';
  for (var i=0; i<byteArray.byteLength; i++) {
    byteString += String.fromCharCode(byteArray[i]);
  }
  return byteString;
}

function arrayBufferToBase64String(arrayBuffer) {
  return btoa(arrayBufferToString(arrayBuffer));
}

function toPem(key) {
  return `
-----BEGIN RSA PRIVATE KEY-----
${key}
-----END RSA PRIVATE KEY-----
`;
}

编辑:

我才意识到jsrsasign可以处理jwk

window.crypto.subtle.generateKey(
  {
    name: "RSA-OAEP",
    modulusLength: 2048,
    publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
    hash: {name: "SHA-256"},
  },
  true,
  ["encrypt", "decrypt"]
)
.then(keyPair => window.crypto.subtle.exportKey("jwk", keyPair.privateKey))
.then(jwk => {
  var rsa = KEYUTIL.getKey(jwk);
  var sig = rsa.signStringPSS('text', 'sha256', 32);
  console.log('signature', sig);
})
.catch(::console.error)

我更喜欢这个解决方案,但我仍然想知道为什么我的 pkcs8 解决方案不起作用。

【问题讨论】:

    标签: javascript cryptography rsa pkcs#8 webcrypto-api


    【解决方案1】:

    将 PEM 标头从 "----BEGIN RSA PRIVATE KEY-----" 更改为 "-----BEGIN PRIVATE KEY-----" 不起作用,因为内容不同。我认为使用 JWK 进行文件导出是最好的方法,因为它在任何浏览器之间都具有很大的互操作性。我之前尝试过同样的事情,但是 PKCS#8 在某些浏览器上不起作用。

    正如 Felix 所述,您的 RSA 密钥是一个 PKCS#1 密钥,它具有 "-----BEGIN RSA PRIVATE KEY-----" PEM 标头。

    如果您需要将 PKCS#1 转换为 PKCS#8KEYUTIL 类可能很有用,如下例所示:

    keyobj = KEYUTIL.getKey("-----BEGIN RSA PRIVATE KEY-----..."); // your key
    pkcs8pem = KEYUTIL.getPEM(keyobj, "PKCS8PRV");
    

    【讨论】:

      【解决方案2】:

      由于“RSA”部分,您的 PEM 编码密钥实际上是 PKCS#1 而不是 PKCS#8。这只是 DER 中的 RSA 密钥对象,没有包含在序列中的密钥标识符。

      jsrsasign 正在寻找 PKCS#8 标头“BEGIN PRIVATE KEY”而不是“BEGIN RSA PRIVATE KEY”。更改标题使其工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-04-05
        • 1970-01-01
        • 2017-10-07
        • 1970-01-01
        • 2016-11-02
        • 1970-01-01
        • 2020-10-14
        • 1970-01-01
        相关资源
        最近更新 更多