kd1*_*345 2 encryption node.js
我正在尝试解密存储在数据库中的数据,然后再将其发送到客户端。
我正在使用带有 AES-256-GCM 加密的内置加密模块。
我已成功实现加密并且工作正常,我的问题是我正在尝试解密不同文件中的数据,但我不断收到错误。
这是错误:
(node:35798) UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]: The "iv" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined
1.js
router.post(
"/",
async(req, res) => {
function getFullAddress({housenumber, address1, address2, city, postcode, country}) {
return [housenumber, address1, ...(address2 ? [address2]: []), city, postcode, country].join(", ");
}
const aes256gcm = (key) => {
const encrypt = (str) => {
const iv = new crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
let enc = cipher.update(str, 'utf8', 'base64');
enc += cipher.final('base64');
return Buffer.concat([Buffer.from(enc), iv, cipher.getAuthTag()]).toString("base64");
};
return {
encrypt,
};
};
const aesCipher = aes256gcm(key);
const hashedPasscode = await bcrypt.hash(req.body.passcode, 12);
await User.create({
email: req.body.email,
mobilenumber: aesCipher.encrypt(req.body.mobilenumber),
passcode: hashedPasscode,
address: aesCipher.encrypt(getFullAddress(req.body))
})
Run Code Online (Sandbox Code Playgroud)
2.js
router.get(
"/",
async(req, res) => {
const aes256gcm = (key) => {
const decrypt = (enc, iv, authTag) => {
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(authTag);
let str = decipher.update(enc, 'base64', 'utf8');
str += decipher.final('utf8');
return str;
};
return {
decrypt,
};
};
const aesCipher = aes256gcm(key);
const decrypted_MobileNumber = aesCipher.decrypt(user.mobilenumber);
const decrypted_address = aesCipher.decrypt(user.address);
console.log('decrypted_MobileNumber',decrypted_MobileNumber)
console.log('decrypted_address',decrypted_address)
Run Code Online (Sandbox Code Playgroud)
这是我的数据库中存储的数据的示例
mobilenumber: 'Sm4xQjA2bmUwUUdEdW4zQkZ3PT3QEq5fBbTJ9ht4TgpQXTLmPYBSoQA836977j0rr3GYwg==',
这是您在加密期间所做的事情:
Buffer.concat([Buffer.from(enc), iv, cipher.getAuthTag()]).toString("base64");
Run Code Online (Sandbox Code Playgroud)
现在,您需要在解密过程中反转:
enc = Buffer.from(enc, "base64");
const iv = enc.slice(enc.length-32, enc.length-16);
const tag = enc.slice(enc.length-16);
enc = enc.slice(0, enc.length-32);
Run Code Online (Sandbox Code Playgroud)
第二个问题是 GCM 模式的 nonce/iv 应该是 12 字节长。我已经改变了这一点,因此上一期的一些索引也应该改变。
第三个问题是您无法连接加密和 Base64 编码的块。您必须在 Base64 编码之前将它们连接起来,以便字符串中间没有 Base64 填充。对于 GCM 来说这不应该是一个大问题,因为调用cipher.final('base64');应该返回一个空字符串。
第四个也是明显的问题是,在加密过程中,您编码了两次,但您只需要编码一次。
一起看起来像这样:
const crypto = require('crypto');
const aes256gcm = (key) => {
const encrypt = (str) => {
const iv = new crypto.randomBytes(12);
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
let enc1 = cipher.update(str, 'utf8');
let enc2 = cipher.final();
return Buffer.concat([enc1, enc2, iv, cipher.getAuthTag()]).toString("base64");
};
const decrypt = (enc) => {
enc = Buffer.from(enc, "base64");
const iv = enc.slice(enc.length - 28, enc.length - 16);
const tag = enc.slice(enc.length - 16);
enc = enc.slice(0, enc.length - 28);
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(tag);
let str = decipher.update(enc, null, 'utf8');
str += decipher.final('utf8');
return str;
};
return {
encrypt,
decrypt,
};
};
const cipher = aes256gcm(Buffer.alloc(32)); // just a test key
const ct = cipher.encrypt('test');
const pt = cipher.decrypt(ct);
console.log(pt);
Run Code Online (Sandbox Code Playgroud)