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

questionAnswers(2)

yourAnswerToTheQuestion