1. hmac
    2. 阅读: 2
    3. 通过哈希算法,我们可以验证一段数据是否有效,方法就是对比该数据的哈希值,例如,判断用户口令是否正确,我们用保存在数据库中的password_md5对比计算md5(password)的结果,如果一致,用户输入的口令就是正确的。
    4. 为了防止黑客通过彩虹表根据哈希值反推原始口令,在计算哈希的时候,不能仅针对原始输入计算,需要增加一个salt来使得相同的输入也能得到不同的哈希,这样,大大增加了黑客破解的难度。
    5. 如果salt是我们自己随机生成的,通常我们计算MD5时采用md5(message + salt)。但实际上,把salt看做一个"口令",加salt的哈希就是:计算一段message的哈希时,根据不通口令计算出不同的哈希。要验证哈希值,必须同时提供正确的口令。
    6. 这实际上就是Hmac算法:Keyed-Hashing for Message Authentication。它通过一个标准算法,在计算哈希的过程中,把key混入计算过程中。
    7. 和我们自定义的加salt算法不同,Hmac算法针对所有哈希算法都通用,无论是MD5还是SHA-1。采用Hmac替代我们自己的salt算法,可以使程序算法更标准化,也更安全。
    8. Python自带的hmac模块实现了标准的Hmac算法。我们来看看如何使用hmac实现带key的哈希。
    9. 我们首先需要准备待计算的原始消息message,随机key,哈希算法,这里采用MD5,使用hmac的代码如下:
    10. >>> import hmac
    11. >>> message = b'Hello, world!'
    12. >>> key = b'secret'
    13. >>> h = hmac.new(key, message, digestmod='MD5')
    14. >>> # 如果消息很长,可以多次调用h.update(msg)
    15. >>> h.hexdigest()
    16. 'fa4ee7d173f2d97ee79022d1a7355bcf'
    17. 可见使用hmac和普通hash算法非常类似。hmac输出的长度和原始哈希算法的长度一致。需要注意传入的keymessage都是bytes类型,str类型需要首先编码为bytes
    18. 练习
    19. 将上一节的salt改为标准的hmac算法,验证用户口令:
    20. # -*- coding: utf-8 -*-
    21. import hmac, random
    22. def hmac_md5(key, s):
    23. return hmac.new(key.encode('utf-8'), s.encode('utf-8'), 'MD5').hexdigest()
    24. class User(object):
    25. def __init__(self, username, password):
    26. self.username = username
    27. self.key = ''.join([chr(random.randint(48, 122)) for i in range(20)])
    28. self.password = hmac_md5(self.key, password)
    29. db = {
    30. 'michael': User('michael', '123456'),
    31. 'bob': User('bob', 'abc999'),
    32. 'alice': User('alice', 'alice2008')
    33. }
    34. def login(username, password):
    35. user = db[username]
    36. return user.password == hmac_md5(user.key, password)
    37. # 测试:
    38. assert login('michael', '123456')
    39. assert login('bob', 'abc999')
    40. assert login('alice', 'alice2008')
    41. assert not login('michael', '1234567')
    42. assert not login('bob', '123456')
    43. assert not login('alice', 'Alice2008')
    44. print('ok')
    45. Run
    46. 小结
    47. Python内置的hmac模块实现了标准的Hmac算法,它利用一个keymessage计算"杂凑"后的hash,使用hmac算法比标准hash算法更安全,因为针对相同的message,不同的key会产生不同的hash