c# - AES 加密 - 使用相同 key 和 IV 的不同加密值

标签 c# asp.net encryption xamarin.ios

我无法理解这里发生的事情。我是加密世界的新手,尝试在通过 HTTP 传输用户名和密码(以 JSON 字符串形式发送)之前对用户名和密码进行加密,并在另一端对其进行解密。

我有一个类,用作 AES 的简单实现(带有硬编码 key /iv):

public class SimpleAES
{
    private byte[] key = { 32, 128, 16, 11, 28, 36, 45, 15, 214, 184, 17, 244, 27, 142, 252, 119, 111, 84, 125, 244, 123, 93, 126, 39, 44, 76, 87, 118, 231, 136, 43, 109 };
    private byte[] vector = { 246, 164, 231, 211, 32, 8, 64, 128, 211, 221, 132, 242, 122, 123, 129, 254 };
    private ICryptoTransform encryptor, decryptor;
    private UTF8Encoding encoder;

    public SimpleAES()
    {
        //return;
        RijndaelManaged rm = new RijndaelManaged();
        encryptor = rm.CreateEncryptor(key, vector);
        decryptor = rm.CreateDecryptor(key, vector);
        encoder = new UTF8Encoding();
    }

    public string Encrypt(string unencrypted)
    {
        //return unencrypted;
        return Convert.ToBase64String(Encrypt(encoder.GetBytes(unencrypted)));
    }

    public string Decrypt(string encrypted)
    {
        //return encrypted;
        return encoder.GetString(Decrypt(Convert.FromBase64String(encrypted)));
    }

    public byte[] Encrypt(byte[] buffer)
    {
        return Transform(buffer, encryptor);
    }

    public byte[] Decrypt(byte[] buffer)
    {
        return Transform(buffer, decryptor);
    }

    protected byte[] Transform(byte[] buffer, ICryptoTransform transform)
    {
        MemoryStream stream = new MemoryStream();
        using( CryptoStream cs = new CryptoStream(stream, transform, CryptoStreamMode.Write) )
        {
            cs.Write(buffer, 0, buffer.Length);
        }
        return stream.ToArray();
    }
}

在我的 ASP.NET Core Web API(针对 Microsoft.AspNetCore 2.1.0)中,我有一个类库(针对 .NET Standard 2.0),其中包含我的 SimpleAES 类。该类也存在于驱动我的 Xamarin.iOS 应用程序的类库中,该应用程序是使用最新稳定版本的 Xamarin.iOS 构建的,面向 iOS 11。

在 ASP.NET Core Web API 中,这是以下语句产生的结果(bs 是 SimpleAES 对象):

bs.Encrypt("testuser") --> dgIoOZ5UKsI2isPIbqXFNA==

bs.Encrypt("testpass") --> MZI72tKGu9VPIhF6vXoN4A==

bs.Encrypt("testuser72") --> gpzPtU6pTc6vuvpIaiwb1w==

bs.Encrypt("testpass1946") --> E3hamfb+u3AQ1Ip6KhC1gg==

在 Xamarin.iOS 应用程序中,以下是完全相同的语句产生的结果:

bs.Encrypt("testuser") --> dgIoOZ5UKsI2isPIbqXFNA==

bs.Encrypt("testpass") --> RCXKi1sGI1N/uiSNBI1JLA==

bs.Encrypt("testuser72") --> 7JVjuO3JNtKffSJCQ/Vndg==

bs.Encrypt("testpass1946") --> BROGP9AUByLcYFVtXS9FMg==

为什么这些值不同?我的理解是,使用相同的 key 、IV、模式和其他设置属性,AES 加密输出在任何给定字符串的任何实现中都是相同的。

此外,如果我更改 iOS 应用程序中的语句以每次创建一个新的 SimpleAES 对象,则加密输出正确地与我的 ASP.NET Core Web API 加密输出相同 .

对我来说,解决方案(不是一个好的解决方案,也不是我想要的解决方案)是这样做:

bs.Encrypt("testuser") --> dgIoOZ5UKsI2isPIbqXFNA==

bs = new SimpleAES();

bs.Encrypt("testpass") --> MZI72tKGu9VPIhF6vXoN4A==

bs = new SimpleAES();

bs.Encrypt("testuser72") --> gpzPtU6pTc6vuvpIaiwb1w==

bs = new SimpleAES();

bs.Encrypt("testpass1946") --> E3hamfb+u3AQ1Ip6KhC1gg==

这会产生正确的加密。在 ASP.NET Core Web API 上的每次加密之间创建一个新的 SimpleAES 对象不会执行任何操作,并且值保持完全相同。

有谁知道为什么这会在 Xamarin.iOS 上以这种方式表现?也许是垃圾收集问题?代码中是否存在 Xamarin.iOS 特有的问题?我只是不知所措,不想使用这个解决方案。

任何帮助将不胜感激。

最佳答案

调用 TransformFinalBlock 后,ICryptoTransform 的实现不一定可重用(这在 CryptoStream 关闭时自动发生)。在使用相同的转换创建另一个 CryptoStream 之前,您应该检查 CanReuseTransform 属性。

异常(exception),正如另一条评论刚刚提到的,框架的某些版本中存在一个错误,即某些实现不会为 CanReuseTransform 返回正确的值。为了安全起见,您可能希望每次都重新创建该对象。

关于c# - AES 加密 - 使用相同 key 和 IV 的不同加密值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50935070/

相关文章:

java - 如何用纯Java创建或打开libsodium兼容的密封盒

c# - 将 2 个变量链接到一个对象

asp.net - 为什么这被认为是不好的做法?或者是吗? (ASP.NET)

c# - 如何从按钮中删除禁用属性?

c# - 在工具提示中使用 <br/> 并更改工具提示的默认颜色

security - 64 位 RC2 的安全性如何?

.net - RijndaelManaged "Padding is invalid and cannot be removed"仅在生产中解密时发生

c# - 在 Silverlight 中生成类似 UML 的框图

c# - 来自 Windows 服务的屏幕截图

c# - 泛型类型值和 '==' 关键字的 'default' 运算符的行为是什么?