我使用NHibernate并且有一个自定义类型来加密数据库中的密码,这样我就可以使用字符串属性来表示密码,但NHibernate在存储到db之前转换/加密该值。目前,我在配置文件中存储了salt值和加密密钥,但我真的更愿意转移到密码哈希。但是,自定义NHibernate类型对被存储的对象一无所知,除了它被告知要处理的属性的值,因此我无法生成一些随机盐并将其与该对象一起存储在此自定义类型中的另一个属性中。
由于我无法单独存储盐,我想知道从密码本身导出salt是否可行,然后散列两者的组合。例如,我可能会使用密码,MD5哈希,然后使用MD5哈希作为salt。这样可以吗?这将允许我以确定的方式持久保存密码,同时使用每个密码的唯一(但派生)盐值,但是这样做时是否有任何安全考虑?
修改
因为到目前为止我收到的所有答案都未能解释问题的上下文,所以让我提出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对象,值和参数索引。我对参数本身或持久化对象的类型一无所知。我只有一个价值。我无法生成随机盐并将其存储在单独的属性中,因为我不知道要保留的对象上存在哪些属性,也不知道它们存储在参数集合中的顺序。我的目标是在此方法调用的上下文中以最安全的方式散列密码 。如果你打算反对我的建议,那么在这种背景下获得另一个想法会很有帮助。
答案 0 :(得分:5)
没有!如果从密码中导出salt,则所有相同的密码都具有相同的散列,并且盐变得无用。
尝试
var temp = value.ToString();
var salt = generateRandonSalt();
var encrypted = encryptor.Encrypt(temp + salt);
param.Value = salt + encrypted;
使用“+”我的意思是连接操作数或与您的值兼容的东西。当然,您需要始终知道盐的长度,以便下次检查密码。
答案 1 :(得分:4)
散列函数的目的是从密码中导出一些东西。如果从密码派生salt,则该派生实际上是散列函数的一部分。你刚刚修改/扩充了散列函数,实际上没有盐。
盐必须是随机的。
他们的工作是让密码暴力变得更加困难。如果salt具有65536个不同的值(例如),那么这意味着相同的密码可以使用65536种不同的方式进行哈希。如果有人想构建一个将哈希值反转回密码的字典,那么他的字典只需要一个密码即可获得65536个条目。
盐必须与密码无关才能发挥作用。
答案 2 :(得分:1)
你的例子的问题是,如果某个攻击者想要找到一个匹配,他们可以创建一个彩虹表,其中所有密码都被他们的md5 couterparts腌制。
每个条目的盐应该是唯一的,这样黑客就必须拥有一个反向工程表,其中包含md5与每种可能的盐的每种可能组合。
答案 3 :(得分:0)
如果你的类盐方案的目的是使用预先确定的哈希来使密码抵抗字典攻击,那么你的方法可能比未加密的哈希更安全,但不如使用有效的盐。
有效盐的一个重要安全优势是两个相同密码的实例会产生两个不同的哈希值。根据您的方案,知道一个用户的密码和哈希将允许攻击者使用相同的哈希推断另一个用户的相同密码。