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('输入错误')

posted @ 2023-03-20 19:50  星空看海  阅读(35)  评论(0编辑  收藏  举报