来自PEM的SubtleCrypto importKey

时间:2019-02-18 07:48:02

标签: javascript ionic-framework

我正在尝试使用Ionic中的SubtleCrypto Web API使用公共密钥加密数据。我以PEM格式导入密钥,然后将其传递到window.crypto.subtle.importKey,然后将结果用于window.crypto.subtle.encrypt

window.crypto.subtle.importKey似乎有问题-尝试导入密钥时出现Uncaught (in promise): DataError

我目前正在使用以下方法导入密钥:

//Get the public key in CryptoKey format
let importedPublicKey = await window.crypto.subtle.importKey(
    "pkcs8",
    this.pemPublicToArrayBuffer(serverPublicKey),
    {
        name: "RSA-OAEP",
        hash: {name: "SHA-256"}
    },
    true,
    []
);

private pemPublicToArrayBuffer(pem) {
  var b64Lines = this.removeLines(pem);
  var b64Prefix = b64Lines.replace('-----BEGIN PUBLIC KEY-----', '');
  var b64Final = b64Prefix.replace('-----END PUBLIC KEY-----', '');

  return this.base64ToArrayBuffer(b64Final);
}

private base64ToArrayBuffer(b64) {
  var byteString = window.atob(b64);
  var byteArray = new Uint8Array(byteString.length);
  for (var i = 0; i < byteString.length; i++) {
    byteArray[i] = byteString.charCodeAt(i);
  }

  return byteArray;
}

有人知道为什么PEM公钥导入失败吗?

1 个答案:

答案 0 :(得分:1)

我本人花了很多时间来解决这个错误,现在我可以为您(和其他任何人)提供一些好的建议。

  1. 您正在将“ pkcs8”作为格式传递给importKey方法,但是如果您要导入PUBLIC密钥,则该格式很可能是公用密钥的特殊格式“ spki”(SubjectPublicKeyInfo),而“ pkcs8”应该用于专用密钥。这就引出了下一个要点:

  2. 您从何处获得此密钥?如果您要使用OpenSSL cli导出公共密钥(openssl rsa -pubout -in priv.pem -out pub.pem),那么您将获得“ spki”格式的密钥(默认值)。

  3. 如果要导入PUBLIC密钥,则应将[“ encrypt”]作为“用法”参数传递给importKey(而不是空数组),否则,将出现以下错误之一: “ SyntaxError:无法使用指定的密钥用法创建密钥”(为密钥指定了错误的用法)或“ InvalidAccessError:key.usages不允许此操作”(用法的空数组)。 这里要记住的是,公钥只能用于[“ encrypt”],而私钥只能用于[“ decrypt”]。虽然我没有尝试导入密钥对,但是据我了解,您应该将“ pkcs8”作为一种格式传递,并将[“ encrypt”,“ decrypt”]用作用法。

  4. 即使您正确地设置了上述所有内容,您仍然可能会收到讨厌的“未捕获(承诺):DataError”,对我来说,这是由于格式不匹配,我一直在传递密钥带有“ spki”参数的PKCS#1 RSAPublicKey格式。因此,您可能应该从检查密钥开始,以从中获取确切的格式和算法详细信息。

希望这对某人有帮助。 伊万