null_error
null_error

Reputation: 51

How to encrypt & decrypt AES key with RSA and store in a textfile

Python, Pycrypto, RSA, AES

I am trying to implement a script that will encrypt a file using a randomly generated AES key then encrypt said AES key with an RSA public key. The encrypted AES key will be shared with authorized persons in possession of the private key to decrypt it. The code is as follows:

from Crypto.PublicKey import RSA
from Crypto.Cipher import AES
from Crypto import Random

RSAkey = '-----BEGIN PUBLIC KEY-----\nSome RSA Key here\n-----END PUBLIC KEY-----'

RSAkey = RSA.importKey(RSAkey)

key = Random.new().read(32)

enc_key = RSAkey.encrypt(key, '')

enc_key = str(enc_key)

custom_writefile_function('enc_key.txt', enc_key)

I am converting the enc_key to a string so that I can write it to a text file, otherwise enc_key.txt will contain rubbish. The problem however, is that in another script, meant for decrypting enc_key to get the original AES key used to encrypt the files, trying to decrypt the enc_key which has been converted to a string produces an error:

RSAkey.decrypt(str(RSAkey.encrypt(key, ''))) Traceback (most recent call last): File "", line 1, in File "/usr/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py", line 174, in decrypt return pubkey.pubkey.decrypt(self, ciphertext) File "/usr/lib/python2.7/dist-packages/Crypto/PublicKey/pubkey.py", line 93, in decrypt plaintext=self._decrypt(ciphertext) File "/usr/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py", line 237, in _decrypt cp = self.key._blind(ciphertext, r) ValueError: Message too large

The code is as follows:

RSAkey = custom_readfile_function('private_key.txt', 'r')
RSAkey = RSA.importKey(RSAkey)

enc_key = custom_readfile_function('enc_key.txt', 'r')

aes_key = RSAkey.decrypt(enc_key)

custom_writefile_function('key.txt', str(aes_key), 'w')

I beleive the issue is a type mismatch. RSAkey.encrypt(key, '') returns type 'tuple', so I figure RSA.decrypt() expects this type as well, but I can't write that type to a textfile. So when I convert it to a string for writing to file, I'll need to convert it back to type 'tuple' when I'm decrypting. How can I do this? Or maybe there is a better way of achieving my desired result that I haven't considered?

Thanks

Upvotes: 3

Views: 10069

Answers (2)

v01d
v01d

Reputation: 327

Even though more than one year has passed since you asked the question, I nevertheless want to provide an actual answer to your problem, because I have myself struggled with this minute yet uncomfortable error, so that anyone who encounters this situation would be able to quickly solve it.

First of all, as the other answer suggests, for human readability I would use base64 encoding:

enc_key = RSAkey.encrypt(key, '')

enc_key = base64.b64encode(enc_key[0]) 

where [0] represents the first value of the tuple which is generated by the encrypt method (the ciphertext itself).

Then, when you want to decrypt the whole thing, you call:

aes_key = RSAkey.decrypt(base64.b64decode(enc_key))

which should return you the original plaintext without the ValueError: Message too large

Upvotes: 0

Maarten Bodewes
Maarten Bodewes

Reputation: 93948

Use base 64 instead of converting directly to a string.

Beware of the documentation of the encrypt method you are using:

Returns: A tuple with two items. The first item is the ciphertext of the same type as the plaintext (string or long). The second item is always None. Overrides: pubkey.pubkey.encrypt

Furthermore, you should heed the following advice:

Attention: this function performs the plain, primitive RSA encryption (textbook). In real applications, you always need to use proper cryptographic padding, and you should not directly encrypt data with this method. Failure to do so may lead to security vulnerabilities. It is recommended to use modules Crypto.Cipher.PKCS1_OAEP or Crypto.Cipher.PKCS1_v1_5 instead.

Upvotes: 3

Related Questions