1

I have started learning about some crypto stuff and was trying to implement AES encryption in a side project in angular 7. Encryption return a cipher text but when I decrypt cipher it returns empty string. I tried searching on internet but cannot find any solution maybe anyone can help.

 encryptPasswords(credentials: PasswordData) {

        const password = credentials.password;

        // msgString is expected to be Utf8 encoded
        const key = CryptoJS.enc.Utf8.parse(utilities.localStorageHelper.LowLevelKey);
        const iv = CryptoJS.lib.WordArray.random(16);
        const encrypted = CryptoJS.AES.encrypt(password, key, {
            iv: iv
        });
        return iv.concat(encrypted.ciphertext).toString(CryptoJS.enc.Base64);
    }

    decryptPasswords(credentials: PasswordData) {
        /*
        * Decrypt payload
        * @param {string}  ciphertextStr - Encrypted Payload
        * @return {}
        */

        const key = CryptoJS.enc.Utf8.parse(utilities.localStorageHelper.LowLevelKey);
        const ciphertext = CryptoJS.enc.Base64.parse(credentials.password);

        // split IV and ciphertext
        const iv = ciphertext.clone();
        iv.sigBytes = 16;
        iv.clamp();
        ciphertext.words.splice(0, 4); // delete 4 words = 16 bytes
        ciphertext.sigBytes -= 16;

        // decryption
        const decrypted = CryptoJS.AES.decrypt({ ciphertext: ciphertext }, key, {
            iv: iv
        });
        console.log(decrypted);
        return decrypted.toString(CryptoJS.enc.Utf8);
    }

PS:- I am still learning so there might be some silly mistake :P

thanks in Advance

SOMEONE
  • 31
  • 1
  • 3
  • Ideally encryption should be done in the server side. From that perspective, if you want to do it in node.js, you may want to refer to this answer. Once you understand the explanation, you would be able to debug yourself: https://stackoverflow.com/a/53573115/1235935 – Saptarshi Basu Dec 01 '18 at 17:50

1 Answers1

0

I would start by reviewing the following link, please note the ciphertext = ....).toString()

  • calling encrypt.toString() outputs the encryption already base64 encoded.

Then you will notice they immediately pass the output of ciphertext = ....).toString() to the decryption.

https://github.com/brix/crypto-js#object-encryption


I am not sure the ramifications of using encrypt.ciphertext I personally do not use it so I am not in a position to comment on it... but I do know that the output of the following is not the same... This would be something to investigate futher.

console.log(encrypted.toString())
console.log(CryptoJS.enc.Base64.stringify(encrypted.ciphertext))

Please note: I believe the decryption expects the ciphertext to be a base64 string... that is at least the case in my application.


I suspect encrypt.toString() versus CryptoJS.enc.Base64.stringify(encrypted.ciphertext) may be the start of your problem... but looking at your concatenation process I suspect there may be issues there as well.

You are generating a random initialization vector with each encryption so there should be a certain layer of obfuscation there... I would just base64 the IV and concatenate it with a delimiting character like : for example... something like this would make life a little easier during the decryption stage in terms of isolating the two... would be a lot easier to troubleshoot as well compared to what you are doing now.

This will result in iv:ciphertext concatenated with a : delimiter both base64... if you had concerns you could then base64 the output of this before you transmit it across the wire... not that it would make it secure... but it would at least be another layer of obfuscation.

btoa(iv)+':'+encrypted.toString()

I will say I think the splice may be a problem... looking at source and destination in the console log... I think the splice may need to be splice(4,4) as those 4 indexes seem to be the ones you want... but again I am not too familiar with how you are attempting this part... so I will defer.

I know this is not a copy paste solution but I am hoping this will be enough information to get you where you need to go.


Revision

Hoping this is copy and paste... if it is it will be a working baseline you can modify as needed.

encryptPasswords(credentials: PasswordData) {

        const password = credentials.password;

        // msgString is expected to be Utf8 encoded
        const key = CryptoJS.enc.Utf8.parse(utilities.localStorageHelper.LowLevelKey);
        const iv = CryptoJS.lib.WordArray.random(16);
        const encrypted = CryptoJS.AES.encrypt(password, key, {
            iv: iv
        });

        return btoa(btoa(iv)+':'+encrypted.toString())
        // return iv.concat(encrypted.ciphertext).toString(CryptoJS.enc.Base64);
    }

    decryptPasswords(credentials: PasswordData) {
        /*
        * Decrypt payload
        * @param {string}  ciphertextStr - Encrypted Payload
        * @return {}
        */

        const key = CryptoJS.enc.Utf8.parse(utilities.localStorageHelper.LowLevelKey);
        // const ciphertext = CryptoJS.enc.Base64.parse(stringBase64);
        const ciphertextArray = atob(stringBase64).split(':');

        const iv = ciphertextArray[0];
        const ciphertext = ciphertextArray[1]

        // split IV and ciphertext
        // const iv = ciphertext.clone();
        // iv.sigBytes = 16;
        // iv.clamp();
        // ciphertext.words.splice(0, 4); // delete 4 words = 16 bytes
        // ciphertext.sigBytes -= 16;

        // decryption
        const decrypted = CryptoJS.AES.decrypt(ciphertext, key, {
            iv: iv
        });

        return decrypted.toString(CryptoJS.enc.Utf8);
    }
Marshal
  • 10,499
  • 2
  • 34
  • 53