Node.js中的AES-256-GCM解密 [英] AES-256-GCM decryption in nodejs

查看:441
本文介绍了Node.js中的AES-256-GCM解密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图先将数据库中存储的数据解密,然后再将其发送到客户端.

i am trying to decrypt the data stored in my database before sending it to the client side.

我正在使用具有AES-256-GCM加密功能的内置加密模块.

I am using the builtin crypto module with AES-256-GCM encryption.

我已经成功实现了加密,并且工作正常,我的问题是我试图解密另一个文件中的数据,但是我一直遇到错误.

I have successfully implemented the encryption and it is working properly my problem is i am trying to decrypt the data in a different file but i keep getting an error.

这是错误:

(节点:35798)UnhandledPromiseRejectionWarning:TypeError [ERR_INVALID_ARG_TYPE]:"iv"消息参数必须是字符串类型,或者是Buffer,TypedArray或DataView的实例.收到未定义的

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))

                          })

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)

这是存储在我的数据库中的数据的一个示例

here is an example of the data stored in my database

手机号码:'Sm4xQjA2bmUwUUdEdW4zQkZ3PT3QEq5fBbTJ9ht4TgpQXTLmPYBSoQA836977j0rr3GYwg ==',

推荐答案

这是您在加密期间执行的操作:

This is what you do during encryption:

Buffer.concat([Buffer.from(enc), iv, cipher.getAuthTag()]).toString("base64");

现在,您需要在解密过程中将其反转:

Now, you need to reverse this during decryption:

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);

第二个问题是,用于GCM模式的nonce/iv应为12个字节长.我已经进行了更改,因此上一期的某些索引也应该更改.

The second issue is that a nonce/iv for GCM mode should be 12 bytes long. I've changed that and so some of the indices from the previous issue should change too.

第三个问题是您无法连接加密和Base64编码的块.您必须在Base64编码之前将它们连接起来,以便在字符串中间没有Base64填充.对于GCM来说,这不是什么大问题,因为对 cipher.final('base64'); 的调用应返回一个空字符串.

The third issue is that you cannot concatenate encrypted and Base64-encoded chunks. You have to concatenate them before Base64 encoding so that there is no Base64 padding in the middle of the string. This shouldn't be much of an issue for GCM because the call to cipher.final('base64'); should return an empty string.

第四个明显的问题是,加密期间您要编码两次,但是只需要编码一次.

The fourth and clear issue is that during encryption you're encoding twice, but you only need to encode once.

这看起来像这样:

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);

这篇关于Node.js中的AES-256-GCM解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆