在 Node.js 加密中使用字符串和缓冲区有什么区别
What is the difference between using string and buffer in Node.js encryption
我在某些网站上看到了以下两个代码。一个使用 Buffer
包装 crypto.randomBytes()
对象作为密码密钥并使用它连接加密的最终结果,另一个使用普通 crypto.randomBytes()
对象作为密码密钥并简单地连接最终结果使用'plus equal' 运算符。
const cipher = crypto.createCipheriv(
"aes-256-gcm",
Buffer.from(crypto.randomBytes(32)),
crypto.randomBytes(16)
);
let encrypted = cipher.update("this is data");
encrypted = Buffer.concat([encrypted, cipher.final()]);
// edited: I forgot below line
encrypted = encrypted.toString("hex");
和...
const cipher = crypto.createCipheriv(
"aes-256-gcm",
crypto.randomBytes(32),
crypto.randomBytes(16)
);
let encrypted = cipher.update("this is data");
encrypted += cipher.final();
两种实现都有效。但是我找不到任何关于他们为什么使用 Buffer
的解释,也不知道这两个示例之间的区别是什么。
更新
我尝试对两种实现使用相同的 key
和 iv
(如 Maarten Bodewes ,它们产生相同的结果:
const crypto = require('crypto');
const data = 'hello world'
const algorithm = 'aes-256-gcm'
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
function encrypt1(data) {
const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(data, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
function encrypt2(data) {
const cipher = crypto.createCipheriv(algorithm, Buffer.from(key), iv);
let encrypted = cipher.update(data);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return encrypted.toString('hex');
}
const result1 = encrypt1(data);
const result2 = encrypt2(data);
console.log('result1: ', result1); // -> result1: 501db5c82e79e3185c1601
console.log('result2: ', result2); // -> result2: 501db5c82e79e3185c1601
那么,为什么要使用看起来更复杂的 Buffer 来产生相同的结果呢?
Buffer
只是使用的内部结构。
以下是一些可能的优势:
- 缓冲区可以将字节存储在机器字(32位或64位)中,以提高后续操作的效率;
- 无需在缓冲区和其他表示之间来回转换;
- 它也可能比在字符串中存储字符更有效——可能不清楚存储这些字符的确切方式是什么,即使它们只是表示字节(它们可以使用 16 位或 32 位字,例如,将所需的大小增加一倍或四倍);
- 如果存在转换错误,也可以在显式转换函数中检测到,而不是在加密方法中检测到,这样可以更容易调试;
- 将代码更改为例如使用不同编码的密钥,例如十六进制。
最后,Buffer
更接近于键实际上应该是 八位字节字符串 或 字节数组 ,不是 文本字符串。
然而,综上所述,对于简单的加密操作,在预期输出方面没有差异。所以从这个意义上说,这两种方法都是有效的。
我在某些网站上看到了以下两个代码。一个使用 Buffer
包装 crypto.randomBytes()
对象作为密码密钥并使用它连接加密的最终结果,另一个使用普通 crypto.randomBytes()
对象作为密码密钥并简单地连接最终结果使用'plus equal' 运算符。
const cipher = crypto.createCipheriv(
"aes-256-gcm",
Buffer.from(crypto.randomBytes(32)),
crypto.randomBytes(16)
);
let encrypted = cipher.update("this is data");
encrypted = Buffer.concat([encrypted, cipher.final()]);
// edited: I forgot below line
encrypted = encrypted.toString("hex");
和...
const cipher = crypto.createCipheriv(
"aes-256-gcm",
crypto.randomBytes(32),
crypto.randomBytes(16)
);
let encrypted = cipher.update("this is data");
encrypted += cipher.final();
两种实现都有效。但是我找不到任何关于他们为什么使用 Buffer
的解释,也不知道这两个示例之间的区别是什么。
更新
我尝试对两种实现使用相同的 key
和 iv
(如 Maarten Bodewes
const crypto = require('crypto');
const data = 'hello world'
const algorithm = 'aes-256-gcm'
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
function encrypt1(data) {
const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(data, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
function encrypt2(data) {
const cipher = crypto.createCipheriv(algorithm, Buffer.from(key), iv);
let encrypted = cipher.update(data);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return encrypted.toString('hex');
}
const result1 = encrypt1(data);
const result2 = encrypt2(data);
console.log('result1: ', result1); // -> result1: 501db5c82e79e3185c1601
console.log('result2: ', result2); // -> result2: 501db5c82e79e3185c1601
那么,为什么要使用看起来更复杂的 Buffer 来产生相同的结果呢?
Buffer
只是使用的内部结构。
以下是一些可能的优势:
- 缓冲区可以将字节存储在机器字(32位或64位)中,以提高后续操作的效率;
- 无需在缓冲区和其他表示之间来回转换;
- 它也可能比在字符串中存储字符更有效——可能不清楚存储这些字符的确切方式是什么,即使它们只是表示字节(它们可以使用 16 位或 32 位字,例如,将所需的大小增加一倍或四倍);
- 如果存在转换错误,也可以在显式转换函数中检测到,而不是在加密方法中检测到,这样可以更容易调试;
- 将代码更改为例如使用不同编码的密钥,例如十六进制。
最后,Buffer
更接近于键实际上应该是 八位字节字符串 或 字节数组 ,不是 文本字符串。
然而,综上所述,对于简单的加密操作,在预期输出方面没有差异。所以从这个意义上说,这两种方法都是有效的。