无法将加密的文本从 C# 传递到 C++ 和相反
Cannot pass encrypted Text from C# to C++ and opposite
我有一个包含 AES 加密的 c++ dll,该函数有两个输入:
字符串:使用 AES
加密
string : 加密输出
外部函数如下:
extern "C" __declspec(dllexport) void aes_crypter(const char* string_in , wchar_t* string_out);
void aes_crypter(const char* string_in , wchar_t* string_out)
{
std::string X_KEY = "abcdefghijklmnopqrstuvwxyz123412";
std::string X_PSS = "612345601234512";
//////// convert input text to LPCWSTR
const wchar_t* inputtext = convertCharArrayToLPCWSTR(string_in);
//////// convert LPCWSTR to string [const to string result wrong ]
std::wstring ws(inputtext);
std::string str(ws.begin(), ws.end());
//////// Encrypt
auto encr = encrypt(str, key, X_PSS);
//////// Convert and Return to Output String
std::wstring widestr = std::wstring(encr.begin(), encr.end());
const wchar_t* output_crypt = widestr.c_str(); /// CONVERT STD TO WCHAR
swprintf(string_out, 4096,output_crypt);
}
代码工作正常,问题出在我的 C# 应用程序中:
这里是导入函数代码:
[DllImport("simpleAES.dll",
CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern void aes_crypter(string string_in, StringBuilder string_out);
问题:
如果我将 CharSet 设置为 ANSI,输入字符串工作正常,在 C++ 中 returns 正确
但是输出字符串 returns 只错了一个字符 !
如果我设置字符集为UNICODE,输入字符串returns错误且只有一个字符。
但是输出字符串 returns 对 !
我哪里弄错了?我该如何解决?
std::string
和 std::wstring
无法使用 std::copy
和相关方法相互复制,除非源包含 ASCII 字符。这里不是这种情况。虽然你用的是 ASCII,但加密的文本将是二进制的,它既不是 ASCII 也不是 Unicode。
您可以将二进制的 std::wstring
复制到 std::string
。但我认为这对你没有帮助,因为 encrypt
似乎期望以 null 结尾的字符串。
相反,您可以将 UTF16 转换为 UTF8 并返回:
#include <string>
#include <codecvt>
extern "C" __declspec(dllexport)
bool aes_crypter(const wchar_t* string_in, BYTE* data, int &datalen)
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
std::string utf8 = convert.to_bytes(string_in);
std::string encr = encrypt(utf8, X_KEY, X_PSS);
datalen = encr.size();
if(datalen > 4096)
return false;
memcpy(data, &encr[0], datalen);
return true;
}
extern "C" __declspec(dllexport)
void aes_decrypter(const BYTE *data, int datalen, wchar_t* string_out)
{
std::string utf8 = decrypt(data, datalen, X_KEY, X_PSS);
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
std::wstring utf16 = convert.from_bytes(utf8);
wcscpy_s(string_out, 4096, utf16.c_str());
}
您的 C# 应用程序将收到长度为 datalen
的加密二进制文件 data
["simpleAES.dll",
CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern bool aes_crypter(string input, IntPtr data, ref int datalen);
["simpleAES.dll",
CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern bool aes_decrypter(IntPtr data, int datalen, StringBuilder sb);
static void Main(string[] args)
{
int datalen = 0;
IntPtr data = Marshal.AllocHGlobal(4096);
if (aes_crypter("1234", data, ref datalen))
{
StringBuilder sb = new StringBuilder(4096);
aes_decrypter(data, datalen, sb);
string recover = sb.ToString();
Console.WriteLine(recover);
}
Marshal.FreeHGlobal(data);
}
您还应该传递 StringBuilder
的大小,而不是假设它是 4096
请注意,在 C++ 中,c_str()
方法将查找 NUL
字符并尝试 return 以 null 结尾的字符串。但是你的加密函数创建的二进制数据中间可能有很多零。
如果加密函数接受二进制输入并输出 std::vector<BYTE>
而不是 std::string
,您可以使事情变得更容易。例子
std::vector<BYTE> encrypt(binary_data_to_encrypt, datalen, X_KEY, X_PSS);
我有一个包含 AES 加密的 c++ dll,该函数有两个输入:
字符串:使用 AES
加密
string : 加密输出
外部函数如下:
extern "C" __declspec(dllexport) void aes_crypter(const char* string_in , wchar_t* string_out);
void aes_crypter(const char* string_in , wchar_t* string_out)
{
std::string X_KEY = "abcdefghijklmnopqrstuvwxyz123412";
std::string X_PSS = "612345601234512";
//////// convert input text to LPCWSTR
const wchar_t* inputtext = convertCharArrayToLPCWSTR(string_in);
//////// convert LPCWSTR to string [const to string result wrong ]
std::wstring ws(inputtext);
std::string str(ws.begin(), ws.end());
//////// Encrypt
auto encr = encrypt(str, key, X_PSS);
//////// Convert and Return to Output String
std::wstring widestr = std::wstring(encr.begin(), encr.end());
const wchar_t* output_crypt = widestr.c_str(); /// CONVERT STD TO WCHAR
swprintf(string_out, 4096,output_crypt);
}
代码工作正常,问题出在我的 C# 应用程序中:
这里是导入函数代码:
[DllImport("simpleAES.dll",
CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern void aes_crypter(string string_in, StringBuilder string_out);
问题:
如果我将 CharSet 设置为 ANSI,输入字符串工作正常,在 C++ 中 returns 正确 但是输出字符串 returns 只错了一个字符 !
如果我设置字符集为UNICODE,输入字符串returns错误且只有一个字符。 但是输出字符串 returns 对 !
我哪里弄错了?我该如何解决?
std::string
和 std::wstring
无法使用 std::copy
和相关方法相互复制,除非源包含 ASCII 字符。这里不是这种情况。虽然你用的是 ASCII,但加密的文本将是二进制的,它既不是 ASCII 也不是 Unicode。
您可以将二进制的 std::wstring
复制到 std::string
。但我认为这对你没有帮助,因为 encrypt
似乎期望以 null 结尾的字符串。
相反,您可以将 UTF16 转换为 UTF8 并返回:
#include <string>
#include <codecvt>
extern "C" __declspec(dllexport)
bool aes_crypter(const wchar_t* string_in, BYTE* data, int &datalen)
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
std::string utf8 = convert.to_bytes(string_in);
std::string encr = encrypt(utf8, X_KEY, X_PSS);
datalen = encr.size();
if(datalen > 4096)
return false;
memcpy(data, &encr[0], datalen);
return true;
}
extern "C" __declspec(dllexport)
void aes_decrypter(const BYTE *data, int datalen, wchar_t* string_out)
{
std::string utf8 = decrypt(data, datalen, X_KEY, X_PSS);
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
std::wstring utf16 = convert.from_bytes(utf8);
wcscpy_s(string_out, 4096, utf16.c_str());
}
您的 C# 应用程序将收到长度为 datalen
data
["simpleAES.dll",
CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern bool aes_crypter(string input, IntPtr data, ref int datalen);
["simpleAES.dll",
CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern bool aes_decrypter(IntPtr data, int datalen, StringBuilder sb);
static void Main(string[] args)
{
int datalen = 0;
IntPtr data = Marshal.AllocHGlobal(4096);
if (aes_crypter("1234", data, ref datalen))
{
StringBuilder sb = new StringBuilder(4096);
aes_decrypter(data, datalen, sb);
string recover = sb.ToString();
Console.WriteLine(recover);
}
Marshal.FreeHGlobal(data);
}
您还应该传递 StringBuilder
的大小,而不是假设它是 4096
请注意,在 C++ 中,c_str()
方法将查找 NUL
字符并尝试 return 以 null 结尾的字符串。但是你的加密函数创建的二进制数据中间可能有很多零。
如果加密函数接受二进制输入并输出 std::vector<BYTE>
而不是 std::string
,您可以使事情变得更容易。例子
std::vector<BYTE> encrypt(binary_data_to_encrypt, datalen, X_KEY, X_PSS);