TripleDES no modo CFB, C # e Crypto ++ difere
Aqui está o meu problema: Eu tenho um código legado em C ++ (usando o crypto ++ v5.6.1) e desenvolvo um novo em C # (.NET 3.5 usando System.Security.Cryptography). Eunão pode mudar o código C ++, mas eu preciso ser capaz de descriptografar dados criptografados anteriormente e aplicativos anteriores tem que ser capaz de descriptografar os dados que vou criptografar com o meu novo código c #.
O algoritmo usado é TripleDES com o modo de cifra CFB em ambos os casos, mas no final, os dados criptografados não são os mesmos, o número de bytes é idêntico, assim como o primeiro byte, mas além disso todos os outros bytes são diferentes.
O preenchimento é feito manualmente (adicionando zeros) no código C ++. Então eu defino o PaddingValue para PaddingMode.Zeros. (Eu também tentei adicionar zeros no final manualmente no código C #, isso não mudou nada).
Eu tentei usar System.Text.Encoding diferente, mas o resultado é o mesmo (na verdade, os caracteres testados são ASCII "puro" (por exemplo, entre 0 e 126)).
O valor do MandatoryBlockSize (), no código C ++, é 8, então eu configurei o FeedbackSize para 8 também. Mas se eu entendi escrever, é na verdade o tamanho do meu IV, não é?
O tamanho da chave é de 24 bytes (3 chaves diferentes) e o IV tem 8 bytes de comprimento. Eles são os mesmos nos dois códigos.
Se eu usar o modo CBC, em ambos os casos, os resultados são os mesmos (mas, como eu disse, não posso alterar o código legado ...), o modo OFB & CTS gera exceções (indisponível para um e incompatível para o outro) no meu aplicativo .NET, não posso comparar os resultados.
Eu tentei usar Mono, com .net versões 3.5 e 4.0, ou usando visual, com .net 3.5 ou 4.0, e os 4 resultados criptografados são os mesmos, mas difere do resultado original.
Agora eu realmente não sei o que testar ... Eu prefiro não envolver o Crypto ++ em um projeto C ++ / CLI para usá-lo em vez do System.Security.Cryptography.
Alguém tem um conselho ou pode dizer o que estou fazendo errado?
Aqui está o código 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;
}
Aqui está o código 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;
}
EDIT: Eu tentei usar o Encryptor diretamente, em vez de usar os fluxos e eu tenho o mesmo problema.
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;
}