微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C++crypto++和C#加密匹配

如何解决C++crypto++和C#加密匹配

为了客户端和服务器之间的安全通信,我想对来自客户端和服务器的数据进行加密和解密,但我无法得到相同的结果,从客户端到服务器的数据没有被解密,同样当对来自服务器的相同数据进行加密,我从客户端的加密中得到了独特的结果。

客户端使用 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& iv)
{
    try {
        string str_out;
        CBC_Mode<AES>::Decryption decryption((byte*)key.c_str(),key.length(),(byte*)iv.c_str());
 
        StringSource decryptor(str_in,new Base64Decoder(
                new StreamTransformationFilter(decryption,new StringSink(str_out)
                )
            )
        );
 
        return str_out;
    }
    catch (exception e) {
        return "null";
    }
}

给出以下输出

data: "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,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(),clearBytes.Length);
                cs.Close();
            }
            byte[] bt = ms.ToArray();
            input = Encoding.ASCII.GetString(bt);
        }
    }
    return input;
}

输出

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

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

解决方法

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

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

  • Encrypt()Decrypt() 方法中使用不同的键。 Decrypt() 方法的键与 C++ 代码中应用的键匹配。比较两个代码的密文,应该替换Encrypt()方法中的key。
  • 密文在 Encrypt() 方法中是 Base64 编码的,但在 Decrypt() 方法中不是 Base64 解码(而是 ASCII 编码)。这里必须在 Decrypt() 方法中进行 Base64 解码(请注意,Encrypt() 方法中的 ASCII 解码不是替代方法,因为这会破坏密文)。

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

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。