用于MD5哈希的密码盐字符串的格式是什么?

时间:2019-02-16 16:21:23

标签: c++ cryptography md5 salt crypto++

我正在使用C ++创建一个简单的数据库访问应用程序,并且添加了包含以下内容的用户表: ID USER PASSWORD 和< strong> SALT ,我正在使用 Crypto ++ 作为加密后端。所以我创建了这个函数:

#include "crypto.h"

#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
#include <md5.h>
#include <hex.h>
#include <osrng.h>

using namespace std;
using namespace CryptoPP;

string MyCrypto::MD5(const string strMessage)
{
    byte arrbyDigest[Weak::MD5::DIGESTSIZE];
    Weak::MD5 hash;
    hash.CalculateDigest(arrbyDigest, /*(const byte*)*/strMessage.c_str(), strMessage.length());

    HexEncoder encoder;
    string strOutput;

    encoder.Attach(new StringSink(strOutput));
    encoder.Put(arrbyDigest, sizeof(arrbyDigest));
    encoder.MessageEnd();

    return strOutput;
}

string MyCrypto::GenerateSalt(const size_t length /*= 16*/)
{
    SecByteBlock arrbySalt(length);
    AutoSeededRandomPool asrp;
    asrp.GenerateBlock(arrbySalt, length);

    string strSalt(arrbySalt);
    strSalt.ToAscii();

    return strSalt;
}

到目前为止,一切正常,直到我意识到生成的盐串可以包含不可打印的字符,甚至空终止符

所以我的问题是:

我做对了吗?

像我实际操作的那样,盐的长度是 16 吗?

在与普通密码字符串连接之前,应该在 Base 64 HEX 中对盐字符串进行加密还是将其保留为纯文本 MD5哈希?

在将盐字符串保存到数据库时,应该在 Base 64 HEX 中将其加密还是保留为纯文本? >

您有什么建议?

1 个答案:

答案 0 :(得分:2)

不,您的做法不正确。 MD5是-或更确切地说是-是加密安全的哈希。它不适用于哈希密码。要对密码进行哈希处理,您需要一个密码哈希,其中包含随机的盐和工作因数(成本或迭代次数,取决于所使用的密码哈希)。这些示例包括bcrypt,PBKDF2和较新的Argon2。 Here是一篇随机文章,讨论了密码散列的使用。

对于编码,我将始终尝试遵守现有标准(存在标准)。对于密码哈希,适用的标准是Modular Crypt Format。如果要设计对互操作性要求不高的新方案,则也可以使用Password Hashing Format

都使用 base 类型的编码作为盐和密码的输出格式。一个示例是bcrypt输出$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy,其中2a表示bcrypt和格式,10是成本(工作因子),N9qo8uLOickgx2ZMRZoMye是盐的基数64编码;其余的是密码哈希。请注意,盐和密码之间没有美元符号分隔符。

我从bcrypt Wikipedia page中获取了上面的示例,这是获取更多信息的有趣起点,其中可能包括crypt的MD5哈希输出(如所示,您不应使用)。

几乎忘记了,是的,大量是16个随机字节/ 128位盐。如果您使用8个字节,没有人会眨眼,但超过32个字节的字节数就超过了。