.net - 使用带有 BountyCastle .NET 的 AES256 解密失败并显示“mac check in GCM failed”
问题描述
我正在使用BountyCastle.NetCore NuGet 库从我们的服务器解密已经准备好的加密消息。我能够成功使用 Java 加密库(本机)和 Python(pycrptodome)实现。一般来说,我们的服务器正在准备这样的消息:
解密策略是:
通过 base64 解码 cryptographyKey 来准备 AES-256 密钥。
通过对消息正文进行 base64 解码来准备密文字节。
- 从密文中删除标签。
- 通过复制密文的前 16 个字节来准备 AAD。
- 通过从 AAD 复制字节 4 – 16 来准备 NONCE (IV)。
- 然后用AES-GCM解密,标签长度=16字节;输入
来自 1、3、4、5。
应用基于此示例的通用算法,我的实现如下所示:
注意:我没有在下面的代码中应用标签,因为它更像是一个验证步骤,我无法通过解密消息。
public string Decrypt(string cryptoKey, string cypherText)
{
string sR = string.Empty;
try
{
// Prepare the AES-256 secret key by decoding the cryptographyKey
var keyBytes = Convert.FromBase64String(cryptoKey);
// Prepare the Cypher bytes by decoding the cypher text
var cypherBytes = Convert.FromBase64String(cypherText);
// <------AAD----->
// [---][--NONCE--][-----Encrypted Message-----][---TAG---]
// <-------------------CypherText------------------------->
// Prepare the AAD - first AAD_LENGTH from cypher
var aad = new Byte[AAD_LENGTH];
Array.Copy(cypherBytes, 0, aad, 0, AAD_LENGTH);
// Prepare NONCE - bytes 4-16 from AAD
var nonce = new Byte[NONCE_LENGTH];
Array.Copy(aad, AAD_LENGTH - NONCE_LENGTH, nonce, 0, NONCE_LENGTH);
// Extract the encrypted message within the body - between AAD and TAG section
var encryptedMsgSize = cypherBytes.Length - TAG_LENGTH - AAD_LENGTH;
var encryptedMsg = new Byte[encryptedMsgSize];
Array.Copy(cypherBytes, AAD_LENGTH, encryptedMsg, 0, encryptedMsgSize);
GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine());
AeadParameters parameters = new AeadParameters(new KeyParameter(keyBytes), 128, nonce);
cipher.Init(false, parameters);
cipher.ProcessAadBytes(cypherBytes, 0, AAD_LENGTH);
byte[] plainBytes = new byte[cipher.GetOutputSize(encryptedMsg.Length)];
Int32 retLen = cipher.ProcessBytes(encryptedMsg, 0, encryptedMsg.Length, plainBytes, 0);
cipher.DoFinal(plainBytes, retLen);
sR = Encoding.UTF8.GetString(plainBytes).TrimEnd("\r\n\0".ToCharArray());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
return sR;
}
尽管尝试了许多不同的组合,设置不同的参数等,它总是会抛出异常:
cipher.DoFinal(plainBytes, retLen);
“在 GCM 中的 mac 检查失败”。
欢迎任何其他建议:-)
解决方案
推荐阅读
- visual-studio-code - 直接在远程ssh中启动vscode
- jenkins - 詹金斯:如果作业名称包含删除作业
- ios - 如何使用一个动画动画删除所有子 UIViewControllers?
- haskell - 为什么odd.fst 不能与过滤器功能一起使用?
- math - 椭圆/椭圆和基于和弦的数学
- typescript - 位置重新加载使 webpack 开发服务器崩溃 - Vue 2
- java - BigDecimal 与 JPA 和灵活的规模
- css - 为什么我在 Bootstrap 4 中的 cols flex-grow 没有对齐?
- parallel-processing - 是否可以使用本地 Browserstack 运行并行测试?
- bash - 递归地将具有特定名称的目录复制到新的位置维护结构