Encrypt/Decrypt - ASP .NET to NodeJS

Hi,
I have an ASP application where I am storing some informaiton in the DB by encrypting with a password. I now need to re-do the application in NodeJS but encryption/decryption is failing in the new project.

I tested the encrypt method in both ASP & NodeJS and found that both work differently.
On encrypting a value 123 with password 456, .NET returns 1ZW7FT9UpUPX0EagmwJFUMs2R3xp/gbOcmfRJqW7F0c= while NodeJS returns LrATaioPsEmHMJ9YwMWj6Q==.W+UH4MBifL/1+G5gh82IpQ==.

This basically means I cannot decrypt any of the encrypted values in the DB in the new project.
What to do here? Please help.

I had the same problem with PHP and NodeJS. Perhaps a custom formatter might work like it did for me?

Thanks @bpj
That is a good work-around. But what did you do for existing encrypted data?

Another caveat here is .NET does not support custom extensions. So I would have to replicate whatever encryption method is being used in .NET as a custom formatter in NodeJS… if Patrick can tell me what it is. Since its all DLLs there. :sweat_smile:

Once I had a compatible formatter I ran an API file that read the existing data, decrypted it server-side, and then stored it again using the new formatter.

I can’t help with .NET I’m afraid.

A new, cross-platform encryption algorithm would, I think be very useful - even if it had to be in addition to existing ones.

I believe that ASP, .NET and PHP are compatible with each other, NodeJS uses a different encrypt, it uses a more secure scrypt on the password while the others use a simple sha256 hash. Comparing the encrypted data will always be different, also with .NET encrypting the same data with the same password a second time will result in a different result.

Here the original C# code we use for the encrypt for if you want to create a compatible NodeJS version

        public static JToken Encrypt(JToken value, JToken password)
        {
            byte[] encrypted;

            using (RijndaelManaged aes = new RijndaelManaged())
            {
                aes.Padding = PaddingMode.Zeros;
                aes.Mode = CipherMode.CBC;
                using (SHA256Managed sha256 = new SHA256Managed())
                {
                    aes.Key = sha256.ComputeHash(Encoding.UTF8.GetBytes((string)password));
                }
                aes.GenerateIV();

                encrypted = aes.IV;

                ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);

                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter sw = new StreamWriter(cs, Encoding.UTF8))
                        {
                            sw.Write((string)value);
                        }

                        encrypted = encrypted.Concat(ms.ToArray()).ToArray();
                    }
                }
            }

            return new JValue(Convert.ToBase64String(encrypted));
        }

How does that work?
I don’t see anything in the shared code which would enable this. Does the encryptor object itself work like that?

Will check with the client what is the best option here. Converting all data to NodeJS version looks like an easire way out here.

aes.GenerateIV(); generates a unique salt each time you encrypt, so it is different each time. The salt is added to the encrypted output so that the salt can be retrieved again when decrypting.

Oh. Thanks. :slight_smile:

If you’re permanently transferring a project, you could have a API endpoint in your ASP project that decrypts an entry and returns it in response to an API call from your Node project. Just then save the response to the db

I thought of that too. But its not sustainable to have another server running just for one task.
And its reporting section of the application where I have this issue. So it won’t be practical performance wise to go to another server every few requests.

After some experimenting here the code for decrypting the data encrypted in .NET.

exports.decrypt = async function(encrypted, password) {
  const crypto = require('crypto')
  const data = Buffer.from(encrypted, 'base64')
  const key = crypto.createHash('sha256').update(password).digest()
  const iv = data.slice(0, 16)
  const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv)
  decipher.setAutoPadding(false)
  const decrypted = decipher.update(data.slice(16), null, 'utf8')
  return (decrypted + decipher.final('utf8')).replace(/\0*$/, '')
}
1 Like

Thank you for this Patrick. Wasn’t expecting this. :pray: