从C#调用时从CFB模式截断的输出 [英] Truncated output from CFB mode when calling from C#
问题描述
我有一个很讨厌的问题,我无法解决2天。我有一个 encrypt()
方法,使用C ++编写的Crypto ++库。该方法实现如下:
string CRijndaelHelper :: Encrypt(string text)
{
CFB_Mode< ; AES> ::加密e;
e.SetKeyWithIV(_key,sizeof(_key),_iv);
string cipher,encoded;
// CFB模式不能使用填充。指定
//一个方案将导致一个异常
StringSource ss(text,true,
new StreamTransformationFilter(e,
new StringSink(cipher)
)
return cipher;
};
当我在本地环境中调用这个方法时,它完美地工作,加密整个26Kb xml字符串,问题。
最后,我不得不在C#代码中实现加密,为此我在native dll中编写了下面的包装代码,以供以后使用PInvoke:
externC
API_EXPORT char * _cdecl encrypt(char * contents)
{
string cont(contents);
CRijndaelHelper rij;
string transformedText = rij.Encrypt(cont);
return marshalReturn(transformedText);
}
PInvoke部分如下:
[DllImport(EncryptDecrypt.dll,CharSet = CharSet.Auto,CallingConvention = CallingConvention.Cdecl)]
[return:MarshalAs(UnmanagedType.LPStr )]
public static extern string encrypt([MarshalAs(UnmanagedType.LPStr)] string contents);
并且一切看起来工作完美,除了我在 transformedText
变量只有第一个540字节加密,这是所有。
请指教。
...返回一个从本地代码调用时正确加密的字符串
问题不是C ++ encrypt
,它使用 std :: string
。问题是将它回归到托管代码作为 char *
。
更改 CRijndaelHelper :: Encrypt
到以下内容以删除嵌入的 NULL
,它将以1/255的概率自由地散布:
#include< cryptopp / base64.h>
使用CryptoPP :: Base64Encoder;
...
string CRijndaelHelper :: Encrypt(string text)
{
CFB_Mode< AES> :: Encryption e;
e.SetKeyWithIV(_key,sizeof(_key),_iv);
string cipher,encoded;
// CFB模式不能使用填充。指定
//方案将导致异常
StringSource ss(text,true,
new StreamTransformationFilter(e,
new Base64Encoder(
new StringSink
)));
return cipher;
};
使用 Base64
编码, a char *
将不截断遇到的第一个 NULL
字节的加密结果。 / p>
然后,对于解密:
StringSource ss(cipher,true,
new Base64Decoder(
new StreamTransformationFilter(d,
new StringSink(text)
)));
I have pretty annoying issue which I'm unable to solve for 2 days. I have an encrypt()
method which makes use of Crypto++ library written in C++. The method is implemented as follows:
string CRijndaelHelper::Encrypt(string text)
{
CFB_Mode< AES >::Encryption e;
e.SetKeyWithIV(_key, sizeof(_key), _iv);
string cipher, encoded;
// CFB mode must not use padding. Specifying
// a scheme will result in an exception
StringSource ss(text, true,
new StreamTransformationFilter(e,
new StringSink(cipher)
));
return cipher;
};
When I call this method within the native environment it works perfectly, encrypting the whole 26Kb xml string without any problem.
Eventually I've had to implement the encryption in C# code, for that purpose I wrote the following wrapper code in native dll for later use with PInvoke:
extern "C"
API_EXPORT char* _cdecl encrypt(char* contents)
{
string cont(contents);
CRijndaelHelper rij;
string transformedText = rij.Encrypt(cont);
return marshalReturn(transformedText);
}
While the PInvoke part looks as follows:
[DllImport("EncryptDecrypt.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string encrypt([MarshalAs(UnmanagedType.LPStr)] string contents);
And everything looks working perfect except that I get in transformedText
variable only first 540 bytes encrypted and that's all.
Please advise.
... returns a string which is correctly encrypted when invoked from native code
The problem is not you C++ encrypt
, which uses a std::string
. The problem is with marshalling it back to managed code as a char*
.
Change CRijndaelHelper::Encrypt
to the following to remove the embedded NULL
that will be sprinkled liberally with a probability of 1/255:
#include <cryptopp/base64.h>
using CryptoPP::Base64Encoder;
...
string CRijndaelHelper::Encrypt(string text)
{
CFB_Mode< AES >::Encryption e;
e.SetKeyWithIV(_key, sizeof(_key), _iv);
string cipher, encoded;
// CFB mode must not use padding. Specifying
// a scheme will result in an exception
StringSource ss(text, true,
new StreamTransformationFilter(e,
new Base64Encoder(
new StringSink(cipher)
)));
return cipher;
};
With the Base64
encoding, the marshaling as a char*
will not truncate the encryption results on the first NULL
byte encountered.
Then, for decryption:
StringSource ss(cipher, true,
new Base64Decoder(
new StreamTransformationFilter(d,
new StringSink(text)
)));
这篇关于从C#调用时从CFB模式截断的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!