Search code examples
pythonpython-3.xencryptionaespycryptodome

Cannot decrypt given cyphertext twice with same AES Object


I am using an AES object (aesDecryptObj ) to decrypt a cyphertext that was encrypted using a seperate AES object (aesEncryptObj ).

def aesInit():
    global aesEncryptObj
    global aesDecryptObj
    aesKey = <my key>
    aesEncryptObj = AES.new(aesKey, AES.MODE_CBC, iv=<My Init Vector>)
    aesDecryptObj = AES.new(aesKey, AES.MODE_CBC, iv=<My Init Vector>)

def aesEncrypt(clearStr):
    global aesEncryptObj 
    padded_data = pad(str(clearStr).encode("utf-8"), aesEncryptObj.block_size)
    e = aesEncryptObj.encrypt(padded_data)
    eb64 = base64.b64encode(e)
    d = eb64.decode('ascii')
    return(d)

def aesDecrypt(encryptedStr):
    global aesDecryptObj
    e = base64.b64decode(encryptedStr)
    b = aesDecryptObj.decrypt(e)
    b = unpad(b, aesDecryptObj.block_size)
    clearStr = b.decode('utf-8')
    return(clearStr)

aesInit()

cypherText = aesEncrypt('test') #this line will render the same result no matter how many times it is repeated

print(aesDecrypt(cypherText)) #this line executes fine
print(aesDecrypt(cypherText)) #this line throws the "padding is incorrect" error

Using aesEncryptObj sequentially any number of times produces successful results, however, when I use aesDecryptObj to decrypt a given cyphertext two or more times in a row I receive the following error:

File "/usr/lib64/python3.6/site-packages/Cryptodome/Util/Padding.py", line 90, in unpad
    raise ValueError("Padding is incorrect.")
ValueError: Padding is incorrect.

Should it be the case that, given the same ciphertext, aesDecryptObj would produce the same results as it did the first time it decrypted the value?


Solution

  • AES objects have a state (at least with AES.MODE_CBC). You initialize that state with iv=<My Init Vector>. As you decrypt ciphertext the state changes. You need to reinitialize your object before you call decrypt again.

    You probably want something like:

    def aesDecrypt(encryptedStr):
        aesKey = <my key>
        aesDecryptObj = AES.new(aesKey, AES.MODE_CBC, iv=<My Init Vector>)
        e = base64.b64decode(encryptedStr)
        b = aesDecryptObj.decrypt(e)
        b = unpad(b, aesDecryptObj.block_size)
        clearStr = b.decode('utf-8')
        return(clearStr)
    

    Or you can simply call aesInit() again after decrypting the first ciphertext.