我一直在使用PHP crypt()作为在我的数据库中存储和验证密码的方法.我对其他东西使用散列,但是crypt()对于密码.文档不是很好,似乎有很多争论.我正在使用河豚和两种盐来加密密码并将其存储在数据库中.在我存储salt和加密密码之前(如盐腌哈希)但实现了它的冗余,因为salt是加密密码字符串的一部分.
我对彩虹表攻击如何工作有点困惑crypt(),无论如何从安全的角度来看这看起来是正确的.我使用第二个盐来附加密码以增加短密码的熵,可能是矫枉过正,但为什么不呢?
function crypt_password($password) {
if ($password) {
//find the longest valid salt allowed by server
$max_salt = CRYPT_SALT_LENGTH;
//blowfish hashing with a salt as follows: "$2a$", a two digit cost parameter, "$", and 22 base 64
$blowfish = '$2a$10$';
//get the longest salt, could set to 22 crypt ignores extra data
$salt = get_salt ( $max_salt );
//get a second salt to strengthen password
$salt2 = get_salt ( 30 ); //set to whatever …Run Code Online (Sandbox Code Playgroud) 好吧,所以我试着在我的java应用程序中学习加密消息.我刚刚发现SALT和KEY不一样.
有人能帮助我理解两者之间的区别是什么吗?
如果数据库中的表格如下:
userid uniqueidentifier
username varchar(20)
password varbinary(max)
Run Code Online (Sandbox Code Playgroud)
当用户提交(注册)时,我将用户/传递发送到存储过程.
存储过程创建一个新的GUID(使用NEWID())然后我使用SQL Server 的HashBytes(sha1)函数根据提供的GUID +密码创建密码然后我将值插入上面的表.
当用户提交(登录)时,我将用户/传递发送到存储过程.
存储过程查找用户名并获取用户ID以将guid +密码的hashbyte(sha1)与密码字段进行比较.
你看到那个逻辑中有任何缺陷吗?
我已经阅读了PHP手册输入中crypt()提供的信息,但我发现自己仍然不确定触发Blowfish算法的salt的格式.
根据手动输入,我应该使用'$ 2 $'或'$ 2a $'作为16个字符串的开头.然而,在以后的例子中,他们使用更长的字符串:" $2a$07$usesomesillystringforsalt$",这表明,我认为任何字符串我提供将切片和切块以适应模型.
我遇到的问题实际上是触发河豚算法中VS STD_DES.例:
$foo = 'foo';
$salt = '$2a$' . hash('whirlpool', $foo); // 128 characters, will be truncated
$hash = crypt($foo, $salt);
// $hash = $26HdMTpoODt6
Run Code Online (Sandbox Code Playgroud)
那哈希显然不是漩涡,事实上STD_DES只有盐的前两个字符用于盐.但是,在PHP手册的例子中,他们的盐以' $2a$07$' 开头,所以如果我将这三个字符添加到相同的代码中,我得到以下内容:
$foo = 'foo';
$salt = '$2a$' . hash('whirlpool', $foo); // 128 characters, will be truncated
$hash = crypt($foo, $salt);
// $hash = $2a$07$b1b2ee48991281a439da2OHi1vZF8Z2zIA.8njYZKR.9iBehxLoIC
Run Code Online (Sandbox Code Playgroud)
我发现我可以提供在此处显示为"人物存在一些差异07$",例如04$和15$两个工作,但01$通过03$不工作(生成一个空字符串),和值等99$,并85$ …
我通过使用我的密码生成salt和hash值,
string salt = CreateSalt(TxtPassword.Text.Length);
string hash = CreatePasswordHash(TxtPassword.Text, salt);
private static string CreateSalt(int size)
{
//Generate a cryptographic random number.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[size];
rng.GetBytes(buff);
// Return a Base64 string representation of the random number.
return Convert.ToBase64String(buff);
}
private static string CreatePasswordHash(string pwd, string salt)
{
string saltAndPwd = String.Concat(pwd, salt);
string hashedPwd =
FormsAuthentication.HashPasswordForStoringInConfigFile(
saltAndPwd, "sha1");
return hashedPwd;
}
Run Code Online (Sandbox Code Playgroud)
您建议在sql server中存储这些值的数据类型是什么?任何建议......
盐:9GsPWpFD
哈希:E778AF0DC5F2953A00B35B35D80F6262CDBB8567
好吧,我知道这可能很简单,但我似乎无法在任何地方找到答案.假设我有以下内容:
Password: "mypassword"
Salt: 1234567
Run Code Online (Sandbox Code Playgroud)
腌制的想法是做什么样的hash(password + salt)或hash(password) + salt?我的猜测是,只有前者才有意义,但我只是想确保我不会错过任何东西.
请原谅我的无知.
假设我为每个用户存储一个随机盐值.更改用户密码时是否必须生成新的salt值,或者在该用户帐户的整个生命周期内使用相同的值?
我正在设计一个如下所示的身份验证系统:
WHERE `Password` = SHA1(CONCAT('$hashedPassword',`Salt`)) AND [..]
Run Code Online (Sandbox Code Playgroud)
目前我的盐是64字节.这足以使词典攻击变得不可行吗?
我确定sha1已知漏洞,但它是我可以在数据库层使用的我的MySQL(5.1)版本上唯一可用的功能,而不是通过应用程序和数据库层之间的连接选择普通的盐.
我需要两个函数/方法,一个用于编码,一个用于解码.这不是用于存储密码.每个用户都有一个特定的密钥/盐来编码数据.
这就是我希望它的工作方式:
function encode($str, $key) {
// something fancy
}
function decode($str, $key) {
// something fancy
}
$key = $logged_in_user->get_key();
$plain = 'abc abc 123 123';
$encoded_data = encode($plain, $key);
// some_fancy_encrypted_data_that_is_really_cooooool
$decoded_data = decode($encoded_data, $key);
// abc abc 123 123
Run Code Online (Sandbox Code Playgroud)
另一件事是每次我使用这个函数时,每次我使用encode具有相同用户密钥的函数时,它都需要返回相同的东西.
我该怎么办?
随着最近(例如LinkedIn)关于密码的讨论,我正在研究密码哈希实现.喝完两杯咖啡和早上读书后,我不再是一个密码学家了.我真的不想假装自己.
使用整数唯一用户ID失败是否有效?(crypt()只使用16位?)
如果我只是一遍又一遍地在哈希上运行sha256(),直到一秒钟用完就能击败蛮力攻击?
如果我必须问这些问题我应该使用bcrypt吗?
目标很简单,如果我的用户的哈希密码被泄露了:
我在#1中读到的是哈希计算必须是昂贵的 - 例如,计算一两秒或者可能需要一点或内存(以阻止硬件解密).
bcrypt有这个内置的,如果我理解正确的话,scrypt更具有前瞻性,并且包含最低内存使用要求.
但是,通过"重新散布"sha256()的结果,需要多次使用几秒钟,然后将最终循环计数与哈希值一起存储以便稍后检查提供的密码,这是一种同样有效的方法吗?
对于#2,为每个密码使用唯一的盐很重要.目前尚不清楚的是盐必须是随机的(或大的).如果目标是避免使用"mypassword"作为密码的每个人拥有相同的哈希,那么仅仅这样做是不够的?:
hash = sha256_hex( unique_user_id + user_supplied_password );
Run Code Online (Sandbox Code Playgroud)
甚至这个,虽然我不确定它会给我什么:
hash = sha256_hex( sha256( unique_user_id ) + user_supplied_password );
Run Code Online (Sandbox Code Playgroud)
使用用户ID可以看到的唯一好处,除了我知道它是唯一的,是避免必须保存盐与哈希.没有多大优势.使用用户的ID作为盐是否存在真正的问题?它没有完成#2吗?
我假设如果有人可以窃取我的用户的哈希密码,那么我必须假设他们可以得到他们想要的任何东西 - 包括生成哈希的源代码.那么,在散列之前向密码添加额外的随机字符串(相同的字符串)是否有任何好处?那是:
# app_wide_string = one-time generated, random 64 7-bit *character* string.
hash = sha256_hex( unique_user_id + app_wide_string + user_supplied_password );
Run Code Online (Sandbox Code Playgroud)
我已经看到了这个建议,但我不明白我从那个用户的盐中得到了什么.如果有人想强行攻击他们会知道"app_wide_string"并在运行他们的字典攻击时使用它,对吗?
如上所述,是否有充分的理由使用bcrypt滚动我自己?也许我问这些问题的理由足够了吗?
顺便说一句 - 我只是计算了我现有的散列函数和我的笔记本电脑,我每秒可以生成大约7000个哈希值.不太经常建议的一两秒钟.
一些相关链接: