2012-08-02 147 views
1

使用:Python 3.2.3,scrypt 0.5.5模块,Ubuntu 12.04Python 3,Scrypt模块,哈希不匹配

我安装了很好的scrypt模块。我在页面上运行了示例代码。我也发现了一个expanded version of the sample code,它也很好。但是我想测试它是否会对相同的单词进行两次散列,因此我添加了对Encrypt()的部分调用来模拟为数据库散列一次的概念,然后在用户登录时再次散列,因此我的完整代码看起来像这样:

import random,scrypt 

class Encrypt(object): 

    def __init__(self): 
     pass 

    def randSTR(self,length): 
     return ''.join(chr(random.randint(0,255)) for i in range(length)) 

    def hashPWD(self,pwd, maxtime=0.5, datalength=64): 
     return scrypt.encrypt(self.randSTR(datalength), pwd, maxtime=maxtime) 

    def verifyPWD(self,hashed_password, guessed_password, maxtime=0.5): 
     try: 
      scrypt.decrypt(hashed_password, guessed_password, maxtime) 
      return True 
     except scrypt.error: 
      return False 

if __name__ == '__main__': 
    e = Encrypt() 
    user_pw = 'theansweris42' 
    user_salt = 't9' 
    pw_salt = user_pw + user_salt 
    hashed_pw = e.hashPWD(pw_salt) # To be stored len()==192 
    y = e.verifyPWD(hashed_pw, pw_salt)    # True 
    n = e.verifyPWD(hashed_pw, 'guessing'+ pw_salt) # False 
    print(y) 
    print(n) 
    #print("Hash: %s" % (hashed_pw)) 

    x = Encrypt() 
    user_pw2 = 'theansweris42' 
    user_salt2 = 't9' 
    pw_salt2 = user_pw2 + user_salt2 
    hashed_pw2 = x.hashPWD(pw_salt2) # To be stored len()==192 
    y2 = x.verifyPWD(hashed_pw, hashed_pw2)    # True 
    print(y2) 
    print(pw_salt) 
    print(pw_salt2) 
    print(hashed_pw) 
    print(hashed_pw2) 

......正如你所看到的,我也硬编码盐(测试)。奇怪的是,每次我运行这个时,hashed_pw & hashed_pw2总是不同的。为什么每次都以不同的方式散列相同的密码?每次我给它输入完全相同的输入时,它不应该输出相同的散列吗?我一直试图弄清楚这个问题一个小时,所以我想我最好问。

回答

0

您使用相同的密码(加上盐)加密两个不同的随机字符串。这将导致两个不同的输出。

这里使用的技巧是密码+ salt可以用来解密随机字符串,而不正确的密码会引发错误。因此,您不需要存储原始随机字符串以确保密码正确,并且由于使用的字符串是随机的(在随机数生成器的限制范围内),因此破解密码将非常困难。

+0

我想我不理解的东西。我对此有点新,所以我很抱歉,如果我问一些'愚蠢的',但是......我如何加密两个不同的随机字符串?它是不是两次散列字符串“theansweris42t9”?该字符串是'pw_salt'和'pw_salt2'的值,所以当我对它们进行哈希处理时,它应该输出相同的值,对吧? – Zamphatta 2012-08-06 12:27:32

+0

此外,我必须在数据库中存储一些内容(散列密码和盐?),以便稍后在用户登录时进行比较,对吧? – Zamphatta 2012-08-06 12:34:50

+0

@ Zamphatta:不,你正在加密的字符串是self.randSTR(datalength)。是的,你需要存储散列和盐。但是你不会比较任何东西,只需使用密码和salt解密存储的散列。 – 2012-08-06 13:13:10