Node.js 节点crypto.createCipheriv(';aes-256-gcm';,…).getAuthKey()中的值是否可以是公共的?

Node.js 节点crypto.createCipheriv(';aes-256-gcm';,…).getAuthKey()中的值是否可以是公共的?,node.js,encryption,cryptography,aes-gcm,message-authentication-code,Node.js,Encryption,Cryptography,Aes Gcm,Message Authentication Code,我找不到一些信息。有人知道从(->返回MAC)返回的值是否可以公开显示吗 TL;博士 消息身份验证码是否可以公开显示,或者是否需要像密码一样保密? 一些背景,我正在尝试加密一个文件。我发现这个问题和答案帮助我开始 在对nodejs文档进行了一些研究之后,我发现答案使用了一个不推荐使用的函数。要使用的新函数应为 因此,为了使用新的createCipheriv,我使用文档编写了一个新的加密和解密函数,类似于文章中使用新的createCipheriv函数的函数。在编写解密函数之后,我得到了一个错误 错

我找不到一些信息。有人知道从(->返回MAC)返回的值是否可以公开显示吗

TL;博士

消息身份验证码是否可以公开显示,或者是否需要像密码一样保密?

一些背景,我正在尝试加密一个文件。我发现这个问题和答案帮助我开始

在对nodejs文档进行了一些研究之后,我发现答案使用了一个不推荐使用的函数。要使用的新函数应为

因此,为了使用新的createCipheriv,我使用文档编写了一个新的加密和解密函数,类似于文章中使用新的createCipheriv函数的函数。在编写解密函数之后,我得到了一个错误

错误:状态不受支持或无法验证数据

在谷歌搜索了这个问题后,我来到了这里。简而言之,它说解密文件需要使用密码生成的authTag

我不知道这个authTag是什么,我认识的人也不知道。所以我开始在谷歌上搜索,它让我找到了这个。它说

authTag是加密过程中计算的消息身份验证码(MAC)

下面是一个关于什么是消息认证码的例子

是这样。这是我的问题。消息身份验证码是否可以公开显示,或者是否需要像密码一样保密?


我的代码没有那么重要,但可能会帮助某人使用createCipheriv和createDecipheriv创建加密和解密

加密

const crypto = require('crypto');
const fs = require('fs');

// const iv = crypto.randomBytes(32).toString('hex');
// EDIT - based on @President James K. Polk. The initialization vector should be 12 bytes long
// const iv = crypto.randomBytes(6).toString('hex');
// EDIT - based on @dsprenkels. I misunderstood @President James K. Polk
const iv = crypto.randomBytes(12).toString('hex');
const privateKey = 'private key that is 32 byte long';
const cipher = crypto.createCipheriv('aes-256-gcm', privateKey, iv);

const filename = 'somefile.txt';
const encFilename = 'somefile.txt.enc';
const unencryptedInput = fs.createReadStream(filename);
const encryptedOutput = fs.createWriteStream(encFilename);
unencryptedInput.pipe(cipher).pipe(encryptedOutput);

encryptedOutput.on('finish', () => {
    const authTagAsHex = cipher.getAuthTag().toString('hex'); // <-- can this be public
    console.log(authTagAsHex);
});
const crypto = require('crypto');
const fs = require('fs');

// const publicIV = 'same iv generated during encryption crypto.randomBytes(32).toString("hex")';
// EDIT - based on @President James K. Polk. The initialization vector should be 12 bytes long
// const publicIV = 'same iv generated during encryption crypto.randomBytes(6).toString("hex")';
// EDIT - based on @dsprenkels. I misunderstood @President James K. Polk
const publicIV = 'same iv generated during encryption crypto.randomBytes(12).toString("hex")';
const authTag = 'same authKey generated from cipher.getAuthTag().toString("hex")';
const privateKey = 'private key that is 32 byte long';
const decipher = crypto.createDecipheriv('aes-256-gcm', privateKey, publicIV);
decipher.setAuthTag(Buffer.from(authTag, 'hex'));

const filename = 'somefile.txt';
const encFilename = 'somefile.txt.enc';
const readStream = fs.createReadStream(encFilename);
const writeStream = fs.createWriteStream(filename);
readStream.pipe(decipher).pipe(writeStream);

是。MAC被认为是公共的

一般来说,消息身份验证码被认为是公共的。消息身份验证代码根据您提供的密钥对(加密)消息进行身份验证。换句话说,它被接收者用来检查密文在传输过程中是否没有改变。在您的情况下,只要密钥保持机密,攻击者就不会使用MAC

存储密文时,MAC通常放在密文旁边(就像IV一样)


顺便说一句,在您的情况下,您是随机生成IV。这很好,但请注意,在同一密钥下可以安全加密的消息数量相当大。如果IV用于多条消息(甚至一次!),则此方案的完全安全性将崩溃。真的,你可能想要这个:

const iv = crypto.randomBytes(12);

身份验证标签不是秘密,通常放在加密消息的某处,通常放在末尾。IV(在GCM模式中通常称为“nonce”)应该是12字节,并且也不是秘密,并且通常与加密消息放在同一个流中,通常放在开头。太棒了,您的回答非常有用,非常感谢!我更新了我的代码,只使用了12字节的初始化向量。太棒了!谢谢你接电话。我更新了上面的代码以反映这一变化。谢谢你的帮助!