TripleDES в режиме CFB, C # и Crypto ++ отличается
Вот моя проблема: у меня есть унаследованный код на C ++ (с использованием crypto ++ v5.6.1), и я разрабатываю новый код на C # (.NET 3.5 с использованием System.Security.Cryptography). яне может измениться код C ++, но мне нужно иметь возможность расшифровывать ранее зашифрованные данные, а предыдущие приложения должны иметь возможность дешифровать данные, которые я буду шифровать с помощью моего нового кода C #.
Используемый алгоритм - TripleDES с режимом шифрования CFB в обоих случаях, но, в конце концов, зашифрованные данные не совпадают, количество байтов одинаково, как и первого байта, но кроме этого все другие байты различны.
Заполнение выполняется вручную (с добавлением нулей) в коде C ++. Поэтому я установил PaddingValue в PaddingMode.Zeros. (Я также попытался добавить нули в конце вручную в коде C #, это ничего не изменило).
Я попытался использовать другое System.Text.Encoding, но результат тот же (на самом деле проверенные символы являются «чистыми» ASCII (т.е. между 0 и 126)).
Значение MandatoryBlockSize () в коде C ++ равно 8, поэтому я также установил в FeedbackSize значение 8. Но если я понимаю, пишите, это на самом деле размер моего IV, не так ли?
Размер ключа составляет 24 байта (3 разных ключа), а длина IV составляет 8 байтов. Они оба одинаковы в двух кодах.
Если вместо этого я использую режим CBC, то в обоих случаях результаты совпадают (но, как я уже сказал, я не могу изменить устаревший код ...), исключения режима OFB и CTS генерируются (недоступно для одного и несовместимо для другого) в моем приложении .NET, поэтому я не могу сравнить результаты.
Я пытался использовать Mono, с версиями .Net 3.5 и 4.0, или визуально, с .Net 3.5 или 4.0, и 4 зашифрованных результата совпадают, но они отличаются от исходного результата.
Теперь я действительно не знаю, что тестировать ... Я бы предпочел не оборачивать Crypto ++ в проект C ++ / CLI, чтобы использовать его вместо 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;
}
РЕДАКТИРОВАТЬ: я пытался использовать Encryptor напрямую, вместо того, чтобы использовать потоки, и у меня та же проблема.
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;
}