Our RijndaelManaged decrypt code no longer decrypts passwords correctly (it truncates) with .NET Core 7 and 6, but used to work with .NET Core 5.
It only decrypts the first 16 bytes, then ignores the rest of the message, so we only get 16 first digits of our passwords :-/
- .NET 5 used 'Internal.Cryptography.UniversalCryptoDecryptor'.
- .NET 6 uses the same, but fails in the same way as
- .NET 7 with 'System.Security.Cryptography.UniversalCryptoDecryptor'.
(this is irrelevant) I have noticed, that the newer versions internally expands a salt buffer from 16 to 20 bytes. In the .NET 5 version that works, that array is padded with the bytes [0 0 0 1]
,
whereas in the .NET 7 version that System.Security.Cryptography.Rfc2898DeriveBytes._salt
buffer appears as [0 0 0 0]
.
It is HMAC-SHA1, as far as I know..
Because Azure seems to recently have dropped all support for .NET 5, it is a rather pressing matter for us :-/.
public static string Decrypt(string cipherText, int BLOCKSIZE, int KeySize)
{
// 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);
// RijndaelManaged, BlockSize 256, 128 ..
using (RijndaelManaged Rijn_symmetricKey = new RijndaelManaged()) {
// https://stackoverflow.com/questions/52699604/how-to-use-rijndael-algorithm-with-256-long-block-size-in-dotnet-core-2-1
// https://github.com/dotnet/runtime/issues/18706
Rijn_symmetricKey.BlockSize = BLOCKSIZE; // 256; // System.PlatformNotSupportedException: 'BlockSize must be 128 in this implementation.'
Rijn_symmetricKey.Mode = CipherMode.CBC;
Rijn_symmetricKey.Padding = PaddingMode.PKCS7;
using (var decryptor = Rijn_symmetricKey.CreateDecryptor(keyBytes, ivStringBytes)) { // ICryptoTransform, System.Security.Cryptography.UniversalCryptoDecryptor
using (var memoryStream = new MemoryStream(cipherTextBytes)) {
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) {
var plainTextBytes = new byte[cipherTextBytes.Length];
// HERE WRONGLY ONLY FIRST 16 BYTES ARRIVES!
var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
string decrypted = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
return decrypted;
}
}
}
}
}
}