Runtime: Support for Rijndael encryption

Created on 26 Sep 2016  路  24Comments  路  Source: dotnet/runtime

I need to port some existing code that uses Rijndeal encryption to .net core. Unfortunately, Rijndeal encryption (RijndaelManaged class) with a blocksize key of 256 bit is not available for .net core. Any idea's when and if this will be made available?

area-System.Security

Most helpful comment

BouncyCastle.NetCore mentioned above has worked great for me as it still supports AES 256

Just to be precise (or, I suppose, pedantic): .NET Core supports _AES-256_. new RijndaelEngine(256) is Rijndael with a 256-bit block (and whatever keysize you gave it). Rijndael with a 128-bit block is AES. Rijndael with a 256-bit block is not.

The 256 in AES-256 refers to the key size, not the block size.

All 24 comments

Related to dotnet/runtime#17818 so you might check that out first.

Closing as dupe of dotnet/runtime#17818.

@adsolutbe Rijndael will only be supported with a block size of 128 in .NET Core (the RijndaelManaged type will only compute AES). We're not maintaining managed implementations of algorithms any longer, and neither of our native implementation providers have support for Rijndael (except when it's AES).

Well this just sucks.

@adsolutbe , @Looooooka may I introduce you to OpenSSL?

The problem for me is we have a lot of data encrypted using the 256 bit blocksize option.
So now I'll have to somehow load/call a standard. net lib to access the data or decrypt and encrypt everything using 128 bit blocksize.
Needless to say I am not a happy camper. Was kinda hoping someone would have created their own provider with 256 blocksize support but I can see I'll just have to sell option 1 or 2.
This is the sort of thing that could have management pull the plug on our transition to .net core.
Oh well.
Life :)

@Looooooka did you look at alternative crypto implementations like BouncyCastle? Based on your comments, it may satisfy your needs.

No but thank you very much!!
Will have a look tomorrow.
I'd rather just rewrite the code than deal with all that data :)

I get that we probably shouldn't of been using 256 blocksize or this encryption in general. But this really sucks and now I have to have a migration for all existing encrypted values.

Why doesn't .NET Core support whatever block size the native implementation does? Or doesn't CNG support any block size but 128?

As suggested above I switched to BouncyCastle and since the code works for. NET and core life is good again. There was no need to change the existing encrypted entries at all :)

@Looooooka Would you mind sharing the code you used for .NET Core for 256bit. I tried for a few hours to convert my encrypt and decrypt with bouncy and a different library but failed.

Why doesn't .NET Core support whatever block size the native implementation does?

That's what the situation is. CNG, OpenSSL, and Security.framework all support AES, none of them support Rijndael (except for Rijndael with a 128-bit block, which is AES).

.NET Framework has a managed implementation of the Rijndael algorithm. .NET Core does not.

I get that, not sure why it wasn't ported since it had a managed implementation and marked obsolete. We moved to data protection api but the migration isn't easy.... It would be much easier if there was options once you are on .net core.

Shipping an encryption implementation is a huge liability.

Could have been marked as deprecated and not supported and even put in a shim / compat library. This is really a huge pain point for those converting to .net core.. As they now have to figure this out once they hit this (it compiles) and then figure out the issue and then back port a migration to legacy code.

Maybe we should mark it as compat difference in https://github.com/dotnet/platform-compat?

BouncyCastle.NetCore mentioned above has worked great for me as it still supports AES 256

Just to be precise (or, I suppose, pedantic): .NET Core supports _AES-256_. new RijndaelEngine(256) is Rijndael with a 256-bit block (and whatever keysize you gave it). Rijndael with a 128-bit block is AES. Rijndael with a 256-bit block is not.

The 256 in AES-256 refers to the key size, not the block size.

Am I mistaken that BouncyCastle doesn't support all of the same paddings and ciphers that RijndaelManaged supported? I'm having a hard time matching up the two implementations because Zero padding gets used in various places with 256 bit block size among the other slight variations.

You are correct. But there are plenty of examples online on how to overcome this using PaddedBufferedBlockCipher, CbcBlockCipher(or others) and RijndaelEngine. Using the Net Standard libraries it will work in Net Core and Net Framework.

@Looooooka I believe I have managed to do that for the block properly but having trouble finding the zero padded implementation for the key/passphrase itself. The PbeParametersGenerator is requiring me to use PKCS5 (or similar) and provide salt and iteration count. Maybe this doesn't matter? This is where I'm stuck at the moment and don't see a clear way forward. Is there a more appropriate place to ask about this sort of thing?

Unfortunately I wouldn't know. When I was stuck with the block part(I was using PKCS7Padding), I got help here, so hopefully someone with more knowledge will come to the rescue with your problem as well.

For anyone else wondering, I was able to implement my own PbeParametersGenerator and ZeroPadderCipherParameters : KeyParameter to zero-pad a byte array to a certain length. This allowed me to move forward without having to using the other ways of padding.

    public class ZeroPadderCipherParameters : KeyParameter
    {
        public ZeroPadderCipherParameters(byte[] key) : base(key)
        {
        }

        public ZeroPadderCipherParameters(byte[] key, int keyOff, int keyLen) : base(key, keyOff, keyLen)
        {
        }
    }
    public class ZeroPadderThingy : PbeParametersGenerator
    {
        public override ICipherParameters GenerateDerivedMacParameters(int keySize)
        {
            while (Password.Length*8 < keySize)
            {
                Password[Password.Length] = 0;
            }

            return new ZeroPadderCipherParameters(Password);
        }

        public override ICipherParameters GenerateDerivedParameters(string algorithm, int keySize)
        {
            //TODO: Make this not crappy
            return GenerateDerivedMacParameters(keySize);
        }

        public override ICipherParameters GenerateDerivedParameters(string algorithm, int keySize, int ivSize)
        {
            //TODO: Make this not crappy
            return GenerateDerivedMacParameters(keySize);
        }

        [Obsolete]
        public override ICipherParameters GenerateDerivedParameters(int keySize)
        {
            throw new NotImplementedException();
        }

        [Obsolete]
        public override ICipherParameters GenerateDerivedParameters(int keySize, int ivSize)
        {
            throw new NotImplementedException();
        }
    }



md5-4f28d6f3e6e4edf7746f5a528c864972



            PbeParametersGenerator generator = new ZeroPadderThingy();
            generator.Init(Encoding.UTF8.GetBytes(Passphrase), new byte[], 0); //ugh
            key = (KeyParameter)generator.GenerateDerivedParameters("this isn't used", _keyBitSize);

It's not pretty but might be useful for someone else trying to accomplish the same thing for legacy projects.

n would you possibly be willing to share your whole Encrypt and Decrypt methods. I've been struggling with this for days now.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

GitAntoinee picture GitAntoinee  路  3Comments

v0l picture v0l  路  3Comments

iCodeWebApps picture iCodeWebApps  路  3Comments

omariom picture omariom  路  3Comments

jzabroski picture jzabroski  路  3Comments