AES加密-相同密钥和IV的不同加密值

时间:2018-06-19 18:44:18

标签: c# asp.net encryption xamarin.ios

我在理解这里发生的事情时遇到了一些麻烦。我是加密世界的新手,尝试通过HTTP(以JSON字符串发送)传输用户名和密码之前对其进行加密,然后在另一端将其解密。

我有一个类可以用作AES的简单实现(带有硬编码的密钥/ 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)中,我有一个包含SimpleAES类的类库(针对.NET Standard 2.0)。该类还存在于驱动我的Xamarin.iOS应用程序的类库中,该应用程序使用针对iOS 11的最新稳定版本的Xamarin.iOS构建。

在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==

为什么这些值不同?我的理解是,使用相同的密钥,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的问题吗?我很茫然,不想使用此解决方案。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:3)

调用<string-array name="arraypowerunit" translatable="false"> <item>@string/array_power_unit_item_00</item> <item>@string/array_power_unit_item_01</item> <item>@string/array_power_unit_item_02</item> <item>@string/array_power_unit_item_03</item> </string-array> 之后,ICryptoTransform的实现不一定是可重用的(TransformFinalBlock关闭时会自动发生)。在创建具有相同变换的另一个CryptoStream之前,应先检查CanReuseTransform属性。

除了,正如刚刚提到的另一条评论所述,该框架的某些版本中存在一个错误,其中某些实现未为CryptoStream返回正确的值。为了安全起见,您可能希望每次都重新创建对象。