【python】:使用称密钥加密算法AES、cpython实现工程文件加密

news/2024/5/10 11:49:58

AES工程文件加密

  • 1.AES加密和解密的详细案例
    • 1.1. 导入必要的库:
    • 1.2. 定义加密和解密类:
    • 1.3. 测试加密和解密:
  • 2.对单个.py文件加密
  • 使用方式:encrypt_file('mypassword', 'mytest.py')
  • 3.使用cpthon实现对文件加密
  • 参考链接:

1.AES加密和解密的详细案例

以下是使用Python实现AES加密和解密的详细案例。

1.1. 导入必要的库:

import base64
import hashlib
import os
from Crypto import Random
from Crypto.Cipher import AES

1.2. 定义加密和解密类:

class AESCipher:def __init__(self, key):self.key = hashlib.sha256(key.encode()).digest()def encrypt(self, raw):raw = self._pad(raw)iv = Random.new().read(AES.block_size)cipher = AES.new(self.key, AES.MODE_CBC, iv)return base64.b64encode(iv + cipher.encrypt(raw)).decode('utf-8')def decrypt(self, enc):enc = base64.b64decode(enc)iv = enc[:AES.block_size]cipher = AES.new(self.key, AES.MODE_CBC, iv)return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')def _pad(self, s):return s + (AES.block_size - len(s) % AES.block_size) * chr(AES.block_size - len(s) % AES.block_size)@staticmethoddef _unpad(s):return s[:-ord(s[len(s)-1:])]

1.3. 测试加密和解密:

key = os.urandom(32)  # 生成一个随机的32 bytes的key
cipher = AESCipher(key)plaintext = 'hello world'
encrypted = cipher.encrypt(plaintext)
decrypted = cipher.decrypt(encrypted)print('plaintext: ', plaintext)
print('encrypted: ', encrypted)
print('decrypted: ', decrypted)

输出:

plaintext:  hello world
encrypted:  PAEte9EbH5Ciz3n5xZp6uTqwEqLr6aWM9oE4iUpvcAI=
decrypted:  hello world

加密和解密都正常工作。现在让我们分解定义的类和方法的工作原理。

首先,初始化类时需要提供一个加密使用的key,该key将由密码字符串使用SHA-256哈希生成:

def __init__(self, key):self.key = hashlib.sha256(key.encode()).digest()

接下来定义了加密方法。它使用python的Crypto库中的随机模块生成一个随机向量(iv),这个向量将与密文一起存储。

然后,选择使用CBC模式的AES加密器。在此模式下,每个块都与前一个块一起加密,这使得更难对密文进行访问。

最后,函数使用base64编码对密文进行编码。编码总是必要的,因为原始Bytes加密文本通常只包含ASCII字符,这会导致一些问题(例如,当其用于网络传输或需要在不同计算机上阅读时)。

def encrypt(self, raw):raw = self._pad(raw)iv = Random.new().read(AES.block_size)cipher = AES.new(self.key, AES.MODE_CBC, iv)return base64.b64encode(iv + cipher.encrypt(raw)).decode('utf-8')

解密功能符合加密函数。它首先对BASE-64编码的 (已加密的)密文进行解码,然后使用相同的IV和密钥重新初始化AES加密器。

解密器执行相反的操作。它除去IV,并尝试从中解密每个块。最后,它还会删除填充。

def decrypt(self, enc):enc = base64.b64decode(enc)iv = enc[:AES.block_size]cipher = AES.new(self.key, AES.MODE_CBC, iv)return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')

关于填充和去除填充,这两个功能都值得解释:

def _pad(self, s):return s + (AES.block_size - len(s) % AES.block_size) * chr(AES.block_size - len(s) % AES.block_size)@staticmethod
def _unpad(s):return s[:-ord(s[len(s)-1:])]

这里采用PKCS #7填充模式,是一种常用的填充方案。需要填充的话,就添加ASCII的值相对应的字符直到填充完。
想要解密,就要先获取最后的字符编码值,再通过该值来确定需要移除多少个字符,最后移除这些字符即可。

2.对单个.py文件加密

实现步骤如下:

  1. 安装 PyCryptodome 模块,该模块支持 AES 加密算法的实现。可以使用以下命令进行安装:

    pip install pycryptodome

  2. 编写 py 文件加密脚本,将需要加密的 py 文件进行加密操作。例如:

from Crypto.Cipher import AES
import os# 加密算法,key 为 16、24 或 32 个字符的字符串def encrypt_file(key, in_filename, out_filename=None, chunksize=64 * 1024):if not out_filename:out_filename = in_filename + '.enc'iv = os.urandom(AES.block_size)  # 随机生成密钥encryptor = AES.new(key, AES.MODE_CBC, iv)filesize = os.path.getsize(in_filename)with open(in_filename, 'rb') as infile:with open(out_filename, 'wb') as outfile:outfile.write(filesize.to_bytes(8, 'big'))  # 写入文件大小outfile.write(iv)  # 写入密钥向量while True:chunk = infile.read(chunksize)if len(chunk) == 0:breakelif len(chunk) % AES.block_size != 0:chunk += b' ' * (AES.block_size - len(chunk) % AES.block_size)outfile.write(encryptor.encrypt(chunk))

使用方式:encrypt_file(‘mypassword’, ‘mytest.py’)

  1. 加密完成后,可以将原始的 py 文件删除,只保留加密后的文件。同时,可以将加密后的文件改名为 .pyc 的后缀,使得 Python 解释器认为该文件是编译后的字节码文件,从而可以正常运行。例如:

    # 将加密后的 mytest.py.enc 文件重命名为 mytest.pyc
    os.rename('mytest.py.enc', 'mytest.pyc')
    
  2. 在命令窗口中,可以使用以下命令运行加密后的 .pyc 文件:

    python mytest.pyc

    注意:必须在加密时将原始文件名存储在加密后的文件中,以便在解密时获取文件名称。另外,解密操作需要使用与加密时相同的密码。可以使用以下解密方法:

    from Crypto.Cipher import AES
    import os# 解密算法,key 为 16、24 或 32 个字符的字符串
    def decrypt_file(key, in_filename, out_filename=None, chunksize=64 * 1024):if not out_filename:out_filename = os.path.splitext(in_filename)[0]with open(in_filename, 'rb') as infile:orig_size = int.from_bytes(infile.read(8), 'big')iv = infile.read(AES.block_size)decryptor = AES.new(key, AES.MODE_CBC, iv)with open(out_filename, 'wb') as outfile:while True:chunk = infile.read(chunksize)if len(chunk) == 0:breakoutfile.write(decryptor.decrypt(chunk))outfile.truncate(orig_size)# 使用方式:decrypt_file('mypassword', 'mytest.pyc.enc')
    

    解密后,将得到原始的 py 文件(如果加密前的文件名为 mytest.py,则解密后的文件名为 mytest.py)。

如果以上步骤不是很容易理解,可以考虑使用第三方加密工具,如 pyarmor 或 cython 等,这些工具可以使用更高级的加密方式,同时提供更方便的使用接口。例如,使用 pyarmor 可以直接使用以下命令对 mytest.py 文件进行加密:

pyarmor obfuscate mytest.py

加密后的文件位于 dist 目录下,可以通过以下命令运行:

python dist/mytest.py

注意:如果使用这些工具加密,需要提前了解其授权模式和使用方式。

3.使用cpthon实现对文件加密

参考我的另一篇连接:

参考链接:

传送门1:
传送门2:


http://wed.xjx100/news/198280.html

相关文章

WoW 游戏软件

访问【WRITE-BUG数字空间】_[内附完整源码和文档] 我们选择Tcp协议进行传输,之所以采用tcp,首先是因为tcp传输稳定,相比于udp不稳定的传输,tcp能确保消息一定传输出去。然后是tcp有服务器,相比于 p2p 无服务器模型,tc…

蓝牙RSSI/BLE AOA/UWB室内定位技术哪个好?

蓝牙AOA定位技术的出现,弥补了蓝牙RSSI值定位精度不高的缺陷。从理论上来说,可以对目前的蓝牙RSSI定位方案进行一定程度的替代。当然了,在高精度定位应用领域中,UWB定位已经在批量的成熟商用了。蓝牙AOA也具有很高的定位精度&…

hibernate入门项目(一)

本节我们将演示如何搭建一个 Hibernate 工程。 搭建 Hibernate 工程需要以下 7 步: 下载 Hibernate 开发包 新建工程 创建数据库表 创建实体类 创建映射文件 创建 Hibernate 核心配置文件 测试 1. 下载 Hibernate 开发包 浏览器访问 Hibernate 官网 下载 Hibern…

面试官:前端如果 100 个请求,你怎么用 Promise 去控制并发?

摘要: 时隔两年半,我,一个卑微的前端菜鸡,又来写面经了!以为钱是程序员年轻奋斗的动力!作为一个程序员,在一个地方慢慢成长后会产生一个能力小提升的一种傲娇!希望你们一跳涨好几丈。…

HTB靶机013-Poison-WP

013-Poison 靶机IP: 10.10.10.84 Scan Nmap 快速扫描: ┌──(xavier㉿kali)-[~] └─$ sudo nmap -sSV -T4 10.10.10.84 -F Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-30 16:41 CST Nmap scan report for 10.10.10.84 Host is up (0.27s…

数据库中的几项区别

mysql中in和exists区别 mysql中的in语句是把外表和内表作hash 连接,而exists语句是对外表作loop 循环,每次loop循环再对内表进行查询。一直大家都认为exists比in语句的效率要高,这种说法其实是不 准确的。这个是要区分环境的。 1. 如…

Netty核心组件模块(一)

1.Bootstrap和ServerBootstrap 1>.Bootstrap意思是引导,一个Netty应用通常由一个Bootstrap开始,主要作用是配置整个Netty程序,串联各个组件,Netty中Bootstrap类是客户端程序的启动引导类,ServerBootstrap是服务端启动引导类; 2>.常见的方法有: ①.public ServerBootstr…

动态规划——带权活动选择

带权活动选择Time Limit: 3000 MSMemory Limit: 1000 KB Description 给定n个活动&#xff0c;活动ai表示为一个三元组(si,fi,vi)&#xff0c;其中si表示活动开始时间&#xff0c;fi表示活动的结束时间&#xff0c;vi表示活动的权重, si<fi。带权活动选择问题是选择一些活…