Day28 hashlib模块、合法性校验、tcp登录

1.hashlib模块

mad()/sha1()/sha512.../hmac()

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

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

##mad加密(相比而言hmac加密的算法不会被破解)

加密效率快 通过的加密精密 方法安全性稍差 位数是32位

# 基本用法
# (1)创建一个md5算法的对象
# (2)把想要加密的字符串通过update方法更新到hs这个对象当中去
# 参数是二进制字节流
# (3)返回的是32位16进制的字符串
# 加盐(加key 只有你自己知道的明文) 目的:增加密码的复杂度
# 加盐是在用md5后者是sha1()或者sha512()时候假如参数key
# 在hashlib.md5(key) # 动态加盐
hs = hashlib.md5()
hs.update("wangwenshuaige".encode("utf-8"))
res = hs.hexdigest()
print(res,len(res))
# a9d3c3ad36ff18b5bc7be96295df079b 32

# 加盐(加key 只有你自己知道的明文) 目的:增加密码的复杂度
hs = hashlib.md5("Xboyww_".encode("utf-8"))
hs.update("123".encode("utf-8"))
res = hs.hexdigest()
print(res)
# 1ea36fffc2174b753b4c47d3deeaca60
# 动态加盐
import random
res = str(random.randrange(10000,1000000))
hs = hashlib.md5(res.encode())
hs.update("aabbccdd".encode())
res = hs.hexdigest()
print(res)
# 485e1769395b018243d7ee16f2540219

## sha

加密效率慢,算法相对来说 安全性稍高

 # 1.创建一个对象

# 2. 对象.update(key) 写入的数据都是字节流的

# 比如:hs = hashlib.sha1()

  hs.update("xboyww_123".encode("utf-8"))

 

hs = hashlib.sha1()
hs.update("xboyww_123".encode("utf-8"))
res = hs.hexdigest()
# 返回的加密字符串长度是40位
print(res,len(res))
# 4f584b41e8cca8c45f4875ddbfa8113dffa36e31 40
# 加盐
hs = hashlib.sha1("PPUU".encode("utf-8"))
hs.update("xboyww_123".encode())
res = hs.hexdigest()
print(res)
# 744316f7f3c985b49c3b0412f5e8444ea861c4d1
# sha512

hs = hashlib.sha512()
hs.update("12345".encode())
res = hs.hexdigest()
# 返回的字符串长度是128位
print(res,len(res))
# 3627909a29c31381a071ec27f7c9ca97726182aed29a7ddd2e54353322cfb30abb9e3a6df2ac2c20fe23436311d678564d0c8d305930575f60e2d3d048184d79 128

 

# hmac

hmac里面的new方法相当于hashlib差古剑对象和update联合在一起的操作.

 

import hmac
import os
key = b"124"
msg = b"456"

hm = hmac.new(key,msg)
res = hm.hexdigest()
print(res,len(res))
# abd3b78f7a6c0a170381a7094c09c777 32
# 随机返回长度为32位的二进制字节流
key = os.urandom(32)
print(key)
# b'\xfe\xf2\xe3\xf7\xb7\xcc@\x8dLx\xf42\x85\xbd\x99Z\xfa\xe0\x9f\x0c\xe0\xa2\x9bT\xb2h\xd8\x1b\xeb\x98J\x15'
hm = hmac.new(key,msg)
res = hm.hexdigest()
print(res,len(res))
# 5c7e1d2e4d48bd14149a8afe5f4904fc 32

 

2.合法性校验

1.小文件的校验

 (1)针对小文件的内容校验
import hashlib
def check_md5(file):
    with open(file,mode="rb") as fp:
        hs = hashlib.md5()
        hs.update(fp.read())
    return hs.hexdigest()
        
print(check_md5("ceshi1.txt"))
print(check_md5("ceshi2.txt"))
# 62c629da1d7f164bb85e2d741b77610e
# b949a12fb038471495f0cdb8db640562


# 可以连续的对内容就行校验
hs = hashlib.md5()
hs.update("昨天晚上\n下雨了".encode())
res = hs.hexdigest()
print(res)
# 894c4dd4b1f57472322db524e7b6a47f
# 可以连续update到hs独享就行字节流的拼接
hs = hashlib.md5()
hs.update("昨天晚上\n".encode())
hs.update("下雨了".encode())
res = hs.hexdigest()
print(res)
# 894c4dd4b1f57472322db524e7b6a47f
 
 

 

2.大文件的校验

# 方法一
def check_md5(file):
    hs = hashlib.md5()
    with open(file,mode="rb") as fp:
        while True:
            content = fp.read(1)
            if content:
                hs.update(content)
            else:
                break
        return hs.hexdigest()

print("<=======>")
print(check_md5("ceshi1.txt"))
print(check_md5("ceshi2.txt"))

# 62c629da1d7f164bb85e2d741b77610e
# b949a12fb038471495f0cdb8db640562
# 方法二
import
os def check_md5(file): hs = hashlib.md5() file_size = os.path.getsize(file) with open(file,mode="rb") as fp: while file_size: # read(1) content = fp.read(1) hs.update(content) file_size -= len(content) return hs.hexdigest() print(check_md5("ceshi1.txt")) print(check_md5("ceshi2.txt")) # 62c629da1d7f164bb85e2d741b77610e # b949a12fb038471495f0cdb8db640562
# 利用创建出来的对象可以持续的update()即是你需要校验的内容,如果需要加(加盐)key(明文)就在创造对象的时候加入。
hs = hashlib.md5("Xboyww_".encode("utf-8"))
小结:方法1是利用一个死循环,每次在里面就行读取一个字节,如果读到有数据的话就就行update()把要校验的内容加进去。直到fp.read(1)读不到数据的时候就行退出,最后返回一个hs.hexdigest()
方法二是利用判断文件大小作为循环的条件,一样的就行每次读取一个字节,利用update()方法就行更新hs对象,直到文件对象file_size的长度为0的时候,说明要校验的内容已经全部写入hs对象中去了。
最后直接返回hs.hexdigest()

3.tcp登录

1.客户端访问服务器时,在服务器端加入一段数据的验证,如果验证通过就可以正常的访问服务器,如果验证不通过不可以访问。

1.除了客户端和服务器端之间约定的一些代码之外,服务器器端还(在验证数据的时候加盐了,加入的数据是随机产生的32位的字节流数据)

例:

客服端发送给服务器的验证数据:

 b"wangwendashuaige"

服务器需要的验证数据:(双方约定好,如果你来访问服务器就必须是这个词,再者考虑到安全的因素,服务器随机增加了一个32位字节的数据并发送给客户端,要求客户端把这个数据和key(盐一起打包发过去))

 # 客户端代码

import socket
import hmac

def auth(sk,key):
    # 接受服务器发过来的随机二进制字节流
    msg = sk.recv(32)
    # print(msg)
    hm = hmac.new(key,msg)
    res = hm.hexdigest()
    # 把加密后的字符串发送给服务器
    sk.send(res.encode())

sk = socket.socket()

key = b"wangwendashuaige"
sk.connect( ("127.0.0.1",9000) )
auth(sk,key)
sk.send(b"download")
sk.close()

 

# 服务器代码

# server 服务端 添加访问的权限验证
import socket
import hmac
import os
def auth(conn,secret_key):
    # 随机获取二进制的字节流
    msg = os.urandom(32)
    # print(msg)
    conn.send(msg)
    hm = hmac.new(secret_key,msg)
    res_serve = hm.hexdigest()
    # 接受客户端发给我的字符串
    res_client = conn.recv(1024).decode("utf-8")
    if res_serve == res_client:
        print("合法的链接")
        return True
    else:
        print("不合法的链接")
        return False

sk = socket.socket()
sk.bind( ("127.0.0.1",9000) )
sk.listen()

conn,addr = sk.accept()
secret_key = b"wangwendashuaige"

if auth(conn,secret_key):
    # 如果返回真,可以接受客户发来的各种请求
    print(conn.recv(1024).decode("utf-8"))



# 收发数据逻辑.
# ...

# 四次挥手
conn.close()
# 退还端口
sk.close()
运行代码:True
Flase:服务端的代码:不合法的链接
小结:1.本例子当中客户端第一次发送的是通过hmac("双方规定的键值","接收到服务器发送的数据当做即将发送的数据")
     2.然后客户端将要发送到服务器就行验证的数据就行hmac发送过去
     3.服务器端就行判断,如果是正确的.../如果是错误的....
   4,本例子客户端只是利用send发送了2次数据,没有接受数据,故客户端没有代码。

 

2.带有输入用户名和密码的,访问服务器(已经存好了可以访问的内容),程序过程是:

1.通过将输入的用户名还有密码通过json转换为字符串再

2.通过encode变成二进制字节流,然后使用hashlib就行加密发送

3.到了服务器端,就行decode()得到当初定义的字典,这个时候需要访问服务器端的数据库的数据就行文件的比对:

       但是本例子中服务器去拿数据的时候,不是拿的数据库的数据而是自己创建的数据,直接通过打开文件数据就行获取就行,但是注意数据的格式,以及收到的数据不要搞混淆了。

      服务器中的数据类型是通过hashlib加密过的(本例中的是:# zhangsan:e7a6d0f97db7ea1c4a0c1c137cbf771c;也就是密码是经过hashlib的)。接收到客户端的数据是字节流,

  如果是正确的:返回一个字典{“code”:1} 并把标记状态的sign = True(最初定义的是False,定义这个状态方便我们就行在客户端就行接受一个数据,从而反应出访问的结果)

4.通过一变量的增加(sign=0,成功之后是sign=1,不做处理如果是sign=0后面继续写逻辑),并发送回客户端,让客户端知道反应结果。

服务器数据库中存放的数据是:

服务器代##服务器登录import socket

import json
import hashlib

def get_md5_code(usr,pwd):
    hs = hashlib.md5(usr.encode())
    hs.update(pwd.encode())
    return hs.hexdigest()

sk = socket.socket()
sk.bind(("127.0.0.1",9001))
sk.listen()

conn,addr = sk.accept()
#把接受到客户端的字节流变成字符串
msg = conn.recv(1024).decode()
# 反序化字典
dic = json.loads(msg)
# 默认编辑用户不存在
sign = False
# 提取服务器中的数据 with open(
"userinfo.txt",mode="r",encoding="utf-8") as fp: for line in fp:
usr,pwd
= line.strip().split(":") if usr == dic['username'] and pwd == get_md5_code(dic['username'],dic['password']): res = {"code":1} res_msg = json.dumps(res).encode() conn.send(res_msg) # 该用户找到了,存在 sign = True break if sign == False: res = {"code":0} res_msg = json.dumps(res).encode() conn.send(res_msg) conn.close() sk.close()

 

客户端代码:

### 客户端
import socket
import json

## 张三 111
# 李四 222
# 王五 333
# 赵六 444
sk = socket.socket()
sk.connect(("127.0.0.1", 9001))
# 收发数据逻辑
usr = input("请输入用户名:")
pwd = input("请输入您的密码:")
dic = {"username": usr, "password": pwd, "operation":"login"}

# 把字典序列化成字符串
json_dic = json.dumps(dic)
# 把字符串变成字节流
bytes_msg = json_dic.encode("utf-8")
sk.send(bytes_msg)

# 接受服务器的返回值
res_msg = sk.recv(1024).decode()
# 反序列化成字典
dic_code = json.loads(res_msg)
if dic_code['code']:
    print("恭喜你,登录成功!")

else:
    print("抱歉,登录失败!")

sk.close

 

 

转载于:https://www.cnblogs.com/longerandergou/p/10969125.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值