5

I'm trying to use AES to safely store some passwords in a home-made password safe, but for some reason I'm not getting the original data back from AES.decrypt. Here is the code I'm testing with:

from Crypto.Cipher import AES
from Crypto.Hash import SHA256

def sha1(text):
    s = SHA256.new()
    s.update(text)
    return s.hexdigest()

aes = AES.new('JG9A90cqiveJ8K7n', AES.MODE_CFB, 'g4vhFIR1KncRIyvO')

text = 'This is some text that will be encrypted'
encrypted_text = aes.encrypt(text)
decrypted_text = aes.decrypt(encrypted_text)

print 'Original:\t' + sha1(text)
print 'Encrypted:\t' + sha1(encrypted_text)
print 'Decrypted:\t' + sha1(decrypted_text)

It's output:

Original:   099e17130a9c796c8b7f21f269a790e877c7f49b6a39deda33d4e7b63b80c049
Encrypted:  71006ff5dc695a32c020dbb27c45b4861ec10a76e40d349bf078bca56b57d5bb
Decrypted:  2683455f4ae01e3cd1cba6c2537712fee8783621f32c865b8d4526130ff0096d

I'm using the cypher feedback mode because I want to be able to encrypt and decrypt strings of any length, plus it won't bother me that it works on a byte-by-byte basis since I'm only planning on encrypting small strings.

What am I doing wrong here?

Hubro
  • 56,214
  • 69
  • 228
  • 381
  • The IV must be different (read: random) for each encryption with the same key. Don't use a static IV, because that makes the cipher deterministic and permits the attacker to deduce the plaintexts if they observed multiple ciphertexts. This is called the many-time pad (or [two-time pad](https://twitter.com/angealbertini/status/425561082841690112/photo/1)). The IV is not secret, so you can send it along with the ciphertext. Usually, it is simply prepended to the ciphertext and sliced off before decryption. – Artjom B. Apr 26 '17 at 05:27

2 Answers2

10

Because you are using the same aes object for encryption and decryption. After the encrypt the initial value has changed. So you are not using the same initial value for decrypting. The following does work (redeclaring aes):

from Crypto.Cipher import AES
from Crypto.Hash import SHA256

def sha1(text):
    s = SHA256.new()
    s.update(text)
    return s.hexdigest()

aes = AES.new('JG9A90cqiveJ8K7n', AES.MODE_CFB, 'g4vhFIR1KncRIyvO')

text = 'This is some text that will be encrypted'
encrypted_text = aes.encrypt(text)

aes = AES.new('JG9A90cqiveJ8K7n', AES.MODE_CFB, 'g4vhFIR1KncRIyvO')
decrypted_text = aes.decrypt(encrypted_text)

print 'Original:\t' + sha1(text)
print 'Encrypted:\t' + sha1(encrypted_text)
print 'Decrypted:\t' + sha1(decrypted_text)
klennepette
  • 3,176
  • 22
  • 23
  • Weird. I was following [an example in the official documentation](https://www.dlitz.net/software/pycrypto/doc/#crypto-cipher-encryption-algorithms) which doesn't recreate the cypher. I guess it's mentioned somewhere that AES cyphers must be used ***ONLY ONCE*** but I didn't spot it. – Hubro Jul 24 '12 at 11:45
  • 1
    @Codemonkey It seems it only mentions the following for Crypto.Cipher: `IV: Contains the initial value which will be used to start a cipher feedback mode. After encrypting or decrypting a string, this value will reflect the modified feedback text; it will always be one block in length. It is read-only, and cannot be assigned a new value.` – klennepette Jul 24 '12 at 11:52
0

Not sure why, but this works:

key = b"JG9A90cqiveJ8K7n"
mode = AES.MODE_CFB
iv = b"g4vhFIR1KncRIyvO"

text = 'This is some text that will be encrypted'

aes_enc = AES.new(key, mode, iv)
enc = aes_enc.encrypt(text)

aes_dec = AES.new(key, mode)
dec = aes_dec.decrypt(iv + enc)

assert text == dec[16:]

I'd have to look up the details of the iv and padding, too :)

Edit:

See http://packages.python.org/pycrypto/Crypto.Cipher.blockalgo-module.html#MODE_CFB

  • 1
    The IV needs to be stored with the ciphertext in order to decrypt. This is often done by simply pre-pending the IV to the ciphertext. My assumption is that your example worked because you did the manual step of pre-pending the IV to the ciphertext (**aes_dec.decrypt(iv + enc)**). Your example didn't work when I tried it on Python 2.7.11 – Mark Apr 22 '16 at 00:11