javascript - 无法在 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 生成的密钥不能在浏览器中展开。
我假设一些默认值是错误的还是什么?
解决方案
NodeJSwebcrypto
在包中有一个叫做 Class的东西crypto
,它有微妙的加密实现。
文档中的示例:
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,它是高于 Node10 的 Nodejs 版本的 webcrypto 实现
推荐阅读
- ios - 字符串数组除外时使用 LazyMapSequence
- java - 如何同时修改多个 EditText 的输入,因为我只修改一个?
- javascript - Azure 网站加载 JSON 文件失败
- scala - 为什么需要 scala 猫中的 Functor
- flutter - 使用 mapbox 插件添加自定义标记以在颤振中映射
- c# - 我想使用@Html.ActionLink Delete 删除数据库中的一行,但它不起作用。我究竟做错了什么?
- css - react-bootstrap 表单边距导致溢出
- android - 主机名不能为空并出现错误:任务“:app:uploadCrashlyticsMappingFileRelease”执行失败
- sql - 查询中的多值选择 PrestoDB
- sql - 如何在没有任何数据集的情况下在 2 个日期(例如分钟)之间进行 SELECT