c# - C++ (crypto++) 和 C# 加密匹配

标签 c# c++ asp.net-core encryption crypto++

为了客户端和服务器之间的安全通信,我想对来自客户端和服务器的数据进行加密和解密,但我无法得到相同的结果,从客户端到服务器的数据未解密,当对来自服务器的相同数据进行加密,我在客户端上加密得到了不同的结果。

客户端是使用 Crypto++ 用 C++ 编写的。代码:

string data = "teststring,teststring,teststring";
string encryptedData = client.encrypt(userData, "01234567891234560123456789123456", "0123456789123456");
string Client::encrypt(const string& str_in, const string& key, const string& iv)
{
    try {
        string str_out;
 
        AES::Encryption aesEncryption((byte*)key.c_str(), key.length());
        CBC_Mode_ExternalCipher::Encryption encryption(aesEncryption, (byte*)iv.c_str());
 
        StringSource encryptor(str_in, true,
            new StreamTransformationFilter(encryption,
                new Base64Encoder(
                    new StringSink(str_out),
                    false
                )
            )
        );
        return str_out;
    }
    catch (exception e) {
        return "null";
    }
}
string Client::decrypt(const string& str_in, const string& key, const string& iv)
{
    try {
        string str_out;
        CBC_Mode<AES>::Decryption decryption((byte*)key.c_str(), key.length(), (byte*)iv.c_str());
 
        StringSource decryptor(str_in, true,
            new Base64Decoder(
                new StreamTransformationFilter(decryption,
                    new StringSink(str_out)
                )
            )
        );
 
        return str_out;
    }
    catch (exception e) {
        return "null";
    }
}

给出以下输出:

data: "teststring,teststring,teststring"
encryptedData: "STpuD/dRgYard+Yqpdd5KOYET7607i7ZRUoKm5eshHzR3ErafaxgZ2+T1tSp0lWJ"

服务器端代码是用C#(ASP.NET Core 3.1)编写的:

public static string Encrypt(string input)
{
    byte[] clearBytes = Encoding.Default.GetBytes(input);
 
    using (Aes encryptor = Aes.Create("AES"))
    {
        // encryptor.BlockSize = 32;
        encryptor.Padding = PaddingMode.Zeros;
        encryptor.KeySize = 128;
        encryptor.Mode = CipherMode.CBC;
        encryptor.Key = Encoding.Default.GetBytes("01286567891233460123456789123456");
        encryptor.IV = Encoding.Default.GetBytes("0123456789123456");
        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
            {
                cs.Write(clearBytes, 0, clearBytes.Length);
                cs.Close();
            }
            byte[] bt = ms.ToArray();
            input = Convert.ToBase64String(bt);
        }
    }
    return input;
}
 
public static string Decrypt(string input)
{
    byte[] clearBytes = Encoding.ASCII.GetBytes(input);
 
    using (Aes decryptor = Aes.Create("AES"))
    {
        //decryptor.BlockSize = 32;
        decryptor.Padding = PaddingMode.Zeros;
        decryptor.KeySize = 128;
        decryptor.Mode = CipherMode.CBC;
        decryptor.Key = Encoding.ASCII.GetBytes("01234567891234560123456789123456");
        decryptor.IV = Encoding.ASCII.GetBytes("0123456789123456");
        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, decryptor.CreateDecryptor(), CryptoStreamMode.Write))
            {
                cs.Write(clearBytes, 0, clearBytes.Length);
                cs.Close();
            }
            byte[] bt = ms.ToArray();
            input = Encoding.ASCII.GetString(bt);
        }
    }
    return input;
}

输出:

data: "teststring,teststring,teststring"
encryptedData: "tIDlWnnzOQWh5HIvRDJya6z7jOglkIlYrICeYW9RoEM="

我无法解密来自客户端和服务器的数据。请帮助我。

最佳答案

发布的 C++ 代码很好。它会在我的机器上返回发布的密文 STpu...0lWJ,并且可以使用 decrypt() 方法对密文进行解密。

相比之下,虽然发布的 C# 代码返回发布的密文 tIDl...RoEM=,但密文无法使用 Decrypt() 方法解密。这有两个原因:

  • Encrypt()Decrypt() 方法中使用不同的 key 。 Decrypt() 方法的 key 与 C++ 代码中应用的 key 匹配。对比两种代码的密文,需要更换Encrypt()方法中的 key 。
  • 密文在 Encrypt() 方法中进行 Base64 编码,但在 Decrypt() 方法中未进行 Base64 解码(而是采用 ASCII 编码)。这里必须在 Decrypt() 方法中完成 Base64 解码(请注意,Encrypt() 方法中的 ASCII 解码不是替代方案,因为这会损坏密文)。

如果修复了这两个错误,C++ 和 C# 代码的密文除了末尾之外都会匹配。最后一个不匹配是由不同的填充引起的。在C++代码中使用PKCS7填充,在C#代码中使用零填充。如果 C# 代码中的填充(在 Encrypt()Decrypt() 方法中)更改为 PaddingMode.PKCS7,则密文匹配.

C# 代码中的其他问题是:

  • Encrypt()方法中使用Encoding.Default,在Decrypt()方法中使用Encoding.ASCII.这里是一致的编码,例如应应用 Encoding.UTF8
  • 指定的 128 位 key 大小与使用的 256 位 key 不一致。这没有任何效果,因为显式 key 规范会自动更正 key 大小(尽管如此,应正确指定 key 大小或完全省略 key 大小)。

另外,应该注意的是,静态 IV 是不安全的(当然,出于测试目的,这没关系)。

关于c# - C++ (crypto++) 和 C# 加密匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67575980/

相关文章:

localization - 了解 MVC6 RC1 中的资源文件

c# - 回到程序的开始

c# - 为什么 SqlDataReader to DataTable 只有在我使用单独的字段时才有效?

c++ - 可以将 CWinApp 放在 DLL 中吗?

c++ - 将多种数据类型写入文件时的额外行和额外数组元素

c# - Asp.Net Core Web 应用程序静态文件在 Linux 上给出 404

c# - 从 Xamarin 可移植类库发送 Http 请求

c# - 自动展开 RadGridView 新增行的 RowDetails

C++ vector<T>::迭代器运算符 +

c# - 从 Visual Studio 2017 中的其他解决方案引用项目