PyCrypto problem using AES+CTR

后端 未结 5 1220
轮回少年
轮回少年 2020-12-03 14:37

I\'m writing a piece of code to encrypt a text using symmetric encryption. But it\'s not coming back with the right result...

from Crypto.Cipher import AES
i         


        
5条回答
  •  余生分开走
    2020-12-03 15:17

    AES is a block cipher: it's an algorithm (more precisely, a pair of algorithms) that takes a key and a message block and either encrypts or decrypts the block. The size of a block is always 16 bytes, regardless of the key size.

    CTR is a mode of operation. It's a pair of algorithms that builds on a block cipher to produce a stream cipher, which can encrypt and decrypt messages of arbitrary lengths.

    CTR works by combining successive message blocks with the encryption of successive values of a counter. The size of the counter needs to be one block so that it's valid input for the block cipher.

    • Functionally, it doesn't matter what the successive values of the counter are, as long as the encryption and decryption side use the same sequence. Usually the counter is treated as a 256-bit number and incremented for each successive block, with an initial value chosen at random. Thus, usually, the incrementation method is baked into the code, but the decryption side needs to know what the initial value is, so encryption side sends or stores the initial counter value at the beginning of the encrypted message.
    • For security, it is vital to never repeat the same counter value with a given key. So for a single-use key, it's ok to start with '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'. But if the key is used multiple times then the second message is not allowed to reuse any of the counter values used by the first message, and the easiest way to ensure that is to generate the initial counter value at random (with a 2^128 space, the chances of a collision are acceptably negligible).

    By letting the caller pick a counter function, the PyCrypto library gives you plenty of rope to hang yourself. You should use Crypto.Util.Counter, not just “for better performance” as the documentation puts it, but because it's easier to build something secure than what you're likely to come up with on your own. And even so, take care to use a random initial value, which is not the default.

    import binascii
    import os
    from Crypto.Cipher import AES
    from Crypto.Util import Counter
    def int_of_string(s):
        return int(binascii.hexlify(s), 16)
    def encrypt_message(key, plaintext):
        iv = os.urandom(16)
        ctr = Counter.new(128, initial_value=int_of_string(iv))
        aes = AES.new(key, AES.MODE_CTR, counter=ctr)
        return iv + aes.encrypt(plaintext)
    def decrypt_message(key, ciphertext):
        iv = ciphertext[:16]
        ctr = Counter.new(128, initial_value=int_of_string(iv))
        aes = AES.new(key, AES.MODE_CTR, counter=ctr)
        return aes.decrypt(ciphertext[16:])
    

提交回复
热议问题