Search code examples
pythonencryptionaessalt

How to encrypt with AES in Python with no salt?


I want to encrypt some data using AES in Python such that two encryptions of the same data give the same output (using the same key in both encryptions). I tried to use a static IV but I still get two different outputs given one input.

Here is what I did:

from Crypto.Cipher import AES

iv = 16 * '\x00'
cipher = AES.new(key, AES.MODE_CBC, iv)

I would like to obtain the same cipher if I decide to encrypt the same data multiple times. Do you know how to prevent the use of a salt? Thank you!


Solution

  • The cipher object here is the state and is initialized using the provided key data and initialization vector. Once you start to use this initialized keystate it is modified for each block you encrypt when you use CBC mode. That is the cipher block chaining in action. To have two separate encryptions you need to use two separate keystates. Or, as mentioned, you can use a mode (ECB) that does not affect the keystate when encrypting a block.

    A demo (python3):

    from Crypto.Cipher import AES
    key = 16 * b'\0'
    iv = 16 * b'\0'
    plaintext = 16 * b'\x41'
    a = AES.new(key, AES.MODE_CBC, iv)
    b = AES.new(key, AES.MODE_CBC, iv)
    ar = a.encrypt(plaintext)
    br = b.encrypt(plaintext)
    >>> ar
    b'\xb4\x9c\xbf\x19\xd3W\xe6\xe1\xf6\x84\\0\xfd[c\xe3'
    >>> br
    b'\xb4\x9c\xbf\x19\xd3W\xe6\xe1\xf6\x84\\0\xfd[c\xe3'
    

    The disadvantage of ECB mode is everytime we encrypt this plaintext with this key and iv we will get this result. With CBC mode, each time we encrypt another block the keystate is changed and we get a different output which is dependent upon what has been encrypted before.

    ECB Mode

    >>> ecb = AES.new(16 * b'\0', AES.MODE_ECB)
    >>> ecb.encrypt(16 * b'\x41')
    b'\xb4\x9c\xbf\x19\xd3W\xe6\xe1\xf6\x84\\0\xfd[c\xe3'
    >>> ecb.encrypt(16 * b'\x41')
    b'\xb4\x9c\xbf\x19\xd3W\xe6\xe1\xf6\x84\\0\xfd[c\xe3'
    

    Each encryption produces the same result. No iv required.

    CBC Mode

    >>> cbc = AES.new(16 * b'\0', AES.MODE_CBC, 16 * b'\0')
    >>> cbc.encrypt(16 * b'\x41')
    b'\xb4\x9c\xbf\x19\xd3W\xe6\xe1\xf6\x84\\0\xfd[c\xe3'
    >>> cbc.encrypt(16 * b'\x41')
    b'o\x9fv\x9a\x9c\xaa\x03\x13\xba\x17\x8c\x1c.\x0f`v'
    >>> cbc.encrypt(16 * b'\x41')
    b'\n1\x165\xb5?\x04h\xa8\r>k\xdbK\xbc4'
    

    The first block encrypts the same as ECB mode but subsequent blocks are different.

    Futher discussion about modes of operation for block ciphers can be found online.