Webwhatsapp-wrapper: Is decryption of media files possible in wapi.js? (Solved)

Created on 24 Jun 2018  路  8Comments  路  Source: mukulhase/WebWhatsapp-Wrapper

The download_media python function does the decryption of an encrypted file using the axolotl.kdf.hkdfv3 python library.

However Whatsapp web does it using its own Javascript libraries.

Has anyone found a way of decrypting an encrypted media file using Javascript in wapi.js?

Which item in the Store object includes the decrypt function?

Most helpful comment

I found how to decrypt image data in Javascript. So let me share it:

This is the modified downloadFile function which returns an ArrayBuffer:

        window.WAPI.downloadFile2 = function (url, done) {
            let xhr = new XMLHttpRequest();
            xhr.onload = function () {
                if (xhr.readyState == 4) {
                    if (xhr.status == 200) {
                        done(xhr.response);
                    } else {
                        console.error(xhr.statusText);
                    }
                } else {
                    console.log(err);
                    done(false);
                }
            };

            xhr.open("GET", url, true);
            xhr.responseType = 'arraybuffer';
            //xhr.responseType = 'blob';
            xhr.send(null);
        };

And this is how you decrypt the downloaded ArrayBuffer:

                            WAPI.downloadFile2(msg.clientUrl, function(result) {
                                console.log("Encryption Key:" + msg.mediaKey);
                                console.log("Image Data:");
                                console.log(result); 
                                Store.CryptoLib.decryptE2EMedia("IMAGE", result, msg.mediaKey, "image/jpeg").then(function(a) {
                                    console.log("Decrypted Data:");
                                    console.log(a); 
                                    console.log(a._blob); 

                                    let reader = new FileReader();
                                    reader.readAsDataURL(a._blob);
                                    reader.onload = function (e) {
                                        console.log("FileReader result1:")
                                        console.log(reader.result)
                                        console.log("FileReader result2:")
                                        console.log(reader.result.substr(reader.result.indexOf(',') + 1));
                                    };
                                }).catch(function(e) {
                                    console.log("Error: " + e);
                                });
                            });

To get the CryptoLib object add the following item to 'neededObjects' array:

{ id: "CryptoLib", conditions: (module) => (module.decryptE2EMedia) ? module : null },

I hope this may be useful to someone who needs it. :)

I'm not closing the issue so that it will be visible in the issues list.

All 8 comments

I found how to decrypt image data in Javascript. So let me share it:

This is the modified downloadFile function which returns an ArrayBuffer:

        window.WAPI.downloadFile2 = function (url, done) {
            let xhr = new XMLHttpRequest();
            xhr.onload = function () {
                if (xhr.readyState == 4) {
                    if (xhr.status == 200) {
                        done(xhr.response);
                    } else {
                        console.error(xhr.statusText);
                    }
                } else {
                    console.log(err);
                    done(false);
                }
            };

            xhr.open("GET", url, true);
            xhr.responseType = 'arraybuffer';
            //xhr.responseType = 'blob';
            xhr.send(null);
        };

And this is how you decrypt the downloaded ArrayBuffer:

                            WAPI.downloadFile2(msg.clientUrl, function(result) {
                                console.log("Encryption Key:" + msg.mediaKey);
                                console.log("Image Data:");
                                console.log(result); 
                                Store.CryptoLib.decryptE2EMedia("IMAGE", result, msg.mediaKey, "image/jpeg").then(function(a) {
                                    console.log("Decrypted Data:");
                                    console.log(a); 
                                    console.log(a._blob); 

                                    let reader = new FileReader();
                                    reader.readAsDataURL(a._blob);
                                    reader.onload = function (e) {
                                        console.log("FileReader result1:")
                                        console.log(reader.result)
                                        console.log("FileReader result2:")
                                        console.log(reader.result.substr(reader.result.indexOf(',') + 1));
                                    };
                                }).catch(function(e) {
                                    console.log("Error: " + e);
                                });
                            });

To get the CryptoLib object add the following item to 'neededObjects' array:

{ id: "CryptoLib", conditions: (module) => (module.decryptE2EMedia) ? module : null },

I hope this may be useful to someone who needs it. :)

I'm not closing the issue so that it will be visible in the issues list.

@mukulhase

@postacik Does this mean, that it would be able to get the full sized image directly from javascript?

This would mean that there would be the possibility to create a version of webwhatsapi that won't rely on axalot-api

That's right. The example above does exactly what you describe.

I couldn't make it work to PTT media, but to work in any media, using the functions given by @postacik:

WAPI.processMediaMessage = (messageObj) => {
    WAPI.download2(messageObj.clientUrl, (arrBuffer) => {
        Store.CryptoLib.decryptE2EMedia(messageObj.type.toUpperCase(), arrBuffer,
            messageObj.mediaKey, messageObj.mimetype)
            .then((a) => {
                let fr = new FileReader();
                fr.readAsDataURL(a._forceToBlob());
                fr.onloadend = () => {
                    let base64 = fr.result.split(',')[1];
                    messageObj.body = base64;
                    messageObj.content = base64;
                }
            });
    });
}

But to remote browser this does not work. I think it's because the _WAPI.download2_ is async.

Do you guys have any idea to do this to a remote browser? Thanks!

Is it possible to do the same "offline"?
I mean if I have the localStorage that contaons the "encKey" and "key", how can I decrypt an encrypted file?
I know it's aes but I don't know the IV (if the key is key or encKey)

@postacik This was really useful, thankss

Im trying decrypt the images, but im receiving this error:
Console:
Encryption Key:XoCx4cwS6d/X5c5iOn0nOSkfEEqUZZumeDy8HVbGsqw=
Image Data:ArrayBuffer(114522) {}
Error: MediaEncryptionError: decrypt async, missing "payload"

Can someone help me ??

Was this page helpful?
0 / 5 - 0 ratings