0

我正在做一个简单的概念证明,通过 node.js 和使用 SubtleCrypto 的浏览器通信导出和导入私钥和公钥。我已经安装了 @peculiar/webcrypto 包来保持前端和后端之间的一致性。第一部分只是密钥的生成和导出,第二部分是我尝试导入密钥。这是代码:

// GENERATE AND EXPORT KEYS
const { publicKey, privateKey } = await crypto.subtle.generateKey(
  {
    name: 'RSA-OAEP',
    modulusLength: 2048,
    publicExponent: new Uint8Array([1, 0, 1]),
    hash: 'SHA-256',
  },
  true,
  ['encrypt', 'decrypt'],
);
const publicExport = await crypto.subtle.exportKey('spki', publicKey);
const privateExport = await crypto.subtle.exportKey('pkcs8', privateKey);

const pubExportedAsString = ab2str(publicExport);
const pubExportedAsBase64 = btoa(pubExportedAsString);
const publicKeyPem = `${pubExportedAsBase64}`;

const privExportedAsString = ab2str(privateExport);
const privExportedAsBase64 = btoa(privExportedAsString);
const privateKeyPem = `${privExportedAsBase64}`;

// IMPORT KEYS
const pubKeyImportedAsString = atob(publicKeyPem);
const pubKeyImportedAsArrayBuffer = str2ab(pubKeyImportedAsString);
const publicKeyImport = await crypto.subtle.importKey(
  'spki', pubKeyImportedAsArrayBuffer, { name: 'RSA-OAEP', hash: 'SHA-256' }, true, ['encrypt']
);

const privateKeyImportedAsString = atob(privateKeyPem);
const privateKeyImportedAsArrayBuffer = str2ab(privateKeyImportedAsString);
const privateKeyImport = await crypto.subtle.importKey(
  'pkcs8', privateKeyImportedAsArrayBuffer, { name: 'RSA-OAEP', hash: 'SHA-256' }, true, ['decrypt']
);

// HELPERS

const ab2str = (buffer: ArrayBuffer): string => new TextDecoder().decode(buffer);

const str2ab = (text: string): ArrayBuffer => new TextEncoder().encode(text);

键的导入是引发错误的地方:

Unhandled error Error: Too big integer

我似乎看不出问题出在哪里,以及为什么密钥编码和解码会失败。如果有人有任何线索或想法,那将非常有帮助:)

4

1 回答 1

0

想通了(对于任何处于类似困境的人)。原来问题是 ab2str 和 str2ab 辅助函数,我被误导相信 TextDecoder/TextEncoder 会正确处理这个用例的转换。

将这些重写为以下解决了这个问题!

const ab2str = (buffer: ArrayBuffer) =>
  String.fromCharCode.apply(null, Array.from(new Uint8Array(buffer)));

const str2ab = (str: string): ArrayBuffer => {
  const buffer = new ArrayBuffer(str.length * 2);
  const bufferInterface = new Uint8Array(buffer);
  Array.from(str)
    .forEach((_, index: number) => bufferInterface[index] = str.charCodeAt(index));
  return buffer;
}
于 2021-04-13T21:58:45.087 回答