Quantcast
Channel: Active questions tagged utf-8 - Stack Overflow
Viewing all articles
Browse latest Browse all 1223

c# unexpected behaviour of Aes decryption

$
0
0

The problem: I have implemented some functionality that does decryption at specific events, but SOMETIMES it throws unexpected and unexplained exceptions.

Flow: A master key/iv is fetched then data (from a PostgreSQL database is fetched) and decoded from base64 and then decrypted and then decompressed and decoded again. So summarizing it goes like this:

  1. Fetch Key/Iv
  2. Decode From Base64
  3. Decrypt with AES-256 CBC
  4. Decompress from Gzip (At this point it fails sometimes)
  5. Decode again to UTF-8

This is the code

public async Task<string> PrivateDecrypt(long userId, string data){   var aesData = await this.GetOrAddPrivateEncryptionData(userId);   var decrypted = await data.FromBase64().AESDecryptAsync(aesData.Key, aesData.IV);   var decompressed = decrypted.DecompressFromGzip();   return decompressed.ToUTF8String();}
public static byte[] FromBase64(this string base64) => Convert.FromBase64String(base64);
public static async Task<byte[]> AESDecryptAsync(this byte[] cipher, string key, string iv){   if (cipher == null || cipher.Length <= 0)      throw new ArgumentNullException(nameof(cipher), "incorrect data");   if (key == null || key.Length != 32)      throw new ArgumentNullException(nameof(key), "incorrect key");   if (iv == null || iv.Length != 16)      throw new ArgumentNullException(nameof(iv), "incorrect iv");   using var aesAlg = Aes.Create();   aesAlg.Mode = CipherMode.CBC;   aesAlg.KeySize = 256;   aesAlg.Key = key.ToUTF8Bytes();   aesAlg.IV = iv.ToUTF8Bytes();   aesAlg.Padding = PaddingMode.PKCS7;   using var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);   return await PerformCryptographyAsync(cipher, decryptor).ConfigureAwait(false);}
private static async Task<byte[]> PerformCryptographyAsync(byte[] data, ICryptoTransform cryptoTransform){   using var memoryStream = new MemoryStream();   using var cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write);   await cryptoStream.WriteAsync(data, 0, data.Length).ConfigureAwait(false);   await cryptoStream.FlushFinalBlockAsync().ConfigureAwait(false);   return memoryStream.ToArray();}

This is part of the exception stack trace I receive

System.IO.InvalidDataException: The archive entry was compressed using an unsupported compression method.   at System.IO.Compression.Inflater.Inflate(FlushCode flushCode)   at System.IO.Compression.Inflater.ReadInflateOutput(Byte* bufPtr, Int32 length, FlushCode flushCode, Int32& bytesRead)   at System.IO.Compression.Inflater.InflateVerified(Byte* bufPtr, Int32 length)   at System.IO.Compression.DeflateStream.CopyToStream.CopyFromSourceToDestination()   at Trading.Tools.Bytes.CompressionExtensions.DecompressFromGzip(Byte[] data) in /src/Trading.Tools/Bytes/CompressionExtensions.cs:line 25   at Trading.Web.Commons.Encryption.LocalEncryptionService.PrivateDecrypt(Int64 userId, String data) in /src/Trading.Web.Commons/Encryption/LocalEncryptionService.cs:line 99

As you can see from the stacktrace the problem lies in the decompression layer AFTER the decryption.

Hypothesis:

  1. This code I can say for sure that it works
  2. This exception that I encounter happens quite rarely
  3. Data in database is correct, otherwise it would never work

My thoughts:

  1. I believe that due to probabilistic nature of the problem then this can be a race condition. There are 2 possibilities I see:
  • Either the database doesn't return me the full string and it escapes some character by mistake, but then how does decryption work ?
  • Either decryption returns weird results sometimes which leads me to think that even if there are separate instances there is still a shared state somewhere ?

Additional Info:

  1. I'm using EFCore 8.0.2 for fetching from database
  2. I'm using .NET Core 8.0.0
  3. I'm using PostgreSQL 16.1-bullseye

Viewing all articles
Browse latest Browse all 1223

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>