TripleDES w trybie CFB, C # i Crypto ++ różni się
Oto mój problem: Mam kod starszego typu w C ++ (używając crypto ++ v5.6.1) i opracowuję nowy kod w C # (.NET 3.5 przy użyciu System.Security.Cryptography). janie mogę się zmienić kod C ++, ale muszę być w stanie odszyfrować dane wcześniej zaszyfrowane, a poprzednie aplikacje muszą być w stanie odszyfrować dane, które będę kryptować za pomocą mojego nowego kodu C #.
Zastosowanym algorytmem jest TripleDES z trybem szyfrowania CFB w obu przypadkach, ale w końcu zaszyfrowane dane nie są takie same, liczba bajtów jest identyczna jak pierwszy bajt, ale poza tym wszystkie inne bajty są różne.
Wypełnienie jest wykonywane ręcznie (dodawanie zer) w kodzie C ++. Ustawiłem PaddingValue na PaddingMode.Zeros. (Próbowałem też ręcznie dodawać zera w kodzie C #, nic nie zmieniło).
Próbowałem użyć innego System.Text.Encoding, ale wynik jest taki sam (w rzeczywistości testowane znaki to „czysty” ASCII (tj. Między 0 a 126)).
Wartość MandatoryBlockSize () w kodzie C ++ wynosi 8, więc ustawiłem także FeedbackSize na 8. Ale jeśli to rozumiem, to w rzeczywistości jest to rozmiar mojego IV, prawda?
Rozmiar klucza wynosi 24 bajty (3 różne klucze), a IV ma długość 8 bajtów. Oba są takie same w 2 kodach.
Jeśli zamiast tego w obu przypadkach używam trybu CBC, wyniki są takie same (ale, jak powiedziałem, nie mogę zmienić kodu starszego ...), tryby OFB i CTS rzucają wyjątki (niedostępne dla jednego i niekompatybilne dla drugiego) na mojej aplikacji .NET, więc nie mogę porównywać wyników.
Próbowałem użyć Mono, z .Net w wersji 3.5 i 4.0, lub używając wizualnego, z .Net 3.5 lub 4.0, a 4 zaszyfrowane wyniki są takie same, ale różnią się od oryginalnego wyniku.
Teraz naprawdę nie wiem, co testować ... Wolałbym nie zawijać Crypto ++ w projekcie C ++ / CLI, aby go używać zamiast System.Security.Cryptography.
Czy ktoś ma radę lub może powiedzieć, co robię źle?
Oto kod 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;
}
Oto kod 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;
}
EDYTUJ: Próbowałem użyć Encryptora bezpośrednio, zamiast używać strumieni i mam ten sam 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;
}