Python Aes-256 GMC decrypt error at decode result

Question:

I’m facing a issue to decrypt data that was encrypted in Node JS into python code:

Error at "return decrypted.decode('utf-8')"
Error: 'utf-8' codec can't decode byte 0xc8 in position 0: invalid continuation byte

any idea why?

import base64
from Crypto.Cipher import AES

args = {
    "content": "725cd5204cf64987a39a6622884527e0",
    "iv": "e6174b11cd2a18fc",
    "tag": {
        "data": [26, 91, 205, 206, 134, 22, 167, 101, 110, 27, 155, 100, 41, 99, 34, 135],
        "type": "Buffer"
    },
    "key": "SqqUUMnwEVUCBYT7p/0Zfz4Cq2eazHqQ"
}

def decrypt_auth_tag(args):
    try:
        key = args["key"]
        content = bytes.fromhex(args["content"])
        iv = bytes.fromhex(args["iv"])
        tag = bytes(args["tag"]["data"])
        
        cipher = AES.new(key.encode('utf-8'), AES.MODE_GCM, nonce=iv)
        cipher.update(tag)
        decrypted = cipher.decrypt(content)
        return decrypted.decode('utf-8')
    except Exception as e:
        print("Error:", e)

print(decrypt_auth_tag(args))

The encryption is done by a serve which I don’t have access to, but I have the version in node js who works really well to decrypt I just need same version in Python code.

Here the version in Node that works to decrypt:

const crypto = require('crypto');

let args = {
    "content": "725cd5204cf64987a39a6622884527e0",
    "iv": "e6174b11cd2a18fc",
    "tag":
    {
        "data": [26, 91, 205, 206, 134, 22, 167, 101, 110, 27, 155, 100, 41, 99, 34, 135],
        "type": "Buffer"
    }
}
// Decrypts the data using a key, iv, and auth tag
function decryptAuthTag(args) {
    try {
        const key = "SqqUUMnwEVUCBYT7p/0Zfz4Cq2eazHqQ";
        const encrypted = {
            content: args.content,
            iv: args.iv,
            tag: args.tag
        };

        const alg = 'aes-256-gcm';
        const decipher = crypto.createDecipheriv(alg, key, encrypted.iv);
        decipher.setAuthTag(Buffer.from(encrypted.tag));
        let dec = decipher.update(encrypted.content, 'hex', 'utf8');
        dec += decipher.final('utf8');
        return dec;
    } catch (error) {
        return "ERROR"
    }
}

console.log(decryptAuthTag(args))
Asked By: Melque Lima

||

Answers:

Decryption works if the IV is UTF-8 encoded (and not hex decoded):

iv = args["iv"].encode('utf-8')

Note that decrypt() only decrypts without prior authentication. Also, update() does not specify the tag, but the additional authenticated data (AAD). The incorrect use of cipher.update(tag) has no effect here only because of the missing authentication.

In order for the data to be authenticated before decryption (as is intended), decrypt_and_verify() must be applied, passing ciphertext and tag:

decrypted = cipher.decrypt_and_verify(content, tag)

With this change, of course, the cipher.update(tag) line must be removed, otherwise authentication will fail and no decryption will be performed.


Regarding the IV size: For performance and compatibility reasons, the recommended IV size for GCM is 12 bytes (the posted example uses a size of 16 bytes).

Answered By: Topaco
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.