Estoy tratando de cifrar y descifrar un flujo de archivos a través de una toma de corriente utilizando RijndaelManaged, pero sigo chocando con la excepciónLongitud de los datos para descifrar es válido
CryptographicException: Length of the data to decrypt is invalid. at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) at System.Security.Cryptography.CryptoStream.FlushFinalBlock() at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing)
La excepción se produce al final de la sentencia using en receiveFile, cuando se ha transferido todo el archivo.
He intentado buscar en la web, pero sólo encontraron respuestas a los problemas que surgen cuando se utiliza codificación el cifrado y descifrado de una sola cadena. Uso un FileStream, por lo que no especifico ninguna codificación para usar, así que ese no debería ser el problema. Estos son mis métodos:
private void transferFile(FileInfo file, long position, long readBytes)
{
// transfer on socket stream
Stream stream = new FileStream(file.FullName, FileMode.Open);
if (position > 0)
{
stream.Seek(position, SeekOrigin.Begin);
}
// if this should be encrypted, wrap the encryptor stream
if (UseCipher)
{
stream = new CryptoStream(stream, streamEncryptor, CryptoStreamMode.Read);
}
using (stream)
{
int read;
byte[] array = new byte[8096];
while ((read = stream.Read(array, 0, array.Length)) > 0)
{
streamSocket.Send(array, 0, read, SocketFlags.None);
position += read;
}
}
}
private void receiveFile(FileInfo transferFile)
{
byte[] array = new byte[8096];
// receive file
Stream stream = new FileStream(transferFile.FullName, FileMode.Append);
if (UseCipher)
{
stream = new CryptoStream(stream, streamDecryptor, CryptoStreamMode.Write);
}
using (stream)
{
long position = new FileInfo(transferFile.Path).Length;
while (position < transferFile.Length)
{
int maxRead = Math.Min(array.Length, (int)(transferFile.Length - position));
int read = position < array.Length
? streamSocket.Receive(array, maxRead, SocketFlags.None)
: streamSocket.Receive(array, SocketFlags.None);
stream.Write(array, 0, read);
position += read;
}
}
}
Este es el método que utilizo para configurar las cifras. byte [] init es una matriz de bytes generada.
private void setupStreamCipher(byte[] init)
{
RijndaelManaged cipher = new RijndaelManaged();
cipher.KeySize = cipher.BlockSize = 256; // bit size
cipher.Mode = CipherMode.ECB;
cipher.Padding = PaddingMode.ISO10126;
byte[] keyBytes = new byte[32];
byte[] ivBytes = new byte[32];
Array.Copy(init, keyBytes, 32);
Array.Copy(init, 32, ivBytes, 0, 32);
streamEncryptor = cipher.CreateEncryptor(keyBytes, ivBytes);
streamDecryptor = cipher.CreateDecryptor(keyBytes, ivBytes);
}
¿Alguien tiene una idea de lo que podría estar haciendo mal?
El FlushFinalBlock() es llamado en la sección de "cierre" de la instrucción using
voy a cambiar el CipherMode, que acaba de entrar en él como un ejemplo para que sepa que no inicializar mi cifrado en cualquier "Manera rara. Los readBytes en sendFile() aún no se utilizan, olvidé eliminarlos. Leí hasta el final del archivo, por lo que este no debería ser el problema aquí. Pensé que se estaba ocupando del relleno? ¿Qué puedo cambiar para que funcione? – PatrickSi el flujo de cifrado está en modo de lectura, el bloque final se perderá si lo descarta; tiene que leer realmente el final del archivo de su flujo fuente subyacente para producir el bloque final. –
En respuesta a Jeffrey: Si intento llamar a stream.FlushFinalBlock(), dice NonSupportedException: FlushFinalBlock no se puede invocar dos veces en la misma transmisión. ¿Esto no significa que se ha leído (y enviado) un final de archivo? – Patrick