CFB模式下的TripleDES,C#和Crypto ++不同 [英] TripleDES in CFB mode, C# and Crypto++ differs

查看:141
本文介绍了CFB模式下的TripleDES,C#和Crypto ++不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的问题:我在C ++中有一个遗留代码(使用crypto ++ v5.6.1),并且在C#中开发了一个新代码(使用System.Security.Cryptography的.NET 3.5).我无法更改,但是我需要能够解密以前加密的数据,并且以前的应用程序必须能够解密将使用新的C#代码加密的数据.

Here is my problem: I've got a legacy code in C++ (using crypto++ v5.6.1) and I develop a new one in C# (.NET 3.5 using System.Security.Cryptography). I can't change the C++ code, but I need to be able to decrypt data previously encrypted and previous applications has to be able to decrypt the data I will crypt with my new C# code.

在两种情况下,使用的算法都是具有CFB密码模式的TripleDES,但最后,加密的数据不相同,字节数与第一个字节相同,但除此之外,其他所有字节均相同.不同.

The algorithm used is TripleDES with CFB cipher mode in both cases, but in the end, the encrypted data are not the same, the number of bytes are identical as well as the first byte, but apart from that all other bytes are different.

在C ++代码中,填充是手动完成的(添加零).因此,我将PaddingValue设置为PaddingMode.Zeros. (我还尝试在C#代码中最后手动添加零,它没有改变任何内容.)

The padding is manually done (adding zeros) in the C++ code. So I set the PaddingValue to PaddingMode.Zeros. (I also tried to add zeros in the end manually in the C# code, it didn't change anything).

我尝试使用不同的System.Text.Encoding,但是结果是相同的(实际上,测试的字符是纯" ASCII(即:0到126之间)).

I tried using different System.Text.Encoding but the result is the same (in fact the tested characters are "pure" ASCII (i.e.: between 0 & 126)).

在C ++代码中,MandatoryBlockSize()的值为8,所以我也将FeedbackSize设置为8.但是,如果我理解的话,它实际上就是我的静脉注射的大小,不是吗?

The value of the MandatoryBlockSize(), in the C++ code, is 8, so I set the FeedbackSize to 8 too. But if I understand it write, it is in fact the size of my IV, isn't it ?

密钥大小为24个字节(3个不同的密钥),IV的长度为8个字节.它们在2个代码中都是相同的.

The key size is 24 bytes (3 different keys) and the IV is 8 bytes long. They are both the same in the 2 codes.

如果我在两种情况下都使用CBC模式,则结果是相同的(但是,正如我所说,我无法更改旧版代码...),OFB& CTS模式在.NET应用程序上引发异常(一个不可用,而另一个不兼容),所以我无法比较结果.

If I use CBC mode instead in both cases the results are the same (but, as I said, I can't change the legacy code ...), OFB & CTS mode throw exceptions (unavailable for one and incompatible for the other) on my .NET application, so I can't compare results.

我尝试将Mono与.Net 3.5及更高版本一起使用. .Net 3.5或4.0或4.0,或使用Visual,则4个加密结果相同,但与原始结果不同.

I tried using Mono, with .Net versions 3.5 & 4.0, or using visual, with .Net 3.5 or 4.0, and the 4 encrypted results are the same but it differs from the original result.

现在我真的不知道要测试什么...我宁愿不将Crypto ++包装在C ++/CLI项目中以代替System.Security.Cryptography使用它.

Now I really don't know what to test ... I'd rather not wrap Crypto++ in a C++/CLI project to use it instead of the System.Security.Cryptography.

有人建议或可以告诉我我做错了什么吗?

Does someone have an advice or can tell what am I doing wrong ?

这是C ++代码:

void *CryptData(BYTE *bDataIn, LONG lIn, LONG *lOut, byte* key, byte* iv)
{
    byte    *bIn;
    byte    *bOut;
    LONG    l2,lb;

    CFB_FIPS_Mode<DES_EDE3>::Encryption encryption_DES_EDE3_CFB;
    encryption_DES_EDE3_CFB.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));

    lb = encryption_DES_EDE3_CFB.MandatoryBlockSize();
    l2 = ((lIn + lb - 1)/lb)*lb;

    bIn = (byte*)malloc(l2);
    bOut = (byte*)malloc(l2);

    memset(bIn,0,l2);
    memset(bOut,0,l2);
    memcpy(bIn,bDataIn,lIn);

    encryption_DES_EDE3_CFB.ProcessString(bOut, bIn, l2);

    *lOut = l2;

    return bOut;
}

这是C#代码:

public FibxCrypt()
{
    _cryptoAlgo = new TripleDESCryptoServiceProvider();
    //_cryptoAlgo.GenerateKey();
    _cryptoAlgo.Key = _key;
    //_cryptoAlgo.GenerateIV();
    _cryptoAlgo.IV = _iv;
    _cryptoAlgo.Mode = CipherMode.CFB;
    _cryptoAlgo.Padding = PaddingMode.Zeros;

    _encoding = new UTF8Encoding();
}

private MemoryStream EncryptingString(string plainText, out long encryptSize)
{
    // Check arguments. 
    if (plainText == null || plainText.Length <= 0)
        throw new ArgumentNullException("plainText");

    // Create a decrytor to perform the stream transform.
    ICryptoTransform encryptor = _cryptoAlgo.CreateEncryptor();

    // Create the streams used for encryption. 
    //using (MemoryStream msEncrypt = new MemoryStream())
    MemoryStream msEncrypt = new MemoryStream();

    encryptSize = ((plainText.Length + _cryptoAlgo.FeedbackSize - 1) / _cryptoAlgo.FeedbackSize) * _cryptoAlgo.FeedbackSize;

    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
    {
        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt, _encoding))
        {
            //Write all data to the stream.
            swEncrypt.Write(plainText);
        }
    }

    // Return the encrypted memory stream. 
    return msEncrypt;
}

我尝试直接使用加密器,而不是使用流,并且遇到了同样的问题.

EDIT : I tried to use the Encryptor directly, instead of using the streams and I've got the same problem.

private MemoryStream EncryptingString(string plainText, out long encryptSize)
{
    // Check arguments. 
    if (plainText == null || plainText.Length <= 0)
        throw new ArgumentNullException("plainText");

    ICryptoTransform encryptor = _cryptoAlgo.CreateEncryptor();

    byte[] cipherData = encryptor.TransformFinalBlock(
        _encoding.GetBytes(plainText), 0, plainText.Length);

    // Return the encrypted memory stream. 
    return msEncrypt;
}

推荐答案

这些不正确:

CFB_FIPS_Mode<DES_EDE3>::Encryption enc;
enc.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));

sizeof(key)sizeof(iv)返回指针的大小,而不是安全参数的大小.您应该改用以下方法:

sizeof(key) and sizeof(iv) returns the size of the pointers, not the size of the security parameters. You should use this instead:

enc.SetKeyWithIV(key, DES_EDE3::DEFAULT_KEYLENGTH, iv, DES_EDE3::BLOCKSIZE);


如果它适用于.Net,那么您应该更喜欢增加Mcrypt和.Net等库的反馈大小;并且不减小Crypto ++中的反馈大小.这是因为当反馈大小不是完整块大小时,某些模式会失去安全性.


If it works for .Net, then you should prefer to increase the feedback size for libraries like Mcrypt and .Net; and not reduce the feedback size in Crypto++. That's because some modes lose security when the feedback size is not the full block size.

我不知道这是否适用于.Net,但是您应该考虑或尝试以下操作:

I don't know if this will work with .Net, but its something you should consider or try:

public FibxCrypt()
{
    _cryptoAlgo = new TripleDESCryptoServiceProvider();
    _cryptoAlgo.Key = _key;
    _cryptoAlgo.IV = _iv;
    _cryptoAlgo.Mode = CipherMode.CFB;
    _cryptoAlgo.Padding = PaddingMode.Zeros;

    // Add this:
   _cryptoAlgo.FeedbackSize = _cryptoAlgo.BlockSize;
}

如果您无法在.Net中调整反馈大小,那么以下是在Crypto ++中更改反馈大小的方法.设置AlgorithmParameters来保存反馈大小参数,然后使用其他参数调用SetKey:

If you can't adjust the feedback size in .Net, then here's how to change feedback size in Crypto++. You setup a AlgorithmParameters to hold the feedback size parameter, and then you call SetKey with the additional parameters:

void *CryptData(BYTE *bDataIn, LONG lIn, LONG *lOut, byte* key, byte* iv)
{
    AlgorithmParameters params = MakeParameters(Name::FeedbackSize(), 1 /*8-bits*/)
                                               (Name::IV(), ConstByteArrayParameter(iv, DES_EDE3::BLOCKSIZE));
    CFB_FIPS_Mode<DES_EDE3>::Encryption enc;
    enc.SetKey(key, 24, DES_EDE3::DEFAULT_KEYLENGTH);

    ...
}

我不清楚在FIPS模式下运行的CFB模式是否允许这么小的反馈量.如果抛出异常,则只需使用CFB_Mode.

Its not clear to me if CFB mode operating in FIPS mode allows such a small feedback size. If it throws an exception, then you will need to use just CFB_Mode.

AlgorithmParameters可能由于operator()重载而显得有些奇怪.您可以在Crypto ++ Wiki上的 NameValuePairs 上进行阅读.其他感兴趣的Wiki页面是 TripleDES

AlgorithmParameters may look a little odd because of the operator() overload. You can read about it at NameValuePairs on the Crypto++ wiki. Other wiki pages of interest are TripleDES and CFB Mode.

要注意的另一件事是文本编码.由于UTF-16,通常会在.Net和Java中引起互操作性问题. UTF-8和ASCII引起的问题最少.因为您encoding = new UTF8Encoding(),您应该没事.

Another thing to watch out for is text encoding. It usually causes interoperability issues in .Net and Java due to UTF-16. UTF-8 and ASCII cause the least amount of problems. You should be OK since you encoding = new UTF8Encoding().

但是,如果仍然无法解决问题,那么您将得到未编码或未解释的字节消息.例如,在.Net和Crypto ++中都使用它:

But if things still don't work for you, then you a byte message that is not encoded or interpreted. For example, use this in both .Net and Crypto++:

byte msg[4] = { 0x01, 0x02, 0x03, 0x04 };

这四个字节没有被解释,因此它避开了编码问题.

The four bytes are not interpreted, so it side steps encoding issues.

这篇关于CFB模式下的TripleDES,C#和Crypto ++不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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