encryption - 我应该使用Base64还是Unicode来存储哈希和盐?

标签 encryption unicode

由于我刚大学毕业,我从未在Web应用程序的安全性方面工作过。现在,我正在寻找工作,并在侧面的一些网站上工作,以保持我的技能敏锐并获得新的技能。我正在处理的一个站点几乎是从original MEAN stack的创建者那里复制而来的,但是试图理解它,并尽我所能做得更好。

为了计算哈希值和盐值,创建者使用了PBKDF2。我对听到有关支持或反对PBKDF2的论点不感兴趣,因为这不是这个问题的意思。他们似乎在这里为所有内容使用了缓冲区,据我了解,这是node中的一种常见做法。我感兴趣的是他们使用base64进行缓冲区编码的原因,而不是简单地使用UTF-8(这是缓冲区对象的一个​​选项)的原因。如今,大多数计算机可以处理Unicode中的许多字符,即使不是全部也可以,但是创建者可以选择将密码编码为Unicode子集,而不必将自己限制为base64的65个字符。

通过“在编码为UTF-8base64之间进行选择”,我的意思是将根据密码计算出的哈希值二进制转换为给定的编码。 node.js指定了几种将二进制数据编码为Buffer对象的方法。在Buffer类的文档页面中:

Pure JavaScript is Unicode friendly but not nice to binary data. When dealing with TCP
streams or the file system, it's necessary to handle octet streams. Node has several
strategies for manipulating, creating, and consuming octet streams.

Raw data is stored in instances of the Buffer class. A Buffer is similar to an array
of integers but corresponds to a raw memory allocation outside the V8 heap. A Buffer
cannot be resized.


据我了解,Buffer类的作用是获取一些二进制数据并计算每8个(通常)位的值。然后,它将每组位转换为与您指定的编码中的值相对应的字符。例如,如果二进制数据是00101100(8位),并且您指定UTF-8作为编码,则输出将是,(逗号)。这是任何人在使用诸如vim之类的文本编辑器查看缓冲区输出时所看到的内容,以及计算机在“读取”它们时所看到的内容。 Buffer类具有几种可用的编码,例如UTF-8base64binary

我认为他们认为,尽管可以在哈希中存储任何可以想象到的UTF-8字符,但它们不会对大多数现代计算机(包括其GB的RAM和TB的空间)进行阶段化,因为它们实际上显示了所有这些字符。可能想要在日志等中执行操作,可能会吓坏用户,他们不得不查看奇怪的中文,希腊语,保加利亚语等字符以及控制字符,例如Ctrl按钮或Backspace按钮甚至发出哔声除非他们是经验丰富的用户测试PBKDF2本身,否则他们根本不需要真正理解它们,但是程序员的首要职责是不给任何用户心脏病发作。使用base64会使开销增加大约三分之一,这在当今已经很难引起注意了,并且减少了字符集,这并没有降低安全性。毕竟,计算机是完全用二进制编写的。正如我之前所说,他们可以选择Unicode的其他子集,但是base64已经是标准的,这使它更容易并减少了程序员的工作。

我对这个存储库的创建者选择使用base64而不是全部Unicode编码密码的原因是否正确?坚持他们的示例会更好,还是我应该使用Unicode或其更大的子集?

最佳答案

有一个与安全性相关的根本原因要存储为Base64而不是Unicode:散列可能包含字节值“ 0”,许多编程语言都将其用作字符串结尾标记。

如果将哈希存储为Unicode,则您,其他程序员或所使用的某些库代码可能会将其视为字符串而不是字节集合,并使用strcmp()或类似的字符串比较函数进行比较。如果您的哈希值包含字节值“ 0”,则表示您已经有效地将哈希值截断为“ 0”之前的部分,从而使攻击变得更加容易。

Base64编码避免了此问题:字节值“ 0”不能以哈希的编码形式出现,因此使用memcmp()(正确的方式)或strcmp()(错误的方式)比较编码的哈希值都没关系)。

这也不只是理论上的问题:使用strcmp()检查数字签名的代码有多种情况,大大削弱了安全性。

关于encryption - 我应该使用Base64还是Unicode来存储哈希和盐?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27014578/

相关文章:

java - 如何实现java字节码加密(防逆向工程)

c - 不兼容的 AES 实现?

c++ - 如何加密文本

javascript - 设置 Javascript 中用于排序的 unicode 字符的值

android - FBEncrypter 库与 Android 的兼容性

MYSQL:使用较低的des解密函数

qt - 将UTF-16 QByteArray转换为QString

python - 在 Python 中使用带有 LOCALE 和 UNICODE 标志的 Regex 测试空格

c# - 如何转换文件名中的符号?

Python TypeError : expected a character buffer object, 个人理解错误