winforms 使用C# AES加密解密期间MAC验证失败

olhwl3o2  于 2023-08-07  发布在  C#
关注(0)|答案(1)|浏览(186)

我在使用AES加密和MAC验证的C#应用程序中遇到了加密和解密过程的问题。加密似乎工作正常,但当我试图解密数据时,我遇到了“MAC验证失败”。数据完整性受损”错误。

  1. using System;
  2. using System.IO;
  3. using System.Security.Cryptography;
  4. using System.Text;
  5. namespace HellsgateDeveloperManager
  6. {
  7. public static class EncryptionManager
  8. {
  9. private const string encryptionKey = "MyEncryptionKey";
  10. public static byte[] EncryptWithIntegrity(string plaintext)
  11. {
  12. byte[] iv = GenerateRandomBytes(16);
  13. byte[] plaintextBytes = Encoding.UTF8.GetBytes(plaintext);
  14. // Calculate the MAC over the plaintext data
  15. byte[] mac = CalculateMAC(plaintextBytes, encryptionKey);
  16. using (Aes aesAlg = Aes.Create())
  17. {
  18. aesAlg.Key = Encoding.UTF8.GetBytes(encryptionKey);
  19. aesAlg.IV = iv;
  20. ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
  21. byte[] encryptedData;
  22. using (MemoryStream msEncrypt = new MemoryStream())
  23. {
  24. using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
  25. {
  26. csEncrypt.Write(plaintextBytes, 0, plaintextBytes.Length);
  27. }
  28. encryptedData = msEncrypt.ToArray();
  29. }
  30. byte[] encryptedDataWithMAC = new byte[iv.Length + encryptedData.Length + mac.Length];
  31. Buffer.BlockCopy(iv, 0, encryptedDataWithMAC, 0, iv.Length);
  32. Buffer.BlockCopy(encryptedData, 0, encryptedDataWithMAC, iv.Length, encryptedData.Length);
  33. Buffer.BlockCopy(mac, 0, encryptedDataWithMAC, iv.Length + encryptedData.Length, mac.Length);
  34. return encryptedDataWithMAC;
  35. }
  36. }
  37. public static string DecryptWithIntegrity(byte[] encryptedDataWithMAC)
  38. {
  39. int ivLength = 16;
  40. int macLength = 32;
  41. int expectedMinLength = ivLength + macLength;
  42. if (encryptedDataWithMAC == null || encryptedDataWithMAC.Length < expectedMinLength)
  43. {
  44. throw new ArgumentException("Invalid encrypted data format.");
  45. }
  46. byte[] iv = new byte[ivLength];
  47. byte[] encryptedData = new byte[encryptedDataWithMAC.Length - ivLength - macLength];
  48. byte[] receivedMAC = new byte[macLength];
  49. Buffer.BlockCopy(encryptedDataWithMAC, 0, iv, 0, iv.Length);
  50. Buffer.BlockCopy(encryptedDataWithMAC, iv.Length, encryptedData, 0, encryptedData.Length);
  51. Buffer.BlockCopy(encryptedDataWithMAC, iv.Length + encryptedData.Length, receivedMAC, 0, receivedMAC.Length);
  52. byte[] calculatedMAC = CalculateMAC(encryptedData, encryptionKey);
  53. if (!CompareMACs(receivedMAC, calculatedMAC))
  54. {
  55. throw new CryptographicException("MAC verification failed. Data integrity compromised.");
  56. }
  57. using (Aes aesAlg = Aes.Create())
  58. {
  59. aesAlg.Key = Encoding.UTF8.GetBytes(encryptionKey);
  60. aesAlg.IV = iv;
  61. ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
  62. using (MemoryStream msDecrypt = new MemoryStream(encryptedData))
  63. {
  64. using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
  65. {
  66. using (StreamReader srDecrypt = new StreamReader(csDecrypt))
  67. {
  68. return srDecrypt.ReadToEnd();
  69. }
  70. }
  71. }
  72. }
  73. }
  74. private static byte[] CalculateMAC(byte[] data, string key)
  75. {
  76. byte[] keyBytes = Encoding.UTF8.GetBytes(key);
  77. using (HMACSHA256 hmac = new HMACSHA256(keyBytes))
  78. {
  79. return hmac.ComputeHash(data);
  80. }
  81. }
  82. private static bool CompareMACs(byte[] mac1, byte[] mac2)
  83. {
  84. if (mac1.Length != mac2.Length)
  85. {
  86. return false;
  87. }
  88. for (int i = 0; i < mac1.Length; i++)
  89. {
  90. if (mac1[i] != mac2[i])
  91. {
  92. return false;
  93. }
  94. }
  95. return true;
  96. }
  97. private static byte[] GenerateRandomBytes(int length)
  98. {
  99. byte[] randomBytes = new byte[length];
  100. using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
  101. {
  102. rng.GetBytes(randomBytes);
  103. }
  104. return randomBytes;
  105. }
  106. }
  107. }

字符串
每当我尝试比较MAC时,就会出现错误。
我将非常感谢任何见解,建议或可能的解决方案,以帮助我解决这个问题。如果任何人在使用C# AES加密和MAC验证时遇到类似的问题,或者如果我可以采取任何其他故障排除步骤,请告诉我。提前感谢您的帮助!
为了调试这个问题,我仔细检查了加密代码,包括IV的生成和MAC。我还检查了加密和解密使用的密钥是否相同。我实施了大量的日志记录来跟踪过程中的数据和密钥,但我无法确定任何差异。我尝试使用Chat-gpt来获得一些指导,但没有进一步的帮助。

hmtdttj4

hmtdttj41#

您正在计算加密明文的MAC,并且正在计算解密密文 * 的MAC *。最好转换为使用encrypt-then-mac。这基本上就是你在解密过程中所做的。如果你这样做,你应该确保将IV包括在计算中。
就目前而言,您应该知道发送相同的消息将导致加密期间相同的MAC,这意味着有关消息的少量信息将被泄露。更糟糕的是,在解密过程中,你可能容易受到填充oracle攻击。
还有其他安全问题,例如使用字符串来构成密钥,使用依赖于静态密钥的静态方法,用于认证标签(MAC结果)的非时间常数比较。也许你可以使用GCM来代替,这样大部分问题都可以很容易地解决。
即使这样,你也应该担心你的协议是否安全,是否容易受到例如重播攻击这就是为什么,你最好不要尝试创建自己的。

相关问题