-1

We have a C# library that encrypts and decrypts using Rijndael

 _algorithm = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.ISO10126 };

   public override byte[] Encrypt(byte[] bytes)
    {
        // a new iv must be generated every time
        _algorithm.GenerateIV();
        var iv = _algorithm.IV;
        var memoryStream = new MemoryStream();
        using (var encryptor = _algorithm.CreateEncryptor(_key, iv))
        using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
        {
            memoryStream.Write(iv, 0, iv.Length);
            cryptoStream.Write(bytes, 0, bytes.Length);
            cryptoStream.FlushFinalBlock();
            return memoryStream.ToArray();
        }
    }

There is a corresponding decrypt method in C# that decrypts what is encrypted by the above code. Now there comes a need that a node application will send an encrypted data using exactly the same algorithm. However, I believe because of the iv, the C# code is not able to decrypt it Any idea

 CryptoJS.AES.encrypt(
       value,
        key,
        {
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Iso10126,
        }
    );

const decryptedString= CryptoJS.enc.Base64.stringify(result.ciphertext);
Dan Hunex
  • 5,172
  • 2
  • 27
  • 38
  • Make sure that you specify the key as `Buffer` instance, and actually supply an IV? You seem to assume that things don't work without actually trying. – Maarten Bodewes Apr 14 '20 at 17:50
  • So why can't the new app that is encrypting use its decrypter? Confused. – Michael Dorgan Apr 14 '20 at 17:50
  • The node api encrypts and uploads it to the azure blob. The C# code gets it and decrypts it. – Dan Hunex Apr 14 '20 at 18:10
  • @MaartenBodewes I don't think you understand the problem. The C# library generatesIV from Rijndael. GenerateIV(). My problem for the IV on javascript, how can I generate a similar one as the C# one in javascript. and off course I have tested it several times. Didn't work – Dan Hunex Apr 14 '20 at 18:12

1 Answers1

1

The C# library generates a random IV. As that IV is 128 bits in size, it is impossible to generate an identical one using CryptoJS. And you don't need to: for decryption you simply send the IV together with the ciphertext. You can then directly set it instead for decryption.

You can do the same when going the other way: generate a random IV on the CryptoJS site, send the IV together with the ciphertext to the C# side and send it to the C# implementation.

Generally the IV is simply prefixed to the ciphertext. For CBC mode the size of the IV is always exactly one block: 128 bits / 16 bytes for AES. So the size is known, which makes it easy to retrieve it from the start of the ciphertext.


Note that:

  • using CBC without HMAC is entirely insecure for transport mode security - not only can an adversary make you receive invalid plaintext, CBC is also vulnerable against plaintext / padding oracle attacks;
  • CBC requires a unpredictable IV which is different for each plaintext when using the same key - generally this means generating a random IV;
  • ISO/IEC 10126 compatible padding is largely deprecated, everybody uses PKCS#7 compatible padding by now, for CBC anyways: most other modes don't require padding at all (but .NET has pretty bad support for other modes of operation).
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • On the C# library, it is legacy I don't have control. but getting 'Padding is invalid and cannot be removed.' – Dan Hunex Apr 14 '20 at 19:11
  • Wrong key, mangled or shortened ciphertext and for short messages invalid IV. But we might not have enough info to resolve that for you. – Maarten Bodewes Apr 14 '20 at 20:25