subprocess模块、hashlib模块
subprocess模块
用python代码实行远程命令可以使用subprocess模块
作用:使用我们自己的电脑去链接别人的电脑 (socket模块)
import subprocess
res = subprocess.Popen(
'tasklist', # 操作系统要执行的命令
shell=True, # 固定配置
stdout=subprocess.PIPE, # 输入命令
stderr=subprocess.PIPE # 输出结果
)
使用1:
print(res)
# <subprocess.Popen object at 0x000001ABB1970310>
print(res.stdout.read().decode('gbk')) # tasklist执行之后的正确结果返回
使用2:
第一个参数写入'tasklistaaa'
print(res.stderr.read().decode('gbk')) # 命令错误会返回
# 输出结果是:'tasklistaaa' 不是内部或外部命令,也不是可运行的程序或批处理文件。
拓展
1.tasklist命令(linex中的知识),是打印电脑正在运行的程序,PID进程号(后续讲解)
2.不知道别人的文件使用什么编码,可以试试,(utf-8,gbk)
3.windows系统默认的编码格式是:gbk
hashlib模块
算法介绍
Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。
什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。
摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。
加密方式
加密方式有3种,对称加密算法,非对称加密算法和 摘要算法
摘要算法:用户通过摘要算法对于目标信息生成一段特定长度的值。常见的摘要算法有:md5、sha系列(sha1、sha2、sha224、sha256)。jwt的签名就是使用的摘要算法,这样就可以生成一个固定长度的值。
对称加密:使用的密钥只有一个,发送和接收双方都使用这个秘钥进行加密和解密。
非对称加密:它需要两个密钥,一个称为公开密钥 (public key),即公钥,另一个称为私有密钥 (private key),即私钥。
加密的概念
1.何为加密
将明文数据处理成密文数据 让人无法看懂
2.如何判断数据是否是加密的
一串没有规律的字符串(数字、字母、符号)
3.密文的长短有何讲究
被加密的数据,密文结果越长代表越难被破解,内部的加密算法越复杂,数据也更安全。但是缺点:被加密出来的结果越长,在发送数据的时候就会占用更多的资源
4.常见的加密算法有哪些
md5、base64、hmac、sha系列
5. 如何选择加密方式
根据自己项目实际需求选择,一般情况下,md5足够了
6.为什么加密
保证数据的安全
7.使用场景:
以后我们做的项目,用户的密码都是密文保存。
7.1 内部人员(程序员)也看不到明文密码
7.2 数据被泄露,也能保证数据的安全
我们以常见的摘要算法MD5为例,计算出一个字符串的MD5值:
import hashlib
# 1. 先确定你要使用的加密方式: md系列,sha系列
md5 = hashlib.md5() # 指定加密方式
# 2. 传入明文数据
data = '123456789'
md5.update(data.encode('utf-8')) # 括号里面加密数据必须是字节类型,bytes类型
# 3. 取出加密结果
print(md5.hexdigest())
# e10adc3949ba59abbe56e057f20f883e
"""
1. 一种格式,被加密的明文数据不管多长,得到的加密串的长度都是固定的
2. 针对md5数据,密文数据能不能倒推出明文数据?
记忆:不能倒推出明文数据
"""
md5解密网址:https://www.cmd5.com/
分开加密
如果数据量很大,可以分块多次调用update(),最后计算的结果是一样的:
练习1:
md5 = hashlib.md5()
data = 'hello123456' # 一次性传可以
md5.update(data.encode('utf-8'))
print(md5.hexdigest())
# d41d8cd98f00b204e9800998ecf8427e
md5 = hashlib.md5()
md5.update(b'hello') # 可以分开加密
md5.update(b'123456')
print(md5.hexdigest())
# d41d8cd98f00b204e9800998ecf8427e
练习2:
md5 = hashlib.md5()
data = b'helloworld'
print(md5.hexdigest())
# fc5e038d38a57032085441e7fe7010b0
md5 = hashlib.md5()
md5.update(b'hello')
md5.update(b'w')
md5.update(b'o')
md5.update(b'r')
md5.update(b'l')
md5.update(b'd')
print(md5.hexdigest())
# fc5e038d38a57032085441e7fe7010b0
常见加密方式
MD5是最常见的摘要算法,速度很快,生成结果是固定的128 bit字节,通常用一个32位的16进制字符串表示。另一种常见的摘要算法是SHA1,调用SHA1和调用MD5完全类似:
md5 = hashlib.md5()
data = '123456'
md5.update(data.encode('utf-8'))
print(md5.hexdigest())
# e10adc3949ba59abbe56e057f20f883e
sha1 = hashlib.sha1()
sha1.update(b'123456')
print(sha1.hexdigest())
# 7c4a8d09ca3762af61e59520943dc26494f8941b
b = hashlib.sha224()
b.update(b'123456')
print(b.hexdigest())
# f8cdb04495ded47615258f9dc6a3f4707fd2405434fefc3cbf4ef4e6
bb = hashlib.sha256()
bb.update(b'123456')
print(bb.hexdigest())
# 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
SHA1的结果是160 bit字节,通常用一个40位的16进制字符串表示。比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法越慢,而且摘要长度更长。
加盐处理
固定加盐(干扰项)处理
# 固定加盐(干扰项)处理
md5 = hashlib.md5()
# 内部在给他添加一个干扰项
random_str = 'hello'
data = '123456'
result = random_str + data
md5.update(result.encode('utf-8'))
print(md5.hexdigest())
# eeb9bad681184779aa6570e402d6ef6c
动态加盐(干扰项)处理
动态加盐
特征: 干扰项是随机变化的 eg:当前时间、用户名部分...
加密实战操作:
1.用户密码加密; 2.文件安全性校验; 3.文件内容一致性校验; 4.大文件内容加密
截取部分内容加密即可
md5 = hashlib.md5()
# 内部添加一个动态干扰项
import s # s模块中定义一个随机码函数get_code(n)
random_str = s.get_code(6)
data = '123456'
result = random_str + data
md5.update(result.encode('utf-8'))
print(md5.hexdigest())
# b71fbcf651a9e894e59dd98572ae4687
实战案例
案例(BBS项目,ATM项目)涉及用户密码,,注册与登录
1.把密码加密
import hashlib
################################1.把密码加密
# 注册
username = input('username:')
password = input('password:')
# 明文密码改成密文密码
md5 = hashlib.md5()
md5.update(password.encode('utf-8'))
new_pwd = md5.hexdigest() # 加密之后的结果
res = '%s|%s' % (username, new_pwd)
with open(r'a.txt', 'w', encoding='utf-8') as f:
f.write(res) # kevin|e10adc3949ba59abbe56e057f20f883e
# 登录
username = input('username:')
password = input('password:') # 123456
# 判断用户名和密码是否正确
# 1. 先取出原来的用户名和密码
with open(r'a.txt', 'r', encoding='utf-8') as f:
real_name, real_pwd = f.read().split('|')
# e10adc3949ba59abbe56e057f20f883e
# 2.把用户输入的密码再次加密与文件中得密码进行对比,是否一样
md5 = hashlib.md5()
md5.update(password.encode('utf-8'))
new_pwd = md5.hexdigest()
# 3. 用户新输入的用户名和密码进行比较
if username == real_name and new_pwd == real_pwd:
print('输入正确')
else:
print('输入错误')
2.加盐处理
################################2.加盐处理
# 注册
username = input('username:')
password = input('password:')
# 明文密码改成密文密码
md5 = hashlib.md5()
random_str = 'hello'
new_str = random_str + password # 得到被加盐之后的新字符串
md5.update(new_str.encode('utf-8'))
new_pwd = md5.hexdigest() # 加密之后的结果
res = '%s|%s' % (username, new_pwd)
with open(r'a.txt', 'w', encoding='utf-8') as f:
f.write(res) # jack|eeb9bad681184779aa6570e402d6ef6c
# 登录
username = input('username:')
password = input('password:') # 123456
# 判断用户名和密码是否正确
# 1. 先取出原来的用户名和密码
with open(r'a.txt', 'r', encoding='utf-8') as f:
real_name, real_pwd = f.read().split('|')
# eeb9bad681184779aa6570e402d6ef6c
# 2.把用户输入的密码再次加密与文件中得密码进行对比,是否一样
md5 = hashlib.md5()
new_str = 'hello' + password
md5.update(new_str.encode('utf-8'))
new_pwd = md5.hexdigest()
# 3. 用户新输入的用户名和密码进行比较
if username == real_name and new_pwd == real_pwd:
print('输入正确')
else:
print('输入错误')
3.动态加盐
# 注册
username = input('username:')
password = input('password:')
import s
# 明文密码改成密文密码
md5 = hashlib.md5()
random_str = s.get_code(6)
new_str = random_str + password # 得到被加盐之后的新字符串
md5.update(new_str.encode('utf-8'))
new_password = md5.hexdigest() # 加密之后的结果
# 把产生的随机字符串也保存在文件中
res = '%s|%s|%s' % (username, new_password, random_str)
with open('a.txt', 'w', encoding='utf-8') as f:
f.write(res) # tom|5ef5592d8daeeeb4601a5ba4422f9c5c|QWGMb0
# 登录
username = input('username:')
password = input('password:') # 123456
# 判断用户名和密码是否正确
# 1. 先取出原来的用户名和密码
with open('a.txt', 'r', encoding='utf-8') as f:
# 该用户的随机字符也分取出
real_username, real_password, random_s = f.read().split('|')
# real_password = 5ef5592d8daeeeb4601a5ba4422f9c5c
# 把用户输入的密码再次加密与文件中得密码进行对比,是否一样
md5 = hashlib.md5()
new_str = random_s + password
md5.update(new_str.encode('utf-8'))
new_pwd = md5.hexdigest()
# 2. 用户新输入的用户名和密码进行比较
if username == real_username and new_pwd == real_password:
print('输入正确')
else:
print('输入错误')