-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
256 blocksize does not work in .net core #13
Comments
What version of .NET Core are you using @ByronAP? Can you provide an example? |
.net core 2.0 and any example using a 256 block size will fail because you are trying to use AES which does not support that. This is block size not key size, a 256 key should work, a 256 block size will absolutely not work unless you write the actual rounds from scratch because the .net core team has emphatically refused to support Rijndael. You can try it by making a .net core console app and trying to decrypt anything that has been encrypted using Rijndael 256. It will fail as soon as you try and set that invalid block size. To further prove this remove the net45 section in the src, it should fail on all systems since it is AES (not tested but should). |
@ByronAP can you provide an example illustrating how you're using a 256 block size with Rijndael256? Rijndael256 currently supports:
N-256 isn't something I set out to support when I created this lib, but if a significant number of users would like to see it, I'm not opposed to investigating it's implementation. Are you certain you want to use 256 block size? It hasn't had nearly as much attention as 128 block size (which means it could have weaknesses that have yet to be discovered). |
I'm sure it is not all that common in .net however some libs in php use it along with some other functions so not having it in c# creates an interoperability impediment. I personally wouldn't bother because you have to write the whole thing yourself or rip some code from bouncy castle to make it work for what is essentially an edge case. |
Closing, since there doesn't appear to be a great interest in this feature. Will re-open if that changes. |
+1 |
https://stackoverflow.com/questions/10168240/encrypting-decrypting-a-string-in-c-sharp I'm using this easy and nice implementation that use 256 block size, could you have a look at it? |
I'm using the same as @ciacco85 but doesn't work on .net core cause it's block size is 256 D: |
Reopening, since interest is spiking |
I'm very interested, too. I have a library based created on .Net Standard. Importing it on .Net Framwork all goes right but using it on .Net Core I have problems. |
I have a similar issue, as well. I have data stored that is encrypted using an initialization vector that requires a block size of 256. I'm trying to find a way to decrypt these values in .NET Core and cannot use 256. |
Unfortunately, as of .NET Core 3.1, RijndaelManaged still does not support block sizes greater than 128. Looking at the source code, you can see .NET Core throws an exception if you try to use 192 or 256: https://github.com/dotnet/corefx/blob/release/3.1/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RijndaelImplementation.cs#L37 cc: @ciacco85 , @Gabriel-Espinoza |
they have made it quite clear over the years that it will never be supported since it is not an official implementation :-( |
+1 @JasonPierce are you still working on this? |
@wmmihaa I'm keeping on eye on it. Unfortunately, as of .NET Core 3, it still does not support this. We can hope that they do add support in the new .NET 5 that is currently in Preview 1. Perhaps we'll get support for it at that time, since it is currently supported in .NET Framework 🤞 |
I believe it is necessary to provide 256 blocksize encryption and decryption. |
Hey, If .NET Core 3.1 still does not support 256 initialization vector why documentation does not reflect that? Look at this: //RijndaelManaged Anybody can't get the same result! Why does the documentation is not refleting the truth? |
Just discovered this, and it creates a huge block. I have to support decryption in .net core of values encrypted with .net framework using 256 bit. Arrrrgggg!!! |
@davidathompson ...hope this can be of help Helper classpublic static class CipherHelper
{
// This constant is used to determine the keysize of the encryption algorithm in bits.
// We divide this by 8 within the code below to get the equivalent number of bytes.
private const int Keysize = 256;
// This constant determines the number of iterations for the password bytes generation function.
private const int DerivationIterations = 1000;
public static string Encrypt(string plainText, string passPhrase)
{
// Salt and IV is randomly generated each time, but is preprended to encrypted cipher text
// so that the same Salt and IV values can be used when decrypting.
var saltStringBytes = Generate256BitsOfRandomEntropy();
var ivStringBytes = Generate256BitsOfRandomEntropy();
var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
{
var keyBytes = password.GetBytes(Keysize / 8);
var engine = new RijndaelEngine(256);
var blockCipher = new CbcBlockCipher(engine);
var cipher = new PaddedBufferedBlockCipher(blockCipher, new Pkcs7Padding());
var keyParam = new KeyParameter(keyBytes);
var keyParamWithIV = new ParametersWithIV(keyParam, ivStringBytes, 0, 32);
cipher.Init(true, keyParamWithIV);
var comparisonBytes = new byte[cipher.GetOutputSize(plainTextBytes.Length)];
var length = cipher.ProcessBytes(plainTextBytes, comparisonBytes, 0);
cipher.DoFinal(comparisonBytes, length);
// return Convert.ToBase64String(comparisonBytes);
return Convert.ToBase64String(saltStringBytes.Concat(ivStringBytes).Concat(comparisonBytes).ToArray());
}
}
public static string Decrypt(string cipherText, string passPhrase)
{
// Get the complete stream of bytes that represent:
// [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText]
var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
// Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes.
var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
// Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes.
var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
// Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray();
using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
{
var keyBytes = password.GetBytes(Keysize / 8);
var engine = new RijndaelEngine(256);
var blockCipher = new CbcBlockCipher(engine);
var cipher = new PaddedBufferedBlockCipher(blockCipher, new Pkcs7Padding());
var keyParam = new KeyParameter(keyBytes);
var keyParamWithIV = new ParametersWithIV(keyParam, ivStringBytes, 0, 32);
cipher.Init(false, keyParamWithIV);
var comparisonBytes = new byte[cipher.GetOutputSize(cipherTextBytes.Length)];
var length = cipher.ProcessBytes(cipherTextBytes, comparisonBytes, 0);
cipher.DoFinal(comparisonBytes, length);
//return Convert.ToBase64String(saltStringBytes.Concat(ivStringBytes).Concat(comparisonBytes).ToArray());
var nullIndex = comparisonBytes.Length - 1;
while (comparisonBytes[nullIndex] == (byte)0)
nullIndex--;
comparisonBytes = comparisonBytes.Take(nullIndex + 1).ToArray();
var result = Encoding.UTF8.GetString(comparisonBytes, 0, comparisonBytes.Length);
return result;
}
}
private static byte[] Generate256BitsOfRandomEntropy()
{
var randomBytes = new byte[32]; // 32 Bytes will give us 256 bits.
using (var rngCsp = new RNGCryptoServiceProvider())
{
// Fill the array with cryptographically secure random bytes.
rngCsp.GetBytes(randomBytes);
}
return randomBytes;
}
} Unit test[Test]
public async Task CipherHelper_ShouldWork()
{
try
{
var value = "Secret to encrypt";
var passPhrase = "your pass phrase";
var encryptedValue = CipherHelper.Encrypt(value, passPhrase);
var decryptedValue = CipherHelper.Decrypt(encryptedValue, passPhrase);
Assert.IsTrue(value == decryptedValue);
}
catch (Exception ex)
{
Assert.Fail(ex.Message);
}
} |
@wmmihaa Thank you! That is exactly what I needed. You saved me a ton of time. |
@wmmihaa Thanks for this - seems to work flawlessly. For anyone wondering - it requires BouncyCastle.NetCore :) |
We have a desktop software using WPF and written a crypto library using RijndaelManaged using .NET FX 4.0 ~2010-2011 timeframe. If MS supported RijndaelManaged with 256 bit blocksize, then it should have a upgrade route. We can definitely use the newer and ratified AES also, but what do we do with encrypted data at rest in files. We do have to support data/ config files from our older products and can not abandon that. I strongly vote for this to be added to .NET 6. |
@wmmihaa, thank you so much! Saved us a lot of time. Cheers! ❤️ |
@wmmihaa , thanks for code! Just need to process corner-case of decrypting empty string. So, instead of
in
Works like a charm! And it seems like Bouncycastle.NetCore is unofficial package, so I've used official BouncyCastle.Cryptography |
In .net core AES is used which does not support 256 blocksize which is the exact reason why RijindaelManaged doesn't work. Unless I am missing something here, if I am please correct me as I can not get it to work.
Ref: https://github.com/dotnet/corefx/issues/12064
The text was updated successfully, but these errors were encountered: