我在我的应用程序中使用 pycryptodome 进行加密。 该应用程序的一部分要求我打开一个文件,加密文件中的数据,并加密文件的名称。我使用了 AES 模式 cbc(因为这是我处理文件时的首选方法),并且文件加密类效果很好:
class Cipher:
def __init__(self, password: str, key: bytes = None):
self.key = PBKDF2(password, key if key else password_as_key(password), dkLen=32)
self.cipher = AES.new(self.key, AES.MODE_CBC, iv=get_random_bytes(16))
def encrypt(self, data: bytes) -> bytes:
return self.cipher.encrypt(pad(data, AES.block_size)) + self.cipher.iv
# decryption is the same as encryption, but it's necessary to remove the IV before
def decrypt(self, data: bytes) -> bytes:
encrypted_data = data[:-16]
iv = data[-16:]
self.cipher = AES.new(self.key, AES.MODE_CBC, iv=iv)
return unpad(self.cipher.decrypt(encrypted_data), AES.block_size)
我也想使用这种加密进行名称加密,但有一个问题。加密文件名时,我需要将文件保存在文件系统上,所以我不能只将名称保存为一堆字节。但是,简单地解码文本是不可能的,因为 AES 会进行大量字节移位,因此我无法确保文件保持任何编码,无论是 utf-8、utf-16 甚至是 base64 (我都试过了,但都失败了)。所以我想知道,在这种情况下有什么方法可以将字符串加密为字符串吗?
顺便说一句,我知道我在标题中说过我想使用 AES 模式 cbc 进行加密,这仍然是事实。但如果没有其他方法来解决这个问题,那么我可以使用其他加密方法,只要它们像 AES 加密一样安全和快速。
我可以看到不少于三个选项:
FPS 或格式保留加密:这可能是最适合您的要求的选项。它将使用任何字母表将文本加密为具有相同字母表和大小的内容。问题是这是一项相当困难的任务,而且 FF1 和 FF2 等 FPS 的实现并不常见。
CBC + 基数转换:可以使用任何方案(例如 CBC)进行加密,然后对字母表中的索引执行基数转换,该字母表仅包含对文件名有效的字符 - 可能除了点之外。这将扩展文件名,因为 CBC 有开销,并且密文使用一个字节的所有可能值。当用于较大的密文时,基数转换可能会很棘手;如果实施不当,会占用大量 CPU。
将其存储为元信息:可能最简单的选择是将文件名存储为密文的一部分,然后使用序列号或类似信息(例如
encrypted_file_001.bin
)。如果这样做,您只需区分文件名和内容即可。如果您不想自己执行此操作,您可以将文件放入存档中并对其进行加密。
此时,您可能必须先进行选择,然后才能进行任何实施。由于第一个确实需要大量理解,第二个需要大量工作,我建议采用选项 3。