Hinaser / jscrypto

Crypto library for Node/ES6/Typescript/Browser.
MIT License
36 stars 6 forks source link

AES GCM decrypts only part #16

Open fu-raz opened 5 months ago

fu-raz commented 5 months ago

I know you're probably not working on this anymore, but I'm hoping you'll at least see this message and might have an idea where I can look.

I'm trying to decrypt data using AES GCM. I can do this in node js perfectly fine and I've almost got it working in your library. I can authenticate the data and key using the AAD and tag, which works great. Then I can decrypt the payload, but it never decrypts the whole message, only a small part.

Full disclosure, I'm trying to decrypt the broadcast messages from Tuya devices, so I can (eventually) use them in an app called SignalRGB. I know how to do this in NodeJS, but their app only supports limited JS. So that's why I'm here. Your library is the only one so far that has been able to decrypt at least part of the data.

Here's a test script, assuming you import AES, MD5, GCM, Hex and Base64

const aad = Hex.parse('00000000000000000013000000f1');
const tag = Hex.parse('36521b69183234690ed71b27fea429b5');

const key = MD5.hash('yGAdlopoPVldABfn');
const payloadBase64 = 'gkfGIQ1HGkmfHBwFqN9mtmz0bWGMVIhllyfMdXM0GnnEu4FYtSeSVumBoNg6yQ0Zvy6vzZhrjpLheWVHwVrytFj1GXNqesVv2u0lyTuaaKtt41epfZbTJ53CUMCFiOyXBjJZlFzHDLVWdwNd6697JT5WVclT8LML7dQ1ZCRJ2RTRoccqa+qbXPtkuyknC6EqwfttCOlshpOB6eKNf0+mG8ZKPIAFIGKIorI/OZgsGy5o4sijBtbJzh9jGQQCp2hPwc57PXqmCnmzA7kvYJkt9XFW+DCS';
const payload = Base64.parse(payloadBase64);

const iv = Hex.parse('7dc8a528c958e1359c7b08ad');

var authtag = GCM.mac(AES, key, iv, aad, payload);

// Let's see if the data is correct
if (authtag.toString() !== tag.toString())
{
    console.log('Error authenticating data');
} else
{
    console.log('Key and data is valid');
    console.log(payload);
    console.log(payload.toString(Base64));

    let decrypted = AES.decrypt(payload.toString(Base64), key, {iv: iv, mode: GCM});
    console.log('Decrypted', decrypted);   
}

This is a 213 byte long encrypted json message. If I decrypt it in node js, it gives me exactly that. A 213 byte decrypted json message. When I use your library it gives me, in this case, 15 bytes of the decrypted json message. So it does decrypt correctly, it just stops randomly.

I have other examples where the library decrypts more, but never the full message. Do you have any clue where I should look?

Best regards, Rick

fu-raz commented 5 months ago

From what I debugged so far is that it happens in the unpad function. In this example it calculates nPaddingBytes = 198, which it then strips from the WordArray, leaving only 15 bytes.

Removing the padding.unpad(finalProcessedBlocks); from BlockCipher.js worked, but I don't know if this now messes up other encryption modes