Reputation: 107
I have this code for encrypting and decrypting data:
def encrypt(self):
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
message = b"THE SECRET KEY IS VERY SECRET!"
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
label=None
)
)
print(ciphertext)
def decrypt(self):
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
with open('test.txt', 'r') as test:
message = test.read()
plaintext = private_key.decrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
label=None
)
)
print(plaintext)
I am new to cryptography
and don't know how it works. What I want is that I encrypt data, store it in a file and when I need this data that I can decrypt it again. Encryption works very well, but every time I try to decrypt it I get this error:
Ciphertext length must be equal to key size.
When I run it without the file it works.
Upvotes: 1
Views: 921
Reputation: 49351
In the encrypt
and decrypt
method, a new key pair is generated with each call, i.e. encryption and decryption are done with public and private keys that do not belong together, so that decryption must fail.
In encrypt
the ciphertext is not written to the file test.txt
at all (or did you do this manually?).
Furthermore, the ciphertext consists of binary data, so the I/O accesses must be done in binary mode (marked with a b
). Another possibility would be to use a suitable binary-to-string-encoding such as Base64.
In the following Python3 code a key pair is generated once, the public key is used for encryption and the private key for decryption. The ciphertext is written into the file at pathCiphertextFile
and loaded from there for decryption. Reading and writing is done in binary mode (rb
, wb
). Then decryption succeeds:
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
def encrypt(message, pathCiphertextFile, public_key):
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
label=None
)
)
with open(pathCiphertextFile, 'wb') as test:
test.write(ciphertext)
def decrypt(pathCiphertextFile, private_key):
with open(pathCiphertextFile, 'rb') as test:
ciphertext = test.read()
plaintext = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
label=None
)
)
return plaintext
message = b'THE SECRET KEY IS VERY SECRET!'
pathCiphertextFile = b'<path to ciphertext file>'
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
ciphertext = encrypt(message, pathCiphertextFile, private_key.public_key())
decryptedText = decrypt(pathCiphertextFile, private_key)
print(decryptedText)
Update: The posted error message indicates that the message length is larger than the key size you use (2048 bits). As Woodstock points out in his comment, with RSA the message cannot be longer than the key size, which is 256 bytes. Depending on the padding applied (which is mandatory for security reasons), the length is further reduced, e.g. for OAEP with SHA1 to 214 bytes, see here. Larger amounts of data are therefore encrypted in practice with a symmetric encryption like AES or with a hybrid encryption, which combines symmetric and asymmetric encryption: The data is encrypted using the symmetric encryption, the symmetric key is exchanged between both parties using the asymmetric encryption.
Upvotes: 2