Python Crypto模块介绍与基本使用方式

下载方式

下载方式 pip命令行安装: pip install pycryptodome
注意不要打错了,还有几个名字相似的模块

这里有三个可能会混淆的库
crypto:https://pypi.org/project/crypto/
pycrypto:https://pypi.org/project/pycrypto/
pycryptodome:https://pypi.org/project/pycryptodome/

下面来介绍一下为什么要安装的是pycryptodome这个模块
pycryptodome是pycrypto的一个分支,它相对于pycrypto最新版带来了一些增强的功能,具体哪些功能可以访问上面pycryptodome这个网站
而crypto是个完全不同的模块,它主要用于命令行操作,而不是py文件中import后使用

常用加密介绍

加密算法主要分为对称加密、非对称加密、信息摘要函数三种

  • 对称加密有AES、DES等
  • 非对称加密有RSA等
  • 信息摘要函数有MD5、sha-1、sha-256等

这些算法都可以用pycryptodome这个模块搞定,下面我们简单介绍一下各个加密并给出简单示例

对称加密

对称加密又可细分为两类

  • 分组加密(或 块加密):以 块 为单位进行一次加密,将明文按一定的位长分组成块,明文块加密后得到密文组。解密雷同,密文组解密还原成明文组。
  • 序列加密(或 流加密):以 位 为单位进行一次加密,利用少量的密钥通过某种复杂的密码算法进行运算产生大量的伪随机位流,用于对明文位流的加密

常见的分组加密有AES、DES等,分组加密需要选定一种分组的模式,常见的分组模式有:ECB、CBC、PCBC、CFB、OFB、CTR
具体每种分组模式的介绍请参考:https://blog.csdn.net/weixin_42272869/article/details/124278342

以AES算法、ECB分组模式为例

AES

关于AES加密算法的介绍,请参考 https://www.cnblogs.com/block2016/p/5596676.html
AES要求128bit或192bit或256bit的密钥,下面统一用128bit的密钥

文件目录

AES/
├── flag.txt
├── c.txt
├── m.txt
├── encrypt.py
└── decrypt.py

flag.txt 中存放需要加密的信息flag
c.txt 中存放经过encrypt.py加密后flag的密文
m.txt 中存放经过decrypt.py解密后flag的明文

以下是encrypt.py的内容

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad,unpad
from Crypto.Hash.SHA256 import SHA256Hash

with open("./flag.txt","rb") as f:
    m = f.read()

key = 'Eternal-sorrow'
key = SHA256Hash(key.encode()).digest()[:16] # 这里以sha256('Eternal-sorrow')前16byte,共128bit作为密钥
# 只要key的长度为128bit(16byte),192bit(24byte),256(32byte)都可以作为密钥
# 这里只是借助了sha256这个信息摘要函数生成了32byte的信息,取前16byte作为密钥

# 生成一个aes加解密方式,包含key与分组方式,这里用的是ECB分组方式
aes = AES.new(key,AES.MODE_ECB)

# aes是分组加密算法,需要将明文划分为16字节的小块,不足的补全到16字节
c = aes.encrypt(pad(m,16))

# 写入c.txt
with open("./c.txt","wb") as f:
    f.write(c)

以下是decrypt.py的内容

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad,unpad
from Crypto.Hash.SHA256 import SHA256Hash

with open("./c.txt","rb") as f:
    c = f.read()

key = 'Eternal-sorrow'
key = SHA256Hash(key.encode()).digest()[:16] # 以sha256('Eternal-sorrow')前16byte,共128bit作为密钥
# 只要key的长度为128bit(16byte),192bit(24byte),256(32byte)都可以作为密钥
# 这里只是借助了sha256这个信息摘要函数生成了32byte的信息,取前16byte作为密钥

# 生成一个aes加解密方式,包含key与分组方式,这里用的是ECB分组方式
aes = AES.new(key,AES.MODE_ECB)

# 16字节一组,解分组得到明文
m = unpad(aes.decrypt(c),16)

# 写入m.txt
with open("./m.txt","wb") as f:
    f.write(m)

非对称加密

非对称加密以RSA为例
实际上不需要这个模块也能使用RSA,不过这个模块可以从公钥、私钥文件中提取出数字,之后可以使用该模块继续进行加解密,也可以自行根据RSA原理进行加解密
RSA能够加密的长度取决于生成的密钥长度,并且加解密速度不如对称加密,所以非对称加密通常用于传递对称加密的密钥,后续使用对称加密通信

RSA

文件目录

RSA/
├── flag.txt
├── c.txt
├── m.txt
├── encrypt.py
├── decrypt.py
├── keygen.py
├── id_rsa
└── id_rsa.pub

flag.txt 中存放需要加密的信息flag
c.txt 中存放经过encrypt.py加密后flag的密文
m.txt 中存放经过decrypt.py解密后flag的明文
keygen.py 用于生成RSA公钥和私钥
id_rsa.rsa 存放RSA私钥
id_rsa.pub 存放RSA公钥

keygen.py文件

from Crypto.PublicKey import RSA

# 使用这个命令生成一个1024bit的RSA密钥,返回一个含有e,n,d,p,q,dp,dq,invp,invq,u这些变量的RsaKey类
rsa = RSA.generate(1024)

# 生成的密钥默认为私钥
with open("./id_rsa", "wb") as f:
    f.write(rsa.export_key())

# 可以使用public_key方法获取公钥
with open("./id_rsa.pub", "wb") as f:
    f.write(rsa.public_key().export_key())

encrypt.py文件

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

# 从生成的公钥文件中读取公钥
with open("./id_rsa.pub", "rb") as f:
    data = f.read()

# 解析公钥
pubkey = RSA.import_key(data)
print(pubkey.can_encrypt())  # True
print(pubkey.has_private())  # False

# 读取flag
with open("./flag.txt", "rb") as f:
    flag = f.read()

key = PKCS1_OAEP.new(pubkey)
c = key.encrypt(flag)

# 写入c.txt
with open("./c.txt", "wb") as f:
    f.write(c)

decrypt.py文件

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

# 从生成的私钥文件中读取私钥
with open("./id_rsa", "rb") as f:
    data = f.read()

# 解析私钥
prikey = RSA.import_key(data)
print(prikey.can_encrypt())  # True
print(prikey.has_private())  # True

# 读取密文
with open("./c.txt", "rb") as f:
    c = f.read()

key = PKCS1_OAEP.new(prikey)
m = key.decrypt(c)

# 写入m.txt
with open("./m.txt", "wb") as f:
    f.write(m)
posted @ 2024-04-06 17:04  zzkkk1h  阅读(5618)  评论(0)    收藏  举报