Я могу определенно опоздать и, возможно, пропустил предыдущие ответы, но я не нашел четкого заявления о том, как это (по крайней мере, ИМХО) сделать в соответствии с пакетами PyCrypto.
Пакет Crypto.Util.Counter предоставляет вызываемые счетчики состояния, которые очень полезны, но по крайней мере мне было легко использовать их ненадлежащим образом.
Вы должны создать счетчик, например, ctr = Counter.new('parameters here')
. Каждый раз, когда ваш счетчик вызывается объектом шифрования режима счетчика для шифрования сообщения, он увеличивается. Это необходимо для правильной криптографической практики, в противном случае информация о равных блоках может вытекать из зашифрованного текста.
Теперь вы не можете вызывать функцию дешифрования для того же объекта шифрования, потому что он вызовет снова тот же счетчик, который за это время был увеличен, возможно, в несколько раз. Вам нужно создать новый объект шифрования с другим счетчиком, инициализированным с теми же параметрами. Таким образом, расшифровка работает правильно, начиная счетчик с той же точки, что и шифрование.
Рабочий пример ниже:
# Import modules
from Crypto.Cipher import AES
from Crypto import Random
from Crypto.Util import Counter
# Pad for short keys
pad = '# constant pad for short keys ##'
# Generate a random initialization vector, to be used by both encryptor and decryptor
# This may be sent in clear in a real communication
random_generator = Random.new()
IV = random_generator.read(8)
# Encryption steps
# Ask user for input and pad or truncate to a 32 bytes (256 bits) key
prompt = 'Input your key. It will padded or truncated at 32 bytes (256 bits).\n-: '
user_keye = raw_input(prompt)
keye = (user_keye + pad)[:32]
# Create counter for encryptor
ctr_e = Counter.new(64, prefix=IV)
# Create encryptor, ask for plaintext to encrypt, then encrypt and print ciphertext
encryptor = AES.new(keye, AES.MODE_CTR, counter=ctr_e)
plaintext = raw_input('Enter message to cipher: ')
ciphertext = encryptor.encrypt(plaintext)
print ciphertext
print
# Decryption steps
# Ask user for key: it must be equal to that used for encryption
prompt = 'Input your key. It will padded or truncated at 32 bytes (256 bits).\n-: '
user_keyd = raw_input(prompt)
keyd = (user_keyd + pad)[:32]
# Create counter for decryptor: it is equal to the encryptor, but restarts from the beginning
ctr_d = Counter.new(64, prefix=IV)
# Create decryptor, then decrypt and print decoded text
decryptor = AES.new(keyd, AES.MODE_CTR, counter=ctr_d)
decoded_text = decryptor.decrypt(ciphertext)
print decoded_text