编程语言
首页 > 编程语言> > python网络编程之hsahlib 加密 文件效验 服务端的合法性效验 TCP登陆

python网络编程之hsahlib 加密 文件效验 服务端的合法性效验 TCP登陆

作者:互联网

hashlib模块

hashlib 这个模块是一堆加密算法的集合体,哈希算法的加密方式不止一种
https://www.cmd5.com/ md5解密
应用场景:在需要效验功能时使用
  用户密码的 => 加密,解密
  相关效验的 => 加密,解密

哈希算法也叫摘要算法,相同的数据始终得到相同的输出,不同的数据得到不同的输出。
(1)哈希将不可变的任意长度的数据,变成具有固定长度的唯一值
(2)字典的键和集合的值是通过哈希计算存储的,存储的数据是散列(无序)

 

hashlib

场景: 网站密码加密
hashlib模块的加密原则是单向不可逆的


md5算法 : 可以把字符串变成具有固定长度的32位十六进制字符串

撞库破解

111222  => 00b7691d86d96aebd21dd9e138f90840
222333  => 00b7691d86d96aebd21dd9e138f90842

 

基本语法

import hashlib
import random

# ### 基本语法
# (一)md5对象
# 1.创建md5对象
hs = hashlib.md5()
# 2.把要加密的数据更新到对象中  [update => 把字节流更新到对象之后,进行加密]
hs.update("111222".encode("utf-8"))
# 3.获取十六进制的字符串
res = hs.hexdigest()
print(res   ,   len(res))  # 00b7691d86d96aebd21dd9e138f90840 


# 加盐 (加key , 加一个关键字)
hs = hashlib.md5("XBOYww_".encode())
hs.update("111222".encode())
res = hs.hexdigest()
print(res)  # 623e0e8d4ecabd638c36a5e40189ba8f


# 动态加盐
res = str(random.randrange(100000,1000000))
hs = hashlib.md5(res.encode())
hs.update("111222".encode())
res = hs.hexdigest()
print(res)

# (二)sha系列算法
"""无论是加盐 还是 加密密码,都需要数据类型为二进制字节流"""
# hs = hashlib.sha1()  # 结果是具有固定长度40位的十六进制字符串;
hs = hashlib.sha512("XGIRLww_".encode())  # 结果是具有固定长度128位的十六进制字符串
hs.update("sha系列算法".encode())
res = hs.hexdigest()
"""20c2502d0e00bf8fe35ebfbf097049d1f070e7968f30ef3353ff33d311af50da6b3883bfb9ab411f9dc4cdcd2310b39f5815c6dc1c48cd138d07443a6bcdcd11 128"""
print(res , len(res))  

 
# (三)hmac加密算法
import hmac
import os
key = b"xdogaa_"
msg = b"112233"
# new(盐(字节流),密码(字节流) )
hm = hmac.new(key,msg)
res = hm.hexdigest()
"""
eebe14b1c144092121236cb1e3da396a
"""
print(res , len(res))

# 动态加盐
"""
os.urandom(位数) 返回随机的二进制字节流
res = os.urandom(10)
print(res , len(res))
"""

key = os.urandom(64)
msg = b"112233"
hm = hmac.new(key,msg)
res = hm.hexdigest()
print(res , len(res))
View Code

文件效验

"""
mode = "r"  fp.read(3) 3个字符
mode = "rb" fp.read(3) 3个字节
"""
import hashlib
import os
# (1) 针对于小文件进行校验
def check_md5(filename):
    hs = hashlib.md5()
    with open(filename , mode="rb" ) as fp:
        hs.update(fp.read())
        # return fp.read() 仅仅适用于小文件
    return hs.hexdigest()
    
res1 = check_md5("lianxi1.py")
res2 = check_md5("lianxi2.py")
print(res1 == res2)


# (2) 针对于大文件进行校验
"""update 可以分批次进行加密  等价于一次性加密的结果"""
# update的使用
strvar = "今天是周五,明天自习"
hs = hashlib.md5()
hs.update(strvar.encode())
res1 = hs.hexdigest()
print(res1)

strvar2 = ",周一上午考试,小人射击+计算器"
hs.update(strvar2.encode())
res2 = hs.hexdigest()
print(res2) # 0163aa435c2eea52fac354ba7e6c84da

strvar = "今天是周五,明天自习,周一上午考试,小人射击+计算器"
hs2 = hashlib.md5()
hs2.update(strvar.encode())
print(hs2.hexdigest()) # 0163aa435c2eea52fac354ba7e6c84da

# 方法一
def check_md5(filename):
    hs = hashlib.md5()
    with open(filename,mode="rb") as fp:
        while True:
            # 最多读取5个字节
            content = fp.read(5)
            # 判断读取的字节如果是空,终止循环
            if content:            
                hs.update(content)
            else:
                break
        return hs.hexdigest()

res1 = check_md5("lianxi1.py")
res2 = check_md5("lianxi2.py")
print(res1 , res2)

# 方法二
def check_md5(filename):
    hs = hashlib.md5()
    filesize = os.path.getsize(filename)
    print(filesize)
    with open(filename,mode="rb") as fp:
        # filesize 如果为空,循环终止;
        while filesize:
            content = fp.read(100)
            hs.update(content)
            # 减去实际读取的字节长度
            filesize -= len(content)
        
        return hs.hexdigest()        
        
res1 = check_md5("lianxi1.py")
res2 = check_md5("lianxi2.py")
print(res1 , res2)
View Code

 

肉眼根本看不出下面两个文件哪不一样 

lianxi1.py文件

# ### hashlib 
"""
场景: 网站密码加密
hashlib模块的加密原则是单向不可逆的
md5算法 : 可以把字符串变成具有固定长度的32位十六进制字符串
"""

# 撞库
"""
111222  => 00b7691d86d96aebd21dd9e138f90840
222333  => 00b7691d86d96aebd21dd9e138f90842
"""

import hashlib
import random

# ### 基本语法
# (一)md5对象
# 1.创建md5对象
hs = hashlib.md5()
# 2.把要加密的数据更新到对象中  [update => 把字节流更新到对象之后,进行加密]
hs.update("111222".encode("utf-8"))
# 3.获取十六进制的字符串
res = hs.hexdigest()
print(res   ,   len(res))  # 00b7691d86d96aebd21dd9e138f90840 


# 加盐 (加key , 加一个关键字)
hs = hashlib.md5("XBOYww_".encode())
hs.update("111222".encode())
res = hs.hexdigest()
print(res)  # 623e0e8d4ecabd638c36a5e40189ba8f


# 动态加盐
res = str(random.randrange(100000,1000000))
hs = hashlib.md5(res.encode())
hs.update("111222".encode())
res = hs.hexdigest()
print(res)

# (二)sha系列算法
"""无论是加盐 还是 加密密码,都需要数据类型为二进制字节流"""
# hs = hashlib.sha1()  # 结果是具有固定长度40位的十六进制字符串;
hs = hashlib.sha512("XGIRLww_".encode())  # 结果是具有固定长度128位的十六进制字符串
hs.update("sha系列算法".encode())
res = hs.hexdigest()
"""20c2502d0e00bf8fe35ebfbf097049d1f070e7968f30ef3353ff33d311af50da6b3883bfb9ab411f9dc4cdcd2310b39f5815c6dc1c48cd138d07443a6bcdcd11 128"""
print(res , len(res))  

 
# (三)hmac加密算法
import hmac
import os
key = b"xdogaa_"
msg = b"112233"
# new(盐(字节流),密码(字节流) )
hm = hmac.new(key,msg)
res = hm.hexdigest()
"""
eebe14b1c144092121236cb1e3da396a
"""
print(res , len(res))

# 动态加盐
"""
os.urandom(位数) 返回随机的二进制字节流
res = os.urandom(10)
print(res , len(res))
"""

key = os.urandom(64)
msg = b"112233"
hm = hmac.new(key,msg)
res = hm.hexdigest()
print(res , len(res))
View Code

lianxi2.py文件

# ### hashlib 
"""
场景: 网站密码加密
hashlib模块的加密原则是单向不可逆的
md5算法 : 可以把字符串变成具有固定长度的32位十六进制字符串
"""

# 撞库
"""
111222  => 00b7691d86d96aebd21dd9e138f90840
222333  => 00b7691d86d96aebd21dd9e138f90842
"""

import hashlib
import random

# ### 基本语法
# (一)md5对象
# 1.创建md5对象
hs = hashlib.md5()
# 2.把要加密的数据更新到对象中  [update => 把字节流更新到对象之后,进行加密]
hs.update("111222".encode("utf-8"))
# 3.获取十六进制的字符串
res = hs.hexdigest()
print(res   ,   len(res))  # 00b7691d86d96aebd21dd9e138f90840 


# 加盐 (加key , 加一个关键字)
hs = hashlib.md5("XBOYww_".encode())
hs.update("111222".encode())
res = hs.hexdigest()
print(res)  # 623e0e8d4ecabd638c36a5e40189ba8f


# 动态加盐
res = str(random.randrange(100000,1000000))
hs = hashlib.md5(res.encode())
hs.update("111222".encode())
res = hs.hexdigest()
print(res)

# (二)sha系列算法
"""无论是加盐 还是 加密密码,都需要数据类型为二进制字节流"""
# hs = hashlib.sha1()  # 结果是具有固定长度40位的十六进制字符串;
hs = hashlib.sha512("XGIRLww_".encode())  # 结果是具有固定长度128位的十六进制字符串
hs.update("sha系列算法".encode())
res = hs.hexdigest()
"""20c2502d0e00bf8fe35ebfbf097049d1f070e7968f30ef3353ff33d311af50da6b3883bfb9ab411f9dc4cdcd2310b39f5815c6dc1c48cd138d07443a6bcdcd11 128"""
print(res , len(res))  

 
# (三)hmac加密算法
import hmac
import os
key = b"xdogaa_"
msg = b"112233"
# new(盐(字节流),密码(字节流) )
hm = hmac.new(key,msg)
res = hm.hexdigest()
"""
eebe14b1c144092121236cb1e3da396a
"""
print(res , len(res))

# 动态加盐
"""
os.urandom(位数) 返回随机的二进制字节流
res = os.urandom(10)
print(res , len(res))
"""

key = os.urandom(64)
msg = b"112233"
hm = hmac.new(key,msg)
res = hm.hexdigest()
print(res , len(res))
View Code

 

 

服务端的合法性效验

客户端

""" 机器和机器之间的数据直接对接 """
import socket
import hmac

sk = socket.socket()
sk.connect( ("127.0.0.1" , 9000) )

def auth(secret_key):
    # 接受服务端发送过来的随机二进制字节流
    msg = sk.recv(32)
    
    # hmac.new(   key(字节流) ,  要加密的内容(字节流)  )
    hm = hmac.new( secret_key.encode() , msg  )
    
    # 返回的是具有固定32位长度的十六进制字符串
    cli_res = hm.hexdigest()
    
    # 把最后计算的结果发送给服务端进行校验
    sk.send(  cli_res.encode() )
    
    # 接受服务端给予的校验结果
    res = sk.recv(1024).decode()
    
    return res
    


# 处理收发数据的逻辑
secret_key = "不开,老妈没回来"
secret_key = "小兔儿乖乖,把门开开"
# 调用授权函数
res = auth(secret_key)

if res == "True":
    print("服务器校验通过")
else:
    print("服务器校验失败")

sk.close()
View Code

服务端

""" 机器和机器之间的数据直接对接 """
import socketserver
import hmac
import os

class MyServer(socketserver.BaseRequestHandler):

    secret_key = "小兔儿乖乖,把门开开"

    def auth(self):
        conn = self.request
        # 创建一个随机的32位字节流
        msg = os.urandom(32)
        
        # 把字节流发送给客户端
        conn.send(msg)
        
        # 服务端进行数据校验
        hm = hmac.new(  self.secret_key.encode() , msg  )
        ser_res = hm.hexdigest()
        
        # 服务端接受客户端发送过来的数据结果
        cli_res = conn.recv(1024).decode()
        
        # 进行比对,如果ok 返回True , 反之亦然
        return  True if ser_res == cli_res else False            

    def handle(self):
        if self.auth():
            self.request.send("True".encode())
        else:
            self.request.send("False".encode())

server = socketserver.ThreadingTCPServer( ("127.0.0.1" , 9000)  , MyServer  )
# 开启,让一个端口绑定多个程序;  模块.类.属性 = True
socketserver.TCPServer.allow_reuse_address = True
server.serve_forever()
View Code

 

 

TCP登陆

客户端

import socket 
import json
"""
pickle => 字节流( 存储数据 )
json   => 字符串( 数据交互 )
"""

sk = socket.socket()
sk.connect( ("127.0.0.1" , 9001) )

# 处理收发数据的逻辑
usr = input("请输入您的用户名:")
pwd = input("请输入您的密码:")
dic = {"username" : usr , "password":pwd , "operate" : "login"}

# 通过json变成字符串
res = json.dumps(dic)

# 转化成字节流发送给服务端
sk.send(res.encode())

# 接受服务端响应的数据
res_str = sk.recv(1024).decode()

# 字符串转化成字典
dic = json.loads(res_str)
print(dic , type(dic))
print(dic["msg"])


sk.close()
View Code

服务端

from collections import Iterator,Iterable
import socketserver
import hashlib
import json

class MyServer(socketserver.BaseRequestHandler):

    # 默认没有登录
    sign = False
    
    def get_md5_code(self,usr,pwd):
        hs = hashlib.md5(usr.encode())
        hs.update(pwd.encode())
        return hs.hexdigest()

    def auth(self):
        
        conn = self.request
        # 接受客户端发送过来的数据,通过decode反解成字符串
        res = conn.recv(1024).decode()
        # 通过json把字符串 转换成 字典
        dic = json.loads(res)
        # {'username': 'caijingguan', 'password': '8888', 'operate': 'login'} 
        print(dic , type(dic)) 
        with open("userinfo.data",mode="r",encoding="utf-8") as fp: # fp文件对象是迭代器,一行一行返回数据
            for i in fp:
                # 文件中解析出用户和密码
                usr,pwd = i.strip().split(":")
                if usr == dic["username"] and pwd == self.get_md5_code( dic["username"] , dic["password"] ) : 
                    # 自定义返回的字典数据
                    dic_msg = {"code":1,"msg":"登录成功"}
                    # 把字典 => 字符串
                    json_str = json.dumps(dic_msg)
                    # 把字符串 => 字节流 发送给客户端
                    conn.send( json_str.encode() )
                    # 把sign标记从False => True 代表登录成功
                    self.sign = True
                    break
                    
            # 没有找到对应合法的用户名和密码,登录失败
            if self.sign == False:
                dic_msg = {"code":0,"msg":"登录失败"}
                res = json.dumps(dic_msg).encode()
                conn.send(res)        
        
    def handle(self):
        self.auth()

server = socketserver.ThreadingTCPServer( ("127.0.0.1" , 9001) , MyServer )
# 开启,让一个端口绑定多个程序;  模块.类.属性 = True
socketserver.TCPServer.allow_reuse_address = True
server.serve_forever()
View Code

 

创建一个userinfo.data文件存储用户数据 密码用hshlib加密

userinfo.data

        wangwen:bbccc59bedc09e551a394699b44ed9f9
lisi:c79439cf9abcbd6c6d46e45766a9e64a
View Code

 

标签:hashlib,python,res,TCP,print,效验,hs,encode,md5
来源: https://www.cnblogs.com/shuaiyao666/p/16124591.html