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

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)

    @staticmethod
    def _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:
                    break
                elif 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:
                        break
                    outfile.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:
如何给Python代码进行加密(脚本之家)
python的py文件(源码)进行加密为so文件(linux)

猜你喜欢

转载自blog.csdn.net/weixin_44322778/article/details/130746508