4

我使用 NHibernate 并有一个自定义类型来加密数据库中的密码,这样我就可以使用字符串属性来表示密码,但是 NHibernate 在存储到数据库之前会转换/加密值。目前,我在配置文件中存储了一个盐值和一个加密密钥,但我真的更愿意使用密码哈希。但是,自定义 NHibernate 类型除了被告知要处理的属性值之外,对存储的对象一无所知,因此我无法生成一些随机盐并将其与对象一起存储在此自定义类型中的另一个属性中.

由于我不能单独存储盐,我想知道是否可以从密码本身导出盐,然后对两者的组合进行哈希处理。例如,我可能会取密码,MD5 散列它,然后使用 MD5 散列作为盐。这样可以吗?这将允许我以确定的方式保存密码,同时为每个密码使用唯一(但派生的)盐值,但是这样做时是否有任何安全考虑?

编辑:

因为到目前为止我收到的所有答案都未能说明问题的上下文,所以让我介绍 NHibernate 术语中定义的方法的签名。

public override void Set(IDbCommand cmd, object value, int index)
{
    var param = (IDataParameter)cmd.Parameters[index];

    if (value == null)
    {
        param.Value = null;
    }
    else
    {
        var temp = value.ToString();
        var encrypted = encryptor.Encrypt(temp);
        param.Value = encrypted;
    }
}

这就是 NHibernate 给我的全部。我收到 IDbCommand 对象、一个值和一个参数索引。我对参数本身或被持久化的对象类型一无所知。我只有一个值。我无法生成随机盐并将其存储在单独的属性中,因为我不知道要持久化的对象上存在哪些属性,也不知道它们在参数集合中存储的顺序。我的目标是在此方法调用的上下文中以最安全的方式对密码进行哈希处理。如果您要反对我的建议,那么在这种情况下接受一个替代想法会很有帮助。

4

4 回答 4

5

不!如果您从密码中派生盐,则所有相同的密码都具有相同的哈希值,并且盐变得无用。

尝试

var temp = value.ToString();
var salt = generateRandonSalt();
var encrypted = encryptor.Encrypt(temp + salt);
param.Value = salt + encrypted;

“+”是指连接操作数或与您的值兼容的东西。当然,您需要始终知道盐的长度,以便下次检查密码。

于 2012-04-07T04:24:27.243 回答
4

散列函数的目的是从密码中派生一些东西。如果您从密码中派生盐,那么该派生实际上是您的散列函数的一部分。您刚刚更改/增强了散列函数,实际上并没有盐。

盐必须是随机的。

他们的工作是让暴力破解密码变得更加困难。如果一个盐有 65536 个不同的值(例如),那么这意味着相同的密码可以散列 65536 种不同的方式。如果有人想建立一个字典,将哈希值反转回密码,他的字典将需要 65536 个条目来输入一个密码。

要使这个想法起作用,盐必须与密码无关。

于 2012-04-07T04:30:39.313 回答
1

您的示例的问题在于,如果某些攻击者想要找到匹配项,他们可以创建一个彩虹表,其中所有密码都由他们的 md5 计算机部分加盐。

每个条目的盐应该是唯一的,这样黑客就必须拥有一个逆向工程表,其中包含 md5 与每种可能的盐的每种可能组合。

于 2012-04-07T04:30:27.800 回答
0

如果您的类盐方案的目的是使用预先确定的散列使密码抵抗字典攻击,那么您的方法可能比未加盐的散列更安全,但不如使用有效的盐安全。

有效盐的一个重要安全优势是相同密码的两个实例将产生两个不同的哈希值。在您的方案下,知道一个用户的密码和哈希将允许攻击者推断出具有相同哈希的另一个用户的相同密码。

于 2012-04-07T04:54:35.623 回答