WebCrypto API: DOMException: 提供的数据太小
WebCrypto API: DOMException: The provided data is too small
我想在客户端(react.js
)使用在后端(node.js
)加密的Web Crypto API
解密消息,但是我运行 遇到了一个奇怪的问题,不知道出了什么问题(我也检查了 )
node.js
function encrypt(message){
const KEY = crypto.randomBytes(32)
const IV = crypto.randomBytes(16)
const ALGORITHM = 'aes-256-gcm';
const cipher = crypto.createCipheriv(ALGORITHM, KEY, IV);
let encrypted = cipher.update(message, 'utf8', 'hex');
encrypted += cipher.final('hex');
const tag = cipher.getAuthTag()
let output = {
encrypted,
KEY: KEY.toString('hex'),
IV: KEY.toString('hex'),
TAG: tag.toString('hex'),
}
return output;
}
react.js
function decrypt() {
let KEY = hexStringToArrayBuffer(data.KEY);
let IV = hexStringToArrayBuffer(data.IV);
let encrypted = hexStringToArrayBuffer(data.encrypted);
let TAG = hexStringToArrayBuffer(data.TAG);
window.crypto.subtle.importKey('raw', KEY, 'AES-GCM', true, ['decrypt']).then((importedKey)=>{
window.crypto.subtle.decrypt(
{
name: "AES-GCM",
iv: IV,
},
importedKey,
encrypted
).then((plaintext)=>{
console.log('plainText: ', plaintext);
})
})
function hexStringToArrayBuffer(hexString) {
hexString = hexString.replace(/^0x/, '');
if (hexString.length % 2 != 0) {
console.log('WARNING: expecting an even number of characters in the hexString');
}
var bad = hexString.match(/[G-Z\s]/i);
if (bad) {
console.log('WARNING: found non-hex characters', bad);
}
var pairs = hexString.match(/[\dA-F]{2}/gi);
var integers = pairs.map(function(s) {
return parseInt(s, 16);
});
var array = new Uint8Array(integers);
return array.buffer;
}
后端加密没有任何错误,但是当想要在客户端解密消息时,浏览器(chrome)给出了这个错误:DOMException: The provided data is too small
,当我在 firefox 浏览器上 运行 程序时,它给我这个错误:DOMException: The operation failed for an operation-specific reason
。太不明白了!!
请问AES-GCM
中的athentication tag
有什么用,需要客户端解密吗?
GCM是鉴权加密。解密需要身份验证标签。用于验证密文的真实性,只有在确认后才进行解密。
由于标记未应用于您的 WebCrypto 代码,因此身份验证和解密失败。
WebCrypto 期望将标签附加到密文:密文 |标签.
下面代码中的数据是使用您的 NodeJS 代码创建的(请注意 NodeJS 代码中存在一个错误:密钥存储在 output
中而不是 IV):
decrypt();
function decrypt() {
let KEY = hexStringToArrayBuffer('684aa9b1bb4630f802c5c0dd1428403a2224c98126c1892bec0de00b65cc42ba');
let IV = hexStringToArrayBuffer('775a446e052b185c05716dd1955343bb');
let encryptedHex = 'a196a7426a9b1ee64c2258c1575702cf66999a9c42290a77ab2ff30037e5901243170fd19c0092eed4f1f8';
let TAGHex = '14c03526e18502e4c963f6055ec1e9c0';
let encrypted = hexStringToArrayBuffer(encryptedHex + TAGHex)
window.crypto.subtle.importKey(
'raw',
KEY,
'AES-GCM',
true,
['decrypt']
).then((importedKey)=> {
window.crypto.subtle.decrypt(
{
name: "AES-GCM",
iv: IV,
},
importedKey,
encrypted
).then((plaintext)=>{
console.log('plainText: ', ab2str(plaintext));
});
});
}
function hexStringToArrayBuffer(hexString) {
hexString = hexString.replace(/^0x/, '');
if (hexString.length % 2 != 0) {
console.log('WARNING: expecting an even number of characters in the hexString');
}
var bad = hexString.match(/[G-Z\s]/i);
if (bad) {
console.log('WARNING: found non-hex characters', bad);
}
var pairs = hexString.match(/[\dA-F]{2}/gi);
var integers = pairs.map(function(s) {
return parseInt(s, 16);
});
var array = new Uint8Array(integers);
return array.buffer;
}
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint8Array(buf));
}
我想在客户端(react.js
)使用在后端(node.js
)加密的Web Crypto API
解密消息,但是我运行 遇到了一个奇怪的问题,不知道出了什么问题(我也检查了
node.js
function encrypt(message){
const KEY = crypto.randomBytes(32)
const IV = crypto.randomBytes(16)
const ALGORITHM = 'aes-256-gcm';
const cipher = crypto.createCipheriv(ALGORITHM, KEY, IV);
let encrypted = cipher.update(message, 'utf8', 'hex');
encrypted += cipher.final('hex');
const tag = cipher.getAuthTag()
let output = {
encrypted,
KEY: KEY.toString('hex'),
IV: KEY.toString('hex'),
TAG: tag.toString('hex'),
}
return output;
}
react.js
function decrypt() {
let KEY = hexStringToArrayBuffer(data.KEY);
let IV = hexStringToArrayBuffer(data.IV);
let encrypted = hexStringToArrayBuffer(data.encrypted);
let TAG = hexStringToArrayBuffer(data.TAG);
window.crypto.subtle.importKey('raw', KEY, 'AES-GCM', true, ['decrypt']).then((importedKey)=>{
window.crypto.subtle.decrypt(
{
name: "AES-GCM",
iv: IV,
},
importedKey,
encrypted
).then((plaintext)=>{
console.log('plainText: ', plaintext);
})
})
function hexStringToArrayBuffer(hexString) {
hexString = hexString.replace(/^0x/, '');
if (hexString.length % 2 != 0) {
console.log('WARNING: expecting an even number of characters in the hexString');
}
var bad = hexString.match(/[G-Z\s]/i);
if (bad) {
console.log('WARNING: found non-hex characters', bad);
}
var pairs = hexString.match(/[\dA-F]{2}/gi);
var integers = pairs.map(function(s) {
return parseInt(s, 16);
});
var array = new Uint8Array(integers);
return array.buffer;
}
后端加密没有任何错误,但是当想要在客户端解密消息时,浏览器(chrome)给出了这个错误:DOMException: The provided data is too small
,当我在 firefox 浏览器上 运行 程序时,它给我这个错误:DOMException: The operation failed for an operation-specific reason
。太不明白了!!
请问AES-GCM
中的athentication tag
有什么用,需要客户端解密吗?
GCM是鉴权加密。解密需要身份验证标签。用于验证密文的真实性,只有在确认后才进行解密。
由于标记未应用于您的 WebCrypto 代码,因此身份验证和解密失败。
WebCrypto 期望将标签附加到密文:密文 |标签.
下面代码中的数据是使用您的 NodeJS 代码创建的(请注意 NodeJS 代码中存在一个错误:密钥存储在 output
中而不是 IV):
decrypt();
function decrypt() {
let KEY = hexStringToArrayBuffer('684aa9b1bb4630f802c5c0dd1428403a2224c98126c1892bec0de00b65cc42ba');
let IV = hexStringToArrayBuffer('775a446e052b185c05716dd1955343bb');
let encryptedHex = 'a196a7426a9b1ee64c2258c1575702cf66999a9c42290a77ab2ff30037e5901243170fd19c0092eed4f1f8';
let TAGHex = '14c03526e18502e4c963f6055ec1e9c0';
let encrypted = hexStringToArrayBuffer(encryptedHex + TAGHex)
window.crypto.subtle.importKey(
'raw',
KEY,
'AES-GCM',
true,
['decrypt']
).then((importedKey)=> {
window.crypto.subtle.decrypt(
{
name: "AES-GCM",
iv: IV,
},
importedKey,
encrypted
).then((plaintext)=>{
console.log('plainText: ', ab2str(plaintext));
});
});
}
function hexStringToArrayBuffer(hexString) {
hexString = hexString.replace(/^0x/, '');
if (hexString.length % 2 != 0) {
console.log('WARNING: expecting an even number of characters in the hexString');
}
var bad = hexString.match(/[G-Z\s]/i);
if (bad) {
console.log('WARNING: found non-hex characters', bad);
}
var pairs = hexString.match(/[\dA-F]{2}/gi);
var integers = pairs.map(function(s) {
return parseInt(s, 16);
});
var array = new Uint8Array(integers);
return array.buffer;
}
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint8Array(buf));
}