[英]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
上閱讀它。 其他感興趣的維基頁面是TripleDES和CFB 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.