哈希算法 - 哈希摘要 - 数字签名/数字指纹 - 防篡改/保护敏感信息
-
哈希算法是一个单向运算的函数(单向哈希函数)
-
通过哈希算法可以将对象计算出哈希摘要,但是哈希摘要无法还原出原来的对象
-
Martin Fowler - 代码有很多种坏味道,重复是最坏的一种
当代码已经充斥着各种坏味道的时候就需要对代码进行重构(refactor)
策略模式
import hashlib
class StreamHasher(object):
def __init__(self, algorithm='md5', size=4096):
self.size = size
alg = algorithm.lower()
if alg == 'md5':
self.hasher = hashlib.md5()
elif alg == 'sha1':
self.hasher = hashlib.sha1()
elif alg == 'sha256':
self.hasher = hashlib.sha256()
elif alg == 'sha512':
self.hasher = hashlib.sha512()
else:
raise ValueError('不支持指定的哈希算法')
def to_md5_digest(self, stream):
'''生成MD5摘要'''
for buf in iter(lambda: stream.read(self.size), b''):
self.hasher.update(buf)
return self.hasher.hexdigest()
def __call__(self, stream):
return self.to_md5_digest(stream)
加密解密
- 对称加密- 加密和揭秘使用同一个密钥 - DES(过时)/AES
- 非对称加密 - 加密和解密使用不同的密钥 - RSA
- pip install pycrypto
编码和解码 - 将内存中的二进制数据处理成其他的形式 - BASE64
- BASE64 - 用64个字符(a-zA-Z0-9/+)表示所有的二进制数据
110000 111010 11100 110101
00110000 00111010 00011100 00110101
魔术方法
- 如果该自定义对象要放到set种那么需要重写两个魔术方法
- hash - 计算出对相对应的哈希码
- eq - '=='运算符对应的方法用来比较两个对象是否相同
- 重写eq的前提是必须先重写hash
- 如果两个对象eq的结果为True那么必须有相同的哈希码
- 如果该两个对象哈希码相同但是eq的结果可能时True也可能时False
- 相同对象必须有相同的哈希码, 不同的对象可能会产生相同的哈希码(哈希碰撞)
- 哈希存储(散列存储) - 通过计算对象的哈希码决定如何存储对象
- 哈希算法 - MD5/SHA1/SHA256/SHA512
class Student(object):
def __init__(self, stuid, name, gender):
self.stuid = stuid
self.name = name
self.gender = gender
def __hash__(self):
return self.stuid
def __eq__(self, other):
# return self.stuid == other.stuid
return self.stuid == other.stuid and self.name == other.name
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
# 当类中的方法要需要使用上下文语法时, 如 with create_studetn() as stu, 必须先定义__enter__和__exit__两个方法来对方法的开始和结束进行处理, 如数据库的开启和关闭.
pass
def create_student(self):
pass
整体代码
import hashlib
class StreamHasher(object):
def __init__(self, algorithm='md5', size=4096):
self.size = size
alg = algorithm.lower()
if alg == 'md5':
self.hasher = hashlib.md5()
elif alg == 'sha1':
self.hasher = hashlib.sha1()
elif alg == 'sha256':
self.hasher = hashlib.sha256()
elif alg == 'sha512':
self.hasher = hashlib.sha512()
else:
raise ValueError('不支持指定的哈希算法')
def to_md5_digest(self, stream):
'''生成MD5摘要'''
for buf in iter(lambda: stream.read(self.size), b''):
self.hasher.update(buf)
return self.hasher.hexdigest()
def __call__(self, stream):
return self.to_md5_digest(stream)
class Student(object):
def __init__(self, stuid, name, gender):
self.stuid = stuid
self.name = name
self.gender = gender
def __hash__(self):
return self.stuid
def __eq__(self, other):
# return self.stuid == other.stuid
return self.stuid == other.stuid and self.name == other.name
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
# 当类中的方法要需要使用上下文语法时, 如 with create_studetn() as stu, 必须先定义__enter__和__exit__两个方法来对方法的开始和结束进行处理, 如数据库的开启和关闭.
pass
def create_student(self):
pass
def main():
# with open('C:\\Users\\ap-le\Desktop\\PokerGame.py', 'rb') as stream:
# # 分流读入文件, 节省内存
# buf = stream.read(4096)
# while buf:
# hasher.update(stream.read())
# buf = stream.read(4096)
# print(hasher.hexdigest())
#
# # 使用迭代对象读入文件
# with open('C:\\Users\\ap-le\Desktop\\PokerGame.py', 'rb') as stream:
# for buf in iter(lambda: stream.read(4096), b''):
# hasher.update(buf)
# print(hasher.hexdigest())
# sh = StreamHasher()
# sh = StreamHasher('sha1')
# sh = StreamHasher('sha256')
sh = StreamHasher('sha512')
with open('C:\\Users\\ap-le\Desktop\\PokerGame.py', 'rb') as stream:
print(sh.to_md5_digest(stream))
print(sh(stream))
print('-'*50)
set1 = {
Student(1001, 'Jefferson', True),
Student(1001, 'Jefferson', True),
Student(1001, '王大锤', True)
}
print(len(set1))
print(set1)
if __name__ == '__main__':
main()
网友评论