AES解密偶现异常:Gzip解压失败问题排查与解决
偶现Gzip解压异常的AES解密问题处理
问题描述
实现了特定事件触发的解密功能,但偶尔会抛出无法解释的异常。
处理流程
- 获取主密钥/IV
- Base64解码
- AES-256 CBC解密
- Gzip解压(偶现失败环节)
- UTF-8解码
相关代码
public async Task<byte[]> PrivateDecrypt(long userId, byte[] data) { var key = await this.GetOrAddPrivateEncryptionKey(userId); var keyBytes = key.ToUTF8Bytes(); var (cipher, ivBytes) = data.ExtractIVPadding(); var decrypted = await cipher .AESDecryptAndDecompressAsync(keyBytes, ivBytes) .ConfigureAwait(false); return decrypted; }
public static byte[] FromBase64(this string base64) => Convert.FromBase64String(base64);
public static async Task<byte[]> AESDecryptAndDecompressAsync(this byte[] cipher, byte[] key, byte[] 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; aesAlg.IV = iv; aesAlg.Padding = PaddingMode.PKCS7; using var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); using (var decompressedStream = new MemoryStream()) { using (var encryptedStream = new MemoryStream(cipher)) { using (var cryptoStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read)) { using (var gzipStream = new GZipStream(cryptoStream, CompressionMode.Decompress)) await gzipStream.CopyToAsync(decompressedStream).ConfigureAwait(false); return decompressedStream.ToArray(); } } } }
异常堆栈信息
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.WriteAsyncCore(ReadOnlyMemory`1 buffer, CancellationToken cancellationToken) at System.Security.Cryptography.CryptoStream.CopyToAsyncInternal(Stream destination, Int32 bufferSize, CancellationToken cancellationToken) at System.IO.Compression.DeflateStream.CopyToStream.CopyFromSourceToDestinationAsync() at Trading.Tools.Bytes.EncryptionExtensions.AESDecryptAndDecompressAsync(Byte[] cipher, Byte[] key, Byte[] iv) in /src/Trading.Tools/Bytes/EncryptionExtensions.cs:line 207 at Trading.Web.Commons.Encryption.LocalEncryptionService.PrivateDecrypt(Int64 userId, Byte[] data) in /src/Trading.Web.Commons/Encryption/LocalEncryptionService.cs:line 107
从堆栈信息可见,问题出在解密后的Gzip解压环节。
假设
- 代码逻辑本身是可行的
- 异常出现频率极低
- 数据库中数据是正确的,否则功能完全无法运行
分析思路
由于问题具有随机性,推测是竞态条件导致,可能的原因:
- 数据库未返回完整字符串,误转义字符,但无法解释解密为何能成功
- 解密偶尔返回异常结果,怀疑存在共享状态问题
环境信息
- 使用EFCore 8.0.2读取数据库
- .NET Core 8.0.3环境
- PostgreSQL 16.1-bullseye数据库
更新记录
- 按@Charlieface建议修改代码后,问题仍存在
- 替换加密逻辑为BouncyCastle Nuget包后,问题解决。升级至8.0.3前无此问题,疑为版本补丁导致
内容的提问来源于stack exchange,提问作者Damian
相关产品推荐
相关产品推荐

