如何解决在 Crypto 中复制 SubtleCrypto 时遇到问题
我有一些代码使用 SubtleCrypto 来加密密钥并将其存储在数据库中。
对于另一个功能,我必须能够在 Node 12 中对其进行加密。如果没有 SubtleCrypto,我必须在 Crypto 中重新创建该功能。
我得到相同大小的输出,但它似乎无法被 SubtleCrypto 解密,我正试图找出我哪里出错了。
这是在浏览器上使用 SubtleCrypto 运行的代码:
key = getKeyMaterial(password)];
salt = base64ToArraybuffer(optionalSalt)
aesKey = crypto.subtle.deriveKey(
{
name: constants.algorithms.pbkdf2,salt: salt,iterations: pbkdf2Iterations,hash: { name: constants.hash.sha256 },},key,{
name: constants.algorithms.aesGcm,length: aesWrapKeyBitsLength,true,['wrapKey','unwrapKey']
),return {
salt: arraybufferTobase64(salt),aesKey: aesKey,}
function getKeyMaterial(password) {
var enc = new TextEncoder();
crypto.subtle.importKey(
constants.format.raw,enc.encode(password),{
name: constants.algorithms.pbkdf2,false,['deriveKey']
)
如果没有 SubtleCrypto,在 Node 12 中,我不得不使用 Crypto 库。 这是我当前的代码迭代。
const ivByteLength = 12;
function wrapKey(privateKey,aesKey) {
const IV = crypto.randomBytes(ivByteLength);
const ALGORITHM = 'aes-256-gcm';
const cipher = crypto.createCipheriv(ALGORITHM,aesKey,IV);
let encrypted = cipher.update(privateKey,undefined,'binary');
encrypted += cipher.final('binary');
const authTag = cipher.getAuthTag();
encrypted += authTag;
const output = {
wrappedKey: arraybufferTobase64(Buffer.from(encrypted,'ascii')),iv: arraybufferTobase64(IV),};
return output;
}
async function deriveAesGcmKey(password,salt) {
return new Promise((resolve,reject) => {
crypto.pbkdf2(password,salt,100000,32,'sha256',(err,derivedKey) => {
if (err) reject(err);
else resolve(derivedKey);
});
});
}
function arraybufferTobase64(buffer) {
let binary = '';
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i += 1) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
function base64ToArraybuffer(base64) {
const binary = atob(base64);
const len = binary.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i += 1) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
封装的密钥在两种实现中具有相同的大小,但 Node 生成的密钥无法在浏览器中解开。
解决方法
NodeJS 在 webcrypto
包中有一个叫做 crypto
的类,它具有微妙的加密实现。
Docs 中的示例:
const { subtle } = require('crypto').webcrypto;
async function digest(data,algorithm = 'SHA-512') {
const ec = new TextEncoder();
const digest = await subtle.digest(algorithm,ec.encode(data));
return digest;
}
还可以查看:https://nodejs.org/api/webcrypto.html#webcrypto_class_subtlecrypto
编辑:
正如在较低版本的 Node 的评论中所说,您可以使用像 https://www.npmjs.com/package/@peculiar/webcrypto 这样的 polyfill,它是 Nodejs 版本高于 Node10 的 webcrypto 实现
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。