簡體   English   中英

CFB模式下的TripleDES,C#和Crypto ++有所不同

[英]TripleDES in CFB mode, C# and Crypto++ differs

這是我的問題:我有一個C ++中的遺留代碼(使用crypto ++ v5.6.1),我在C#(使用System.Security.Cryptography的.NET 3.5)中開發了一個新代碼。 無法更改 C ++代碼,但我需要能夠解密先前加密的數據,以前的應用程序必須能夠解密我將使用新的C#代碼加密的數據。

在兩種情況下使用的算法都是具有CFB密碼模式的TripleDES,但最后,加密數據不相同,字節數和第一個字節相同,但除此之外所有其他字節都不同。

在C ++代碼中手動完成填充(添加零)。 所以我將PaddingValue設置為PaddingMode.Zeros。 (我還嘗試在C#代碼中手動添加零,它沒有改變任何東西)。

我嘗試使用不同的System.Text.Encoding但結果是相同的(實際上測試的字符是“純”ASCII(即:介於0和126之間))。

在C ++代碼中,MandatoryBlockSize()的值是8,所以我也將FeedbackSize設置為8。 但是,如果我理解它寫的,它實際上是我的IV的大小,不是嗎?

密鑰大小為24個字節(3個不同的密鑰),IV為8個字節長。 它們在2個代碼中都是相同的。

如果我在兩種情況下都使用CBC模式,結果是相同的(但是,正如我所說,我無法更改遺留代碼...),OFB和CTS模式拋出異常(一個不可用,另一個不兼容)在我的.NET應用程序上,所以我無法比較結果。

我嘗試使用Mono,.Net版本3.5和4.0,或使用visual,與.Net 3.5或4.0,4加密結果相同,但它與原始結果不同。

現在我真的不知道要測試什么...我寧願不在C ++ / CLI項目中包裝Crypto ++來使用它而不是System.Security.Cryptography。

有人有建議或者能說出我做錯了什么嗎?

這是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;
}

編輯:我試圖直接使用加密器,而不是使用流,我有同樣的問題。

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;
}

您已更改的FeedBackSize與CFB操作模式( msdn文檔 )有關。 因此,您還應該檢查C ++和C#中的反饋大小是否相同。

我相信你的bug可能是C ++代碼和C#代碼之間的惡意BlockSizes。 您是否嘗試在C#實現中設置BlockSize = 8?

這些都不正確:

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

sizeof(key)sizeof(iv)返回指針的大小,而不是安全參數的大小。 您應該使用此代替:

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

如果它適用於.Net,那么你應該更喜歡增加像Mcrypt和.Net這樣的庫的反饋大小; 而不是減少Crypto ++中的反饋大小。 這是因為當反饋大小不是完整的塊大小時,某些模式會失去安全性。

我不知道這是否適用於.Net,但它應該考慮或嘗試:

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

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

由於operator()重載, AlgorithmParameters看起來有點奇怪。 您可以在Crypto ++ wiki上的NameValuePairs上閱讀它。 其他感興趣的維基頁面是TripleDESCFB Mode

----

另外需要注意的是文本編碼。 由於UTF-16,它通常會導致.Net和Java中的互操作性問題。 UTF-8和ASCII導致的問題最少。 你應該沒問題,因為你encoding = new UTF8Encoding()

但是,如果事情仍然不適合您,那么您將得到一個未編碼或解釋的字節消息。 例如,在.Net和Crypto ++中使用它:

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

不解釋這四個字節,因此它會對步驟進行編碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM