c# - C++ 和 C# 与 Crypto 之间加密的互操作性

标签 c# c++ qt encryption aes

我正在尝试在 Qt 项目中使用 Crypto++ 库在 C++ 中加密字符串,并在 Web 应用程序中在 C# 中解密该字符串。这是我的代码。

C++ 代码,使用 Crypto++ 库

std::string Crypter::encrypt(const std::string& str_in, const std::string& key, const std::string& iv)
{
    std::string str_out;
    CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption encryption((byte*)key.c_str(), key.length(), (byte*)iv.c_str());
    qDebug() << encryption.DefaultKeyLength();
    qDebug() << encryption.DefaultIVLength();


    CryptoPP::StringSource encryptor(str_in, true,
        new CryptoPP::StreamTransformationFilter(encryption,
            new CryptoPP::Base64Encoder(
                new CryptoPP::StringSink(str_out),
                false // do not append a newline
            )
        )
    );
    return str_out;
}

在这里调用函数

std::string str = "123456789012345";
std::string key = "01234567891234560123456789123456"; // 32 bytes
std::string iv  = "0123456789123456"; // 16 bytes
std::string str_encrypted = c->encrypt(str, key, iv);
std::string str_decrypted = c->decrypt(str_encrypted, key, iv);
std::cout << "str_encrypted: " << str_encrypted << std::endl;
std::cout << "str_decrypted: " << str_decrypted << std::endl;

这段代码产生如下结果

Plain text: "123456789012345"
Encrypted value (base64): 3Qo/6hWctRiID3txA9nC

我在这里用 C# 编写了相同的代码

    private void button1_Click(object sender, EventArgs e)
    {
        string strOutput = Encrypt("123456789012345");
        Debug.WriteLine("Encrypted value is: " + strOutput);
    }

   private string Encrypt(string clearText)
    {
        byte[] clearBytes = Encoding.ASCII.GetBytes(clearText + "\0");

        using (Aes encryptor =  Aes.Create("AES"))
        {
            encryptor.BlockSize = 128;
            encryptor.KeySize = 128;
            encryptor.Mode = CipherMode.CFB;
            encryptor.Key = Encoding.ASCII.GetBytes("01234567891234560123456789123456");
            encryptor.IV = Encoding.ASCII.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();
                clearText = Convert.ToBase64String(bt);
            }
        }
        return clearText;
    }

产生以下结果

Encrypted value is: 3YklwM2vG20ZmkOT029jTTL7FlSZHrh0RfvaT1FFa2k=

有人可以告诉我我错过了什么吗?从两种语言获得相似输出的正确方法是什么。

我的目标是在 C++ 中加密一个值并在 C# 中解密该值。

编辑

我做了一些改变。

将 Hello world 替换为 123456789012345 将编码从 utf 更改为 Ascii 在 C# 字符串的末尾添加了一个空字节 改变模式为CFB

我也用新结果编辑了原始结果

不幸的是,同样这样做之后,两个字符串都不匹配。

我已确保两个输入相同。

最佳答案

您的 C++ 代码是根据 std::string 编写的。这很可能是保存在 ANSI 代码页下编码的文本。当您将它传递给 CryptoPP::StringSource 时,我希望它直接处理该文本的字节,而无需将其转换为任何其他编码。

您的 C# 正在传递 Encoding.Unicode.GetBytes 的结果。这意味着加密是针对 UTF-16 编码数据的字节进行的。

由于编码不同,字节表示也不同。那么由于字节不同,加密后的结果也不同。

您需要让两段代码在同一方案下工作。

如果您只想处理 ANSI(或什至只是 ASCII)字符(给定您的 C++ 代码可能就是这种情况),那么您可以修改 C# 代码以使用 Encoding.Default.GetBytes(或者可能是 Encoding.ASCII.GetBytes)以获取明文的字节。


编辑

进一步看,您的 C++ 代码使用 CryptoPP::CFB_Mode,而您的 C# 代码使用 encryptor.Mode = CipherMode.CBC;。这些模式需要匹配,否则算法将以不同方式应用。

您可能需要检查其他属性,例如填充,以确保两者在同一方案下工作。

关于c# - C++ 和 C# 与 Crypto 之间加密的互操作性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24214716/

相关文章:

c# - 使用 BindIPEndPointDelegate 指定源端口似乎不起作用

c++ - 如何在 C++ 中对派生类使用 Boost 序列化?

c# - WPF 是 100 倍或比普通 Windows 窗体慢的东西是正常的吗?

c# - 使用反射获取基类的 protected 属性值

c# - 换行符未在文本框中正确显示

c++ - 在 Mac OS Catalina 中编译 hadoop 原生库。错误 : unknown type name 'constexpr' . 别名声明是 C++11 扩展

c++ - 如何处理带有指针的 map ?

c++ - MSVC QT Creator - 如何正确设置 CDB?

QTextEdit 或 QTextBrowser 性能问题

qt - windeployqt 模块 QtQuick 未安装