从C#调用时从CFB模式截断的输出 [英] Truncated output from CFB mode when calling from C#

查看:275
本文介绍了从C#调用时从CFB模式截断的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个很讨厌的问题,我无法解决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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆