javascript - 来自 PEM 的 SubtleCrypto importKey

标签 javascript ionic-framework

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

window.crypto.subtle.importKey 似乎有问题 - 我在尝试时遇到了 Uncaught (in promise): DataError导入 key 。

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

//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 公钥导入 key 失败?

最佳答案

我自己已经花了很长时间来解决这个错误,现在我确信我可以给你(和其他任何人)一些关于这个的好建议。

  1. 您正在将“pkcs8”作为一种格式传递给 importKey 方法,但如果您正在导入一个 PUBLIC key ,该格式很可能是“spki”(SubjectPublicKeyInfo) 一种用于公钥的特殊格式,而“pkcs8”应该用于私钥。这就把我们带到了下一点:

  2. 你从哪里得到这个 key ?如果您使用 OpenSSL cli (openssl rsa -pubout -in priv.pem -out pub.pem) 导出公钥,那么您将获得“spki”格式(默认格式)的 key 。

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

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

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

关于javascript - 来自 PEM 的 SubtleCrypto importKey,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54742554/

相关文章:

javascript - 用于确认删除的模态对话框

javascript - 如何使应用程序中的日期字段独立于系统时区?

angularjs - $cordovaSQLite.execute 不是 ionic 中的函数

javascript - 函数中 $cordovaDialogs 的回调/ promise

javascript - a-google-place 自动完成选择的回调

javascript - Handlebars 和缓存(模板未更新)

javascript - 无法在模块外访问 Vuex getter

javascript - 如何在 window.onscroll 事件期间只调用一次 javascript 函数?

javascript - ngCordova 无法识别相机、手电筒或 Android 手机的其他部分

facebook - 无法使用 ionic 登录(无法通过网络浏览器进行身份验证)