如何使用 PyCryptodome 加密和解密文件? (RSA)

问题描述 投票:0回答:1

我正在尝试使用 PyCryptodome 加密和解密文件,但没有成功。我可以很好地加密字符串和数据,但是当尝试加密文件时它会失败。我有两个问题,第一是我无法加密较大的字符串。我试图通过使用缓冲区读取文件来解决问题。其次,当我尝试将其加密为较小的缓冲区时,它只会给我一个错误“raise ValueError(“长度不正确的密文。”)“

我的代码如下所示:

from Crypto.Cipher import PKCS1_OAEP
import binascii
import ast

file_to_encrypt = "file_example_MP3_700KB.mp3"
buffer_size = 65536  # 64kb

input_file = open(file_to_encrypt, "rb")
output_file = open(file_to_encrypt + ".encrypted", "wb")


# Import keys
pub = open("publickey.txt", "rb")
pubKey = RSA.importKey(pub.read())
pub.close()

priv = open("privatekey.txt", "rb")
keyPair = RSA.importKey(priv.read())
priv.close()
# --------------------------------------------------------------


# Encrypt
encryptor = PKCS1_OAEP.new(pubKey)
buffer = input_file.read(buffer_size)

while len(buffer) > 0:
    encrypted = encryptor.encrypt(buffer)
    output_file.write(encrypted)
    buffer = input_file.read(buffer_size)

input_file.close()
output_file.close()
# --------------------------------------------------------------


input_file = open(file_to_encrypt + ".encrypted", "rb")
output_file = open(file_to_encrypt + ".decrypted", "wb")


# Decrypt
decryptor = PKCS1_OAEP.new(keyPair)
buffer = input_file.read(buffer_size)

while len(buffer) > 0:
    decrypted = decryptor.decrypt(ast.literal_eval(str(buffer)))
    output_file.write(decrypted)
    buffer = input_file.read(buffer_size)

input_file.close()
output_file.close()
# --------------------------------------------------------------

生成密钥如下所示:

from Crypto.Cipher import PKCS1_OAEP
import binascii
import ast

# key generation
keyPair = RSA.generate(3072*2)
pubKey = keyPair.publickey()
# --------------------------------------------------------------

# Export keys
pub = open("publickey.txt", "wb")
pub.write(pubKey.exportKey('PEM'))
pub.close()

priv = open("privatekey.txt", "wb")
priv.write(keyPair.exportKey('PEM'))
priv.close()
# --------------------------------------------------------------

# Import keys
pub = open("publickey.txt", "rb")
pubKey = RSA.importKey(pub.read())
pub.close()

priv = open("privatekey.txt", "rb")
keyPair = RSA.importKey(priv.read())
priv.close()
# --------------------------------------------------------------

# encryption
msg = '550011'
encryptor = PKCS1_OAEP.new(pubKey)
encrypted = encryptor.encrypt(msg.encode())
# --------------------------------------------------------------

# decryption
decryptor = PKCS1_OAEP.new(keyPair)
decrypted = str(decryptor.decrypt(ast.literal_eval(str(encrypted))))[2:-1]
# --------------------------------------------------------------

print("Encrypted:", binascii.hexlify(encrypted))
print("Decrypted:", decrypted)

if msg == decrypted:
    print("PASSED!")
else:
    print("FAILED!")

更改 buffer_size 解决了第一个问题(我尝试加密的数据太大。) 但加密后我仍然无法解密我的文件。

生成和导入密钥效果很好。用它们加密和解密也可以正常工作。只要我只加密小字符串而不是文件。

python encryption cryptography rsa pycryptodome
1个回答
0
投票

正如 Topaco 所说,这不是一个好主意,因为耗时等。无论如何,您可以简单地将文件切成块,对其进行加密并以可以检索块的方式对其进行编码,即通过创建每个加密块一个新行。请注意,我们需要确保加密的块不包含任何

\n
(换行符)。为此,我们可以简单地对加密块进行hexify并将其编码为
UTF-8
。也就是说,这在尺寸和时间上都不是一种有效的技术。

要求

安装pycryptodome并下载

file_example_MP3_700KB.mp3

# Optional, use a venv
python -m venv rsa_env
source rsa_env/bin/activate or ./rsa_env/Scripts/activate

# Install the needed package
pip install pycryptodome

生成您的密钥对

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

# key generation
key_pair = RSA.generate(2048)
public_key = key_pair.publickey()
# --------------------------------------------------------------

# Export keys
with open("publickey.txt", "wb") as public_key_file:
    public_key_file.write(public_key.exportKey('PEM'))

with open("privatekey.txt", "wb") as private_key_file:
    private_key_file.write(key_pair.exportKey('PEM'))

# --------------------------------------------------------------

del key_pair
del public_key

# Import keys
with open("publickey.txt", "rb") as public_key_file:
    public_key = RSA.importKey(public_key_file.read())

with open("privatekey.txt", "rb") as private_key_file:
    key_pair = RSA.importKey(private_key_file.read())
# --------------------------------------------------------------

# encryption
MESSAGE = b'550011'
scrambler = PKCS1_OAEP.new(public_key)
encrypted = scrambler.encrypt(MESSAGE)
# --------------------------------------------------------------

# decryption
descrambler = PKCS1_OAEP.new(key_pair)
decrypted = descrambler.decrypt(encrypted)
# --------------------------------------------------------------

print("Encrypted:", encrypted)
print("Decrypted:", decrypted)

if MESSAGE == decrypted:
    print("PASSED!")

else:
    print("FAILED!")

加密您的文件

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

# https://file-examples.com/index.php/sample-audio-files/sample-mp3-download/
FILE_TO_ENCRYPT = "file_example_MP3_700KB.mp3"
PATH_TO_PUBLIC_KEY = "publickey.txt"


def load_public_key(path):
    with open(path, "rb") as public_key_file:
        return RSA.importKey(public_key_file.read())


def public_key_bytes_length(public_key) -> int:
    key: bytes = public_key.public_key().export_key()
    return len(key[key.index(b'\n'):key.rindex(b'\n')])


def encrypt_file(public_key, file_path, encrypted_file_path):
    scrambler = PKCS1_OAEP.new(public_key)

    # It is just a guest
    buffer_size = public_key_bytes_length(public_key) // 2

    with open(file_path, "rb") as input_file:
        with open(encrypted_file_path, "wb") as output_file:
            while True:
                to_encrypt = input_file.read(buffer_size)

                # We reached the end
                if len(to_encrypt) == 0:
                    break

                encrypted = scrambler.encrypt(to_encrypt)
                output_file.write(encrypted.hex().encode('utf-8'))
                output_file.write(b'\n')


if __name__ == "__main__":
    encrypt_file(
        load_public_key(PATH_TO_PUBLIC_KEY),
        FILE_TO_ENCRYPT,
        f"{FILE_TO_ENCRYPT}.encrypted"
    )

解密它

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

FILE_TO_DECRYPT = "file_example_MP3_700KB.mp3.encrypted"
PATH_TO_PRIVATE_KEY = "privatekey.txt"


def load_private_key(path):
    with open(path, "rb") as private_key_file:
        return RSA.importKey(private_key_file.read())


def decrypt_file(private_key, file_path, decrypted_file_path):
    descrambler = PKCS1_OAEP.new(private_key)

    with open(file_path, "rb") as input_file:
        with open(decrypted_file_path, "wb") as output_file:
            while True:
                to_decrypt = input_file.readline()

                # We reached the end
                if len(to_decrypt) == 0:
                    break

                to_decrypt = bytes.fromhex(
                    # Remove newline and decode the line
                    to_decrypt[:-1].decode('utf-8')
                )

                decrypted = descrambler.decrypt(to_decrypt)
                output_file.write(decrypted)


if __name__ == "__main__":
    decrypt_file(
        load_private_key(PATH_TO_PRIVATE_KEY),
        FILE_TO_DECRYPT,
        f"{FILE_TO_DECRYPT}.decrypted.mp3"
    )

© www.soinside.com 2019 - 2024. All rights reserved.