zoukankan      html  css  js  c++  java
  • 内置模块之hashlib

    hashlib模块

      hashlib模块是一个内部有摘要算法的模块,而且内部可以给我们提供不止一种摘要算法。

      为什么需要摘要算法?

      由于数据的不安全性,为了保证用户的信息的绝对安全,所有敏感的数据都不应该用明文传输,而应该经过适当的处理,通过密文来存储。摘要算法就是通过对任意长度的内容经过计算,转换为一个定长的16进制的字符串,目的是保证该文件没有被篡改过。摘要算法,之所以能够做到这点,是因为算法都是不可逆的。

      为什么需要hashlib?

      1.因为不同的字符串通过摘要算法得到的密码总是不同的,相同的算法相同的字符串总是相同的。

      2.在不同的编程语言,不同的环境(操作系统,版本,时间),都是一致的,不存在差异。


    hashlib模块的使用

      hashlib模块提供了多种摘要算法:

        md5算法: 定长32位  16进制(应用最广发的摘要算法)

        sha系统算法: 定长40位  

          #sha算法要比MD5算法更加复杂,且sha N数值越大,算法越复杂,耗时越久,结果越长,但也更安全

    #hashlib模块md5摘要算法的使用
    name = 'alex'
    password = 'alex3714'               
    
    #1.首先,需要先实例化一个md5的对象,一个对象只加密一个数据
    md5_obj = hashlib.md5() 
    #2. update()方法,把需要进行MD5的对象放入
    md5_obj.update(password.encode('utf-8'))
    #3.通过hexdigest(),得到摘要算法之后的密文
    md5_password = md5_obj.hexdigest()
    print(md5_password)
    print(len(md5_password))                 #md5算法,定长32位
    >>>
    aee949757a2e698417463d47acac93df
    32
    
    # 使用sha摘要算法
    name = 'alex'
    password = 'alex3714'
    
    #操作与md5如出一辙,先创建对象,通过update加密,在通过hexdigest取值
    sha_obj = hashlib.sha1()
    sha_obj.update(password.encode('utf-8'))
    sha_password = sha_obj.hexdigest()
    print(sha_password)
    print(len(sha_password))          #sha1算法定长40位
    >>>
    8a003668a9c990f15148f9e4046e1410781533b6
    40     
    

    hashlib的应用  

    • 用户登录的验证
    name    | password
    --------+----------
    hehehe | hehehe1994
    

      有一个用户hehehe,密码为hehehe1994,如果密码就这样用明文存储,如果数据库被黑客侵入,那么密码就毫无保留的暴露给了黑客。所以这时候就需要用到摘要,在数据库中,存储密码的摘要信息。每次登陆的时候,在做摘要信息的比对。

    username | password
    ---------+---------------------------------
    michael  |69d5dd8a4651f8c77adc140c53469479
    

       所以每次登陆的时候,便需要进行密码信息的摘要比对。

    def get_md5_pws(s):
        md5_obj = hashlib.md5()
        md5_obj.update(s.encode('utf-8'))
        ret = md5_obj.hexdigest()
        return ret
    
    username = input('username>>>:').strip()
    password = input('password>>>:').strip()
    
    with open('userinfo',encoding='utf-8') as f:
        for line in f:
            usr,pwd = line.strip().split('|')
            if username == usr and get_md5_pws(password) == pwd:
                print('登录成功')
                break
        else:
            print('登录失败')
    

      通过摘要算法的手段,虽然密码是用密文的形式存储了,但是在现在的攻击手段中,有一种叫做"撞库"的手段,就是通过一个存储着大量密码与md5后的摘要对应的关系,再一一进行匹配,如果摘要信息一致,便能够反推出密码,因为同一种算法的同一个字符串,结果总是不变的。那么,有什么方法能够防止撞库?那就通过加盐值得手段(1.固定盐值  2.更好的方法:动态加盐

      何为盐值(salt),其实就是给原数据+一段指定的字符串,这样得到的MD5值就会发生变化。只要颜值不被黑客知道,那么就很难反向推出原数据。

    #加盐的md5算法,采用固定盐值(盐值:salt)
    username = 'hehehe'
    password = 'hehehe1994'
    md5_obj = hashlib.md5('salt'.encode('utf-8'))       #加盐
    md5_obj.update('alex3714'.encode('utf-8'))
    ret = md5_obj.hexdigest()
    print(ret)
    
    
    #动态加盐,通过把用户的唯一标识作为盐值,例如每个用户的用户名都是唯一
    username = 'hehehe'
    password = 'hehehe1994'
    md5_obj = hashlib.md5(username.encode('utf-8'))       #动态加盐
    md5_obj.update('alex3714'.encode('utf-8'))
    ret = md5_obj.hexdigest()
    print(ret)
    • 文件一致性的校验

      给一个文件中的所有内容进行摘要算法,得到一个md5结果。此时,我们可以体验到md5摘要算法的神奇的地方,对于同一个字符串,不管把他拆开多少段,最终得到的md5值都是一样。

    # 同一个字符串,不管拆开多少段,最终的md5都是一样的。
    
    slogan= 'hello,python'
    md5_obj1 = hashlib.md5()
    md5_obj1.update(slogan.encode('utf-8'))
    ret1 = md5_obj1.hexdigest()
    print(ret1)
    >>>
    15ac32041ff74c93c1842b152df7519e
    
    md5_obj2 = hashlib.md5()
    md5_obj2.update('hello,'.encode('utf-8'))
    md5_obj2.update('python'.encode('utf-8'))
    ret2 = md5_obj2.hexdigest()
    print(ret2)
    >>>
    15ac32041ff74c93c1842b152df7519e
    

      所以,对文件进行一致性校验。

    def get_file_md5(file_path):
        md5_obj = hashlib.md5()
        with open(file_path,encoding='utf-8') as f:
            for line in f:
                md5_obj.update(line.encode('utf-8'))
        ret = md5_obj.hexdigest()
        return ret
    • 对视频进行一致性校验

       一般是视频格式的文件/网络传输的文件,都是二进制的bytes类型。此时没有行的概念,该怎么做?此时,可以设置一个buffer,每次都读取相同长度的buffer.

    #设置一个buffer,每次都通过f.read(buffer)读取定长的数据。
    def get_video_md5(file_path,buffer=1024):
        file_size = os.path.getsize(file_path)
        md5_obj = hashlib.md5()
        with open(file_path, 'rb') as f:
            while file_size:
                content = f.read(buffer)
                file_size-= len(content)
                md5_obj.update(content)
        return md5_obj.hexdigest()
    

      

      

  • 相关阅读:
    自动化CodeReview
    10个有关RESTful API良好设计的最佳实践
    ASP.NET Core 获取控制器上的自定义属性
    [转] Autofac创建实例的方法总结
    PetaPoco
    LogViewer
    hdoj:2047
    hdoj:2046
    hdoj:2045
    hdoj:2044
  • 原文地址:https://www.cnblogs.com/hebbhao/p/9599181.html
Copyright © 2011-2022 走看看