首页 > 其他分享 >hashlib模块

hashlib模块

时间:2023-12-19 19:14:05浏览次数:33  
标签:hashlib code 加密 口令 模块 password data md5

hashlib模块

(一)什么是摘要算法

  • Python的hashlib提供了常见的摘要算法
    • 如MD5
    • SHA1等等。
  • 摘要算法又称哈希算法、散列算法。
  • 它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
  • 摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest
    • 目的是为了发现原始数据是否被人篡改过。
  • 摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数
    • 计算f(data)很容易,但通过digest反推data却非常困难。
    • 而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。

(二)摘要算法(MD5)

(1)加密数据----一次性加密(同一段数据)

#导入模块
import hashlib
#1.创建md5对象
md5=hashlib.md5()
#2.获取原始的数据,转为二进制数据
res='syh'
res=res.encode('utf-8')
#3.加密数据
md5.update(res)
#4.获取加密后的值
res=md5.hexdigest()
print(res)#df3c2a17b71f08f79902e738e6b7730c

# 摘要算法加密的特点是 : 相同的数据加密出来的加密串是一样的,不同的数据的加密串肯定是不一样的

(2)分次加密(同一段数据)

  • 如果数据量很大,可以分块多次调用update(),最后计算的结果是一样的:
import hashlib

md5 = hashlib.md5()
md5.update(b'how to use md5 in ')
md5.update(b'python hashlib?')
print(md5.hexdigest())

# 计算结果如下:
# d26a53750bc40b38b65a520292f69306
  • MD5是最常见的摘要算法,速度很快,生成结果是固定的128 bit字节,通常用一个32位的16进制字符串表示。

(2)获取加密数据

# md5加密模块
from hashlib import md5
# 如果需要十六进制的结果与二进制的结果之间的转换,需要的模块
import binascii

# 【1】准备数据

# 这里是字符串类型
data = '你好'

# 字符串转二进制数据方式一
encode_data = data.encode()
# 字符串转二进制数据方式二
# encode_data = b'你好'

# 【2】数据加密
# 构建md5对象
md5_obj = md5()
# 将数据更新到md5算法中进行数据加密 (参数为二进制数据的明文数据)
# (方法一):直接在加密算法中进行转码
# md5_obj.update("你好".encode("utf-8"))
md5_obj.update(data.encode("utf-8"))
# (方法二):先将明文数据进行转码,再传入到加密算法中
# md5_obj.update(encode_data)

# 【3】数据提取
# 拿到加密字符串 # 十六进制的结果
result_16 = md5_obj.hexdigest()
print(result_16)
# 7eca689f0d3389d9dea66ae112e5cfd7

# 拿到加密字符串 # 二进制的结果
result_2 = md5_obj.digest()
print(result_2)
# b'~\xcah\x9f\r3\x89\xd9\xde\xa6j\xe1\x12\xe5\xcf\xd7'

# 拿到加密字符串 # 十六进制的结果与二进制的结果之间的转换 (参数为result_16 或 result_2)
result_change = binascii.unhexlify(result_16)
print(result_change)
# b'~\xcah\x9f\r3\x89\xd9\xde\xa6j\xe1\x12\xe5\xcf\xd7'

(三)摘要算法升级之加盐

  • 任何允许用户登录的网站都会存储用户登录的用户名和口令。
  • 如何存储用户名和口令呢?
    • 方法是存到数据库表中:
name    | password
--------+----------
michael | 123456
bob     | abc999
alice   | alice2008
  • 如果以明文保存用户口令,如果数据库泄露,所有用户的口令就落入黑客的手里。
  • 此外,网站运维人员是可以访问数据库的,也就是能获取到所有用户的口令。
  • 正确的保存口令的方式是不存储用户的明文口令,而是存储用户口令的摘要,比如MD5:
username | password
---------+---------------------------------
michael  | e10adc3949ba59abbe56e057f20f883e
bob      | 878ef96e86145580c38c87f0410ad153
alice    | 99b1c2188db85afee403b1536010c2c9
  • 考虑这么个情况,很多用户喜欢用123456,888888,password这些简单的口令
  • 于是,黑客可以事先计算出这些常用口令的MD5值,得到一个反推表:
'e10adc3949ba59abbe56e057f20f883e': '123456'
'21218cca77804d2ba1922c33e0151105': '888888'
'5f4dcc3b5aa765d61d8327deb882cf99': 'password'
  • 这样,无需破解,只需要对比数据库的MD5,黑客就获得了使用常用口令的用户账号。
  • 对于用户来讲,当然不要使用过于简单的口令。
    • 但是,我们能否在程序设计上对简单口令加强保护呢?
  • 由于常用口令的MD5值很容易被计算出来
    • 所以,要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5
    • 这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”:
hashlib.md5("salt".encode("utf8"))
  • 经过Salt处理的MD5口令,只要Salt不被黑客知道,即使用户输入简单口令,也很难通过MD5反推明文口令。
  • 但是如果有两个用户都使用了相同的简单口令比如123456,在数据库中,将存储两条相同的MD5值,这说明这两个用户的口令是一样的。
    • 有没有办法让使用相同口令的用户存储不同的MD5呢?
  • 如果假定用户无法修改登录名,就可以通过把登录名作为Salt的一部分来计算MD5,从而实现相同口令的用户也存储不同的MD5。
  • 摘要算法在很多地方都有广泛的应用。
    • 要注意摘要算法不是加密算法,不能用于加密(因为无法通过摘要反推明文),只能用于防篡改,但是它的单向计算特性决定了可以在不存储明文口令的情况下验证用户口令。

(四)摘要算法模板

import hashlib


def get_md5_digest(salt,data):
    data = salt + data
    b_data = data.encode('utf-8')
    encrypted_data = hashlib.md5(b_data)

    return encrypted_data.hexdigest()

练习:

练习一:

  • 注册
    • 保存加密密码到json文件中
  • 登录
    • 验证json文件中的加密文件是否和登录输入的加密密码一样
"""md5加密"""
def encrypt_password(data):
    #创建md5
    md5=hashlib.md5()
    #获取数据 转为二进制
    data=data.encode('utf-8')
    #对数据进行加密
    md5.update(data)
    #获取加密数据
    data=md5.hexdigest()
    return data
def save_data(path,data,mode='w',encoding='utf-8'):
    with open(path,mode=mode,encoding=encoding)as f:
        json.dump(data,f,ensure_ascii=False)
def register():
    username=input("请输入用户名:").strip()
    password=input("请输入用户名:").strip()
    encrypt_password_data=encrypt_password(data=password)
    user_pwd={"username":username,"password":encrypt_password_data}
    save_data(path='user_pwd',data=user_pwd)

def code(x):
    code=''
    for i in range(x):
        list=[str(random.randint(0,9)),chr(random.randint(97,122)),chr(random.randint(65,90))]
        code_choice=random.choice(list)
        code+=code_choice
    return code
def read_data(path,mode='r',encoding='utf-8'):
    with open(path,mode=mode,encoding=encoding)as f:
        data=json.load(f)
    return data
def login():
    username=input("请输入用户名:").strip()
    password=input("请输入用户名:").strip()
    data=read_data(path='user_pwd')
    #将登录输入的密码加密
    md5=hashlib.md5()
    password=password.encode('utf-8')
    md5.update(password)
    encrypt_password =md5.hexdigest()
    #比较登录加密后的密码 和注册加密的密码
    if encrypt_password!=data['password']:
        return  "密码错误"
    #获取验证码
    choice_code=code(6)
    print(choice_code)
    #输入验证码
    code_input=input("请输入验证码:").strip()
    #比较验证码
    if code_input.lower()!=choice_code.lower():
        return "验证码有误!"
    return  f"{username}登录成功!"

练习二:

  • 注册
    • 加盐加密
    • 记得保存注册时候生成的未加密的盐
  • 登录
    • 将注册时生成的盐找出来
    • 将登录输入的密码与注册时候的盐进行加密
    • 比较登录注册加盐加密的密码
    • 相同登录成功!不同登录失败!
"""加盐加密"""
def code(x):
    code=''
    for i in range(x):
        list=[str(random.randint(0,9)),chr(random.randint(97,122)),chr(random.randint(65,90))]
        choice_code=random.choice(list)
        code+=choice_code
    return code

def encrypt(data,salt):
    encrypt_password=data+salt
    #获取md5
    md5=hashlib.md5()
    #获取二进制的数据
    encrypt_password=encrypt_password.encode('utf-8')
    #对数据进行加密
    data=md5.update(encrypt_password)
    #获取机密后的数据
    encrypt_password=md5.hexdigest()
    return encrypt_password
def  save_data(path ,data,mode='w',encoding='utf-8'):
    with open(path,mode=mode,encoding=encoding)as f:
        json.dump(data,f,ensure_ascii=False)

def  regsiter():
    username=input("请输入用户名:").strip()
    password=input("请输入用户名:").strip()
    #加密密码时加盐
    salt=code(4)
    # 对密码进行加密
    encrypt_password = encrypt(data=password,salt=salt)
    user_pwd={username:{'username':username,'password':encrypt_password,'salt':salt}}
    save_data(path='user_pwd.json',data=user_pwd)
# regsiter()
def read_data(path,mode='r',encoding='utf-8'):
    with open(path,mode=mode,encoding=encoding)as f:
        data=json.load(f)
    return data
def login():
    username=input("请输入用户名:").strip()
    password=input("请输入用户名:").strip()
    #生成随机六位验证码
    choice_code=code(6)
    print(choice_code)
    code_input=input("请输入验证码:").strip()
    #比较验证码
    if choice_code.lower()!=code_input.lower():
        return f"验证码有误!"
    #读取json文件中的数据
    user_pwd_dict=read_data(path='user_pwd.json')
    user_pwd=user_pwd_dict.get(username)
    #获取文件中注册时存入的盐
    salt=user_pwd.get('salt')
    #将登录输入的密码和注册时的盐进行加密
    #{"username": "syh", "password": "60e6a3d07d40c5d79a6a24b7975d001a", "salt": "r15h"}
    password=encrypt(data=password,salt=salt)
    #将登录输入的加盐加密后的密码与注册时加盐加密的密码比较
    if password!=user_pwd.get('password'):
        return f"密码错误"
    return f"登录成功!"
print(login())

# 请输入用户名:syh
# 请输入用户名:123
# hC07Hq
# 请输入验证码:hC07Hq
# 登录成功!

标签:hashlib,code,加密,口令,模块,password,data,md5
From: https://www.cnblogs.com/suyihang/p/17914481.html

相关文章

  • os模块
    os模块(一)文件操作(os)__file__是指当前文件(二)文件路径相关(path)(1)获取当前文件路径(abspath)#获取当前文件路径abspath#print(os.path.abspath(__file__))#D:\oldboy\python\python28基础\day19\02os模块.py(2)获取当前文件所在的文件夹路径(dirname)#获取当前文件所在文件夹......
  • random模块
    random模块(一)导入模块importrandom(二)随机小数默认区间的小数random.random()默认为0-1直接指定区间的小数random.uniform()可以指定起始结束参数(1)默认区间的小数random.random#随机生成默认区间内的小数print(random.random())#0.6827460153816446(2)指定区间的......
  • time模块
    time模块表示时间的三种方式时间戳元组(struct_time)格式化的时间字符串:格式化的时间字符串(FormatString):‘1999-12-06’(1)导入模块importtime(2)时间戳(time)(1)生成时间戳生成时间戳,时间戳是浮点数类型##时间戳##time=time.time()##print(time)......
  • python中导入模块/包的几种方式
    一、模块的导入方式模块就是.py类型的Python文件导入时不需要.py后缀,直接导入文件名即可1.利用import直接导入:语法:importmodule_name使用方式:module_name.class_name或者module.func_name2.利用import导入模块并设置一个别名语法:importmodule_nameasXXX使用方式:XXX.cl......
  • 理解ROS2的坐标转换模块tf2
    0概述tf2是ROS的核心库之一,它记录了所有坐标系的转换关系,包括动态坐标转换tf,和静态坐标转换tf_static;首先,介绍tf2库(即,geometry2)编译/调试环境的搭建步骤;然后,介绍部分的类图结构,和调用时序;1搭建ROS2的编译环境参考:http://docs.ros.org/en/iron/Installation/Ubuntu-Install-D......
  • Numpy模块
    Numpy模块的核心就是基于数组的运算,相比于列表和其他数据结构,数组的运算效率是最高的。常用的数学函数np.pi常数pnp.e常数enp.fabs(arr)  例如:np.fabs(-3) 计算各元素的浮点型绝对值np.ceil(arr) 例如:np.ceil(3.2)对元素向上取整np.floor(arr) 类似ceil 向下取整对......
  • DC电源模块的安装和使用步骤是什么?
    DC电源模块的安装和使用步骤是什么?安装和使用DC电源模块的步骤如下:确定模块的电源需求:查阅模块的规格和说明书,确定所需的输入电压范围和输出电流能力。配置电源线:根据电源模块的输入要求,选择合适的电源线。确保电源线具备足够的额定电流和正确的接线方式。连接电源线:将电源线的一......
  • BOSHIDA DC电源模块的安装和使用步骤是什么?
    BOSHIDADC电源模块的安装和使用步骤是什么?安装和使用DC电源模块的步骤如下: 1.确定模块的电源需求:查阅模块的规格和说明书,确定所需的输入电压范围和输出电流能力。2.配置电源线:根据电源模块的输入要求,选择合适的电源线。确保电源线具备足够的额定电流和正确的接线方式。3......
  • Git:submodule子模块操作
    一、子模块添加gitsubmoduleadd<url><path>gitsubmoduleaddhttps://github.com/../.gitthemes/MeiFixIt二、子模块更新gitsubmoduleupdate--remote--merge三、下载子模块同父模块一起下载子模块gitclone--recurse-submodules<repository-url>父模块......
  • 【GD32307E-START】06 ST7735 SPI-LCD显示模块移植
    软硬件平台GD32F307E-STARTBoard开发板GCCMakefile1.8寸TFTLCD分辨率128*160驱动ICST7735S接口定义序号引脚标号说明1GND接地2VCC5V/3.3V电源输入3SCKSPI总线时钟信号4SDASPI总线写数据信号5RESET液晶屏复位信号,低电平复位6DC......