¿El relleno no es válido y no se puede eliminar?

126

He buscado en línea lo que significa esta excepción en relación con mi programa, pero parece que no puedo encontrar una solución o la razón por la que le ocurre a mi programa específico. He estado usando el ejemplo provisto por mi msdn para encriptar y desencriptar un XmlDocument usando el algoritmo de Rijndael. El cifrado funciona bien, pero cuando intento descifrar, obtengo la siguiente excepción:

El relleno no es válido y no se puede quitar

¿Alguien puede decirme qué puedo hacer para resolver este problema? Mi código a continuación es donde obtengo la clave y otros datos. Si el cryptoMode es falso, llamará al método de descifrado, que es donde ocurre la excepción:

public void Cryptography(XmlDocument doc, bool cryptographyMode)
{
    RijndaelManaged key = null;
    try
    {
    // Create a new Rijndael key.
    key = new RijndaelManaged();
    const string passwordBytes = "Password1234"; //password here 

    byte[] saltBytes = Encoding.UTF8.GetBytes("SaltBytes");
    Rfc2898DeriveBytes p = new Rfc2898DeriveBytes(passwordBytes, saltBytes);
    // sizes are devided by 8 because [ 1 byte = 8 bits ] 
    key.IV = p.GetBytes(key.BlockSize/8);
    key.Key = p.GetBytes(key.KeySize/8);

    if (cryptographyMode)
    {
        Ecrypt(doc, "Content", key);
    }
    else
    {
        Decrypt(doc, key);
    }

    }
    catch (Exception ex)
    {
    MessageBox.Show(ex.Message);
    }
    finally
    {
    // Clear the key.
    if (key != null)
    {
        key.Clear();
    }
    }

}

private void Decrypt(XmlDocument doc, SymmetricAlgorithm alg)
{
    // Check the arguments.  
    if (doc == null)
    throw new ArgumentNullException("Doc");
    if (alg == null)
    throw new ArgumentNullException("alg");

    // Find the EncryptedData element in the XmlDocument.
    XmlElement encryptedElement = doc.GetElementsByTagName("EncryptedData")[0] as XmlElement;

    // If the EncryptedData element was not found, throw an exception.
    if (encryptedElement == null)
    {
    throw new XmlException("The EncryptedData element was not found.");
    }


    // Create an EncryptedData object and populate it.
    EncryptedData edElement = new EncryptedData();
    edElement.LoadXml(encryptedElement);

    // Create a new EncryptedXml object.
    EncryptedXml exml = new EncryptedXml();


    // Decrypt the element using the symmetric key.
    byte[] rgbOutput = exml.DecryptData(edElement, alg); <----  I GET THE EXCEPTION HERE
    // Replace the encryptedData element with the plaintext XML element.
    exml.ReplaceData(encryptedElement, rgbOutput);

}
Amor marrón
fuente
12
¿Puede intentarlo configurando explícitamente el modo de relleno para que sea idéntico tanto en el cifrado como en el descifrado? Por ejemplo: alg.Padding = PaddingMode.NONE;
NetSquirrel
¿Qué aspecto tiene el método Encrypt ()?
csharptest.net
1
Gracias chicos que trabajaron.
Brown Love
2
@NetSquirrel: gracias por el recordatorio de PaddingMode.NONE. Me saca de este error (a otro) ... Haciendo AES tanto en Java como en C #, y ahora no sé por qué C # se queja del relleno de Java, aunque ambos usan PKCS # 7
Hoàng Long

Respuestas:

81

Rijndael / AES es un cifrado en bloque. Cifra datos en bloques de 128 bits (16 caracteres). El relleno criptográfico se utiliza para asegurarse de que el último bloque del mensaje tenga siempre el tamaño correcto.

Su método de descifrado espera cualquiera que sea su relleno predeterminado y no lo encuentra. Como dice @NetSquirrel, debe configurar explícitamente el relleno tanto para el cifrado como para el descifrado. A menos que tenga una razón para hacer lo contrario, use el relleno PKCS # 7.

rossum
fuente
7
¿Cómo configurar el relleno explícitamente?
Ahmad Hajjar
7
Gracias. Lo encontré rj.Padding = PaddingMode.none; :)
Ahmad Hajjar
7
@AhmadHajjar Ningún relleno tiene implicaciones de seguridad, no lo use.
deviantfan
1
Hola, configuré el relleno explícitamente, pero no funciona. No sé qué pasos hice mal. Por favor ayuda. alg.Padding = PaddingMode.PKCS7;
Johnny
21
Me doy cuenta de que este es un hilo antiguo. Pero, para quienes visiten, asegúrese de eliminar el bloque final al cifrar los datos.
Markus
53

Asegúrese de que las claves que utiliza para cifrar y descifrar sean las mismas . El método de relleno, incluso si no se establece explícitamente, debería permitir un descifrado / cifrado adecuado (si no se establece, será el mismo). Sin embargo, si por alguna razón está utilizando un conjunto de claves diferente para el descifrado que el utilizado para el cifrado , obtendrá este error:

El relleno no es válido y no se puede quitar

Si está utilizando algún algoritmo para generar claves dinámicamente, no funcionará. Deben ser iguales tanto para el cifrado como para el descifrado. Una forma común es hacer que la persona que llama proporcione las claves en el constructor de la clase de métodos de cifrado, para evitar que el proceso de cifrado / descifrado intervenga en la creación de estos elementos. Se centra en la tarea en cuestión (el cifrado y descifrado de datos) y requiere que el ivy keypara ser suministrado por el llamante.

atconway
fuente
Este consejo fue muy útil, porque, a veces, las claves se almacenan en app.config y siempre debemos estar seguros de que las claves que se utilizan para cifrar son las mismas que se utilizan para descifrar.
Mário Meyrelles
@atconway ¿Le importaría echar un vistazo a mi pregunta? Tengo un problema similar pero en C ++ / CLI: stackoverflow.com/questions/57139447/…
Simple
1
Sugeriría que en el uso diario, esta es probablemente la razón más probable por la que las personas encontrarán este error. Especialmente si no estás jugando con la configuración del relleno.
Dan
28

Para el beneficio de las personas que realizan búsquedas, puede valer la pena comprobar la entrada que se está descifrando. En mi caso, la información que se envía para descifrar entraba (incorrectamente) como una cadena vacía. Resultó en el error de relleno.

Esto puede estar relacionado con la respuesta de Rossum, pero pensó que valía la pena mencionarlo.

HockeyJ
fuente
Estoy de acuerdo, me pasó lo mismo, verificando que la entrada se descifre ANTES de hacer otras verificaciones. Obtuve 1 byte más de lo que encripte ...
Andrea Antonangeli
Una cuerda vacía también fue la culpable para mí.
dotNET
Mi caso fue que la frase de contraseña no estaba configurada (sí, lo sé), pero esta respuesta me llevó en la dirección correcta.
Jim
2
Mi problema fue que la cadena a descifrar se estaba convirtiendo a minúsculas antes de intentar descifrarla. Estaba obsesionado con el relleno y los cifrados y todo eso, pero resultó que era una mala entrada. ¡A veces solo necesitas dar un paso atrás!
Tom Gerken
15

Si se utilizan la misma clave y el mismo vector de inicialización para codificar y decodificar, este problema no proviene de la decodificación de datos sino de la codificación de datos.

Después de llamar al método Write en un objeto CryptoStream, SIEMPRE debe llamar al método FlushFinalBlock antes del método Close.

La documentación de MSDN sobre el método CryptoStream.FlushFinalBlock dice:
" Llamar al método Close llamará a FlushFinalBlock ... "
https://msdn.microsoft.com/en-US/library/system.security.cryptography.cryptostream.flushfinalblock(v=vs .110) .aspx
Esto es incorrecto. Llamar al método Close simplemente cierra CryptoStream y el flujo de salida.
Si no llama a FlushFinalBlock antes de Close después de escribir los datos para cifrarlos, al descifrar los datos, una llamada al método Read o CopyTo en su objeto CryptoStream generará una excepción CryptographicException (mensaje: "El relleno no es válido y no se puede eliminar").

Esto probablemente sea cierto para todos los algoritmos de cifrado derivados de SymmetricAlgorithm (Aes, DES, RC2, Rijndael, TripleDES), aunque acabo de verificarlo para AesManaged y un MemoryStream como flujo de salida.

Por lo tanto, si recibe esta excepción CryptographicException en el descifrado, lea el valor de la propiedad Stream Length de salida después de escribir sus datos para encriptarlos, luego llame a FlushFinalBlock y lea su valor nuevamente. Si ha cambiado, sabrá que llamar a FlushFinalBlock NO es opcional.

Y no es necesario realizar ningún relleno mediante programación ni elegir otro valor de propiedad de relleno. El relleno es un trabajo del método FlushFinalBlock.

.........

Comentario adicional para Kevin:

Sí, CryptoStream llama a FlushFinalBlock antes de llamar a Close, pero es demasiado tarde: cuando se llama al método CryptoStream Close, el flujo de salida también se cierra.

Si su flujo de salida es un MemoryStream, no puede leer sus datos después de cerrarlo. Por lo tanto, debe llamar a FlushFinalBlock en su CryptoStream antes de usar los datos cifrados escritos en MemoryStream.

Si su flujo de salida es un FileStream, las cosas empeoran porque la escritura está almacenada en búfer. La consecuencia es que los últimos bytes escritos pueden no escribirse en el archivo si cierra el flujo de salida antes de llamar a Flush en FileStream. Entonces, antes de llamar a Close en CryptoStream, primero debe llamar a FlushFinalBlock en su CryptoStream y luego llamar a Flush en su FileStream.

figolu
fuente
1
¿Por qué dices que está mal? El código de las Stream.Close()llamadas this.Dispose(true). El código CryptoStream.Dispose(bool)es:if (disposing) { if (!this._finalBlockTransformed) { this.FlushFinalBlock(); } this._stream.Close(); }
Kevin Doyon
1
Esto resolvió mi problema. Estaba desechando el cryptoStream correctamente, pero la llamada de disposición estaba ocurriendo "demasiado tarde", tal como dices. Esto resultó en el error de "relleno no válido", como se describe. Al agregar cryptoStream.FlushFinalBlock (), se resolvió el error de relleno no válido. ¡Gracias!
Daniel Lambert
14

Un tiempo de serval de lucha, finalmente resolví el problema.
(Nota: uso AES estándar como algoritmo simétrico. Esta respuesta puede no ser adecuada para todos).

  1. Cambie la clase de algoritmo. Reemplazar la RijndaelManagedclase porAESManaged una.
  2. No establezca explícitamente la KeySizeclase de algoritmo, déjelas predeterminadas.
    (Este es el paso muy importante. Creo que hay un error en la propiedad KeySize).

Aquí hay una lista en la que desea verificar qué argumento puede haber pasado por alto:

  • Llave
    (matriz de bytes, la longitud debe ser exactamente uno de 16, 24, 32 bytes para diferentes tamaños de clave).
  • IV
    (matriz de bytes, 16 bytes)
  • CipherMode
    (uno de CBC, CFB, CTS, ECB, OFB)
  • PaddingMode
    (Uno de ANSIX923, ISO10126, Ninguno, PKCS7, Zeros)
Johnny
fuente
3
No establecer explícitamente lo KeySizearregló para mí de inmediato. Oh, las peculiaridades de .NET :-(
Juan
Tenga en cuenta que esto parece ser una regresión en el propio .NET Framework. Tengo un código que solía funcionar con RijndaelManaged, pero dejó de funcionar, y simplemente cambiándolo a AesManaged / AesCryptoServiceProvider, vuelve a funcionar. Ni siquiera tenía ningún código que estableciera explícitamente KeySize. Entonces, si esto le muerde, siéntase mejor: es posible que la culpa no sea suya, sino del propio .NET Framework.
Usas
6

Mi problema fue que la contraseña de cifrado no coincidía con la contraseña de descifrado ... así que arrojó este error ... un poco engañoso.

ecklerpa
fuente
En realidad, es cierto que usamos PaddingMode.PKCS7 para cifrar y descifrar, pero recibí el mismo mensaje de error. También tenemos entorno Stage y Dev con diferentes valores clave. Cuando utilicé la clave adecuada, específica del entorno, esta excepción se resolvió ...
Mayor
Aunque todas las respuestas anteriores son buenas y debe usar el mismo relleno para Cifrar y Descifrar (¡NO se recomienda ninguna!) En realidad, esta respuesta también puede ser cierta. Cuando utilicé la clave adecuada, específica del entorno, la excepción "System.Security.Cryptography.CryptographicException: el relleno no es válido y no se puede eliminar". fue resuelto. Entonces sí, puede ser engañoso.
Mayor
Si con "passPhrase" estás hablando del valor exacto para encriptar / desencriptar (no es un problema con el uso de la clave incorrecta), entonces sí, este era mi problema. Mi caso fue que el valor cifrado original era más largo de lo que permitía el campo de la tabla de mi base de datos, por lo que se truncaba para que se ajustara sin que me diera cuenta. Luego, al descifrar ese valor truncado, se lanzó esta excepción.
David Gunderson
2

La solución que solucionó la mía fue que, sin darme cuenta, apliqué diferentes claves a los métodos de cifrado y descifrado.

Rondakay
fuente
1

Me encontré con este error al intentar pasar una ruta de archivo no cifrada al método Decrypt. La solución fue verificar si el archivo pasado está cifrado primero antes de intentar descifrar

if (Sec.IsFileEncrypted(e.File.FullName))
{
    var stream = Sec.Decrypt(e.File.FullName);
} 
else
{
    // non-encrypted scenario  
}
útilAbeja
fuente
1
Desafío a cualquier cobarde de Hit and Run sobre la validez de esta solución.
helpfulBee
+1 porque esta excepción se genera cuando descifra dos veces o descifra algo no cifrado. Entonces leí esta respuesta como "¿estás seguro de que los datos están realmente encriptados?".
Gerardo Grignoli
0

Otro escenario, nuevamente en beneficio de las personas que buscan.

Para mí, este error ocurrió durante el método Dispose () que enmascara un error anterior no relacionado con el cifrado.

Una vez que se solucionó el otro componente, esta excepción desapareció.

Clay Lenhart
fuente
3
¿Cuál fue el error anterior no relacionado con el cifrado?
NStuke
0

Encontré este error de relleno cuando editaba manualmente las cadenas cifradas en el archivo (usando el bloc de notas) porque quería probar cómo se comportaría la función de descifrado si mi contenido cifrado se modificaba manualmente.

La solución para mí fue colocar un

        try
            decryption stuff....
        catch
             inform decryption will not be carried out.
        end try

Como dije, mi error de relleno fue porque estaba escribiendo manualmente sobre el texto descifrado usando el bloc de notas. Puede que mi respuesta pueda guiarte hacia tu solución.

webzy
fuente
0

Yo tenía el mismo error. En mi caso fue porque he almacenado los datos cifrados en una base de datos SQL. La tabla en la que se almacenan los datos tiene un tipo de datos binarios (1000). Al recuperar los datos de la base de datos, descifraría estos 1000 bytes, mientras que en realidad había 400 bytes. Entonces, al eliminar los ceros finales (600) del resultado, se solucionó el problema.

Martijn
fuente
0

Tuve este error y estaba configurando explícitamente el tamaño del bloque: aesManaged.BlockSize = 128;

Una vez que eliminé eso, funcionó.

Barry Franklin
fuente
0

Tuve el mismo problema al intentar portar un programa Go a C #. Esto significa que ya se han cifrado muchos datos con el programa Go. Estos datos ahora deben descifrarse con C #.

La solución final fue PaddingMode.Noneo más bienPaddingMode.Zeros .

Los métodos criptográficos en Go:

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/sha1"
    "encoding/base64"
    "io/ioutil"
    "log"

    "golang.org/x/crypto/pbkdf2"
)

func decryptFile(filename string, saltBytes []byte, masterPassword []byte) (artifact string) {

    const (
        keyLength         int = 256
        rfc2898Iterations int = 6
    )

    var (
        encryptedBytesBase64 []byte // The encrypted bytes as base64 chars
        encryptedBytes       []byte // The encrypted bytes
    )

    // Load an encrypted file:
    if bytes, bytesErr := ioutil.ReadFile(filename); bytesErr != nil {
        log.Printf("[%s] There was an error while reading the encrypted file: %s\n", filename, bytesErr.Error())
        return
    } else {
        encryptedBytesBase64 = bytes
    }

    // Decode base64:
    decodedBytes := make([]byte, len(encryptedBytesBase64))
    if countDecoded, decodedErr := base64.StdEncoding.Decode(decodedBytes, encryptedBytesBase64); decodedErr != nil {
        log.Printf("[%s] An error occur while decoding base64 data: %s\n", filename, decodedErr.Error())
        return
    } else {
        encryptedBytes = decodedBytes[:countDecoded]
    }

    // Derive key and vector out of the master password and the salt cf. RFC 2898:
    keyVectorData := pbkdf2.Key(masterPassword, saltBytes, rfc2898Iterations, (keyLength/8)+aes.BlockSize, sha1.New)
    keyBytes := keyVectorData[:keyLength/8]
    vectorBytes := keyVectorData[keyLength/8:]

    // Create an AES cipher:
    if aesBlockDecrypter, aesErr := aes.NewCipher(keyBytes); aesErr != nil {
        log.Printf("[%s] Was not possible to create new AES cipher: %s\n", filename, aesErr.Error())
        return
    } else {

        // CBC mode always works in whole blocks.
        if len(encryptedBytes)%aes.BlockSize != 0 {
            log.Printf("[%s] The encrypted data's length is not a multiple of the block size.\n", filename)
            return
        }

        // Reserve memory for decrypted data. By definition (cf. AES-CBC), it must be the same lenght as the encrypted data:
        decryptedData := make([]byte, len(encryptedBytes))

        // Create the decrypter:
        aesDecrypter := cipher.NewCBCDecrypter(aesBlockDecrypter, vectorBytes)

        // Decrypt the data:
        aesDecrypter.CryptBlocks(decryptedData, encryptedBytes)

        // Cast the decrypted data to string:
        artifact = string(decryptedData)
    }

    return
}

... y ...

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/sha1"
    "encoding/base64"
    "github.com/twinj/uuid"
    "golang.org/x/crypto/pbkdf2"
    "io/ioutil"
    "log"
    "math"
    "os"
)

func encryptFile(filename, artifact string, masterPassword []byte) (status bool) {

    const (
        keyLength         int = 256
        rfc2898Iterations int = 6
    )

    status = false
    secretBytesDecrypted := []byte(artifact)

    // Create new salt:
    saltBytes := uuid.NewV4().Bytes()

    // Derive key and vector out of the master password and the salt cf. RFC 2898:
    keyVectorData := pbkdf2.Key(masterPassword, saltBytes, rfc2898Iterations, (keyLength/8)+aes.BlockSize, sha1.New)
    keyBytes := keyVectorData[:keyLength/8]
    vectorBytes := keyVectorData[keyLength/8:]

    // Create an AES cipher:
    if aesBlockEncrypter, aesErr := aes.NewCipher(keyBytes); aesErr != nil {
        log.Printf("[%s] Was not possible to create new AES cipher: %s\n", filename, aesErr.Error())
        return
    } else {

        // CBC mode always works in whole blocks.
        if len(secretBytesDecrypted)%aes.BlockSize != 0 {
            numberNecessaryBlocks := int(math.Ceil(float64(len(secretBytesDecrypted)) / float64(aes.BlockSize)))
            enhanced := make([]byte, numberNecessaryBlocks*aes.BlockSize)
            copy(enhanced, secretBytesDecrypted)
            secretBytesDecrypted = enhanced
        }

        // Reserve memory for encrypted data. By definition (cf. AES-CBC), it must be the same lenght as the plaintext data:
        encryptedData := make([]byte, len(secretBytesDecrypted))

        // Create the encrypter:
        aesEncrypter := cipher.NewCBCEncrypter(aesBlockEncrypter, vectorBytes)

        // Encrypt the data:
        aesEncrypter.CryptBlocks(encryptedData, secretBytesDecrypted)

        // Encode base64:
        encodedBytes := make([]byte, base64.StdEncoding.EncodedLen(len(encryptedData)))
        base64.StdEncoding.Encode(encodedBytes, encryptedData)

        // Allocate memory for the final file's content:
        fileContent := make([]byte, len(saltBytes))
        copy(fileContent, saltBytes)
        fileContent = append(fileContent, 10)
        fileContent = append(fileContent, encodedBytes...)

        // Write the data into a new file. This ensures, that at least the old version is healthy in case that the
        // computer hangs while writing out the file. After a successfully write operation, the old file could be
        // deleted and the new one could be renamed.
        if writeErr := ioutil.WriteFile(filename+"-update.txt", fileContent, 0644); writeErr != nil {
            log.Printf("[%s] Was not able to write out the updated file: %s\n", filename, writeErr.Error())
            return
        } else {
            if renameErr := os.Rename(filename+"-update.txt", filename); renameErr != nil {
                log.Printf("[%s] Was not able to rename the updated file: %s\n", fileContent, renameErr.Error())
            } else {
                status = true
                return
            }
        }

        return
    }
}

Ahora, descifrado en C #:

public static string FromFile(string filename, byte[] saltBytes, string masterPassword)
{
    var iterations = 6;
    var keyLength = 256;
    var blockSize = 128;
    var result = string.Empty;
    var encryptedBytesBase64 = File.ReadAllBytes(filename);

    // bytes -> string:
    var encryptedBytesBase64String = System.Text.Encoding.UTF8.GetString(encryptedBytesBase64);

    // Decode base64:
    var encryptedBytes = Convert.FromBase64String(encryptedBytesBase64String);
    var keyVectorObj = new Rfc2898DeriveBytes(masterPassword, saltBytes.Length, iterations);
    keyVectorObj.Salt = saltBytes;
    Span<byte> keyVectorData = keyVectorObj.GetBytes(keyLength / 8 + blockSize / 8);
    var key = keyVectorData.Slice(0, keyLength / 8);
    var iv = keyVectorData.Slice(keyLength / 8);

    var aes = Aes.Create();
    aes.Padding = PaddingMode.Zeros;
    // or ... aes.Padding = PaddingMode.None;
    var decryptor = aes.CreateDecryptor(key.ToArray(), iv.ToArray());
    var decryptedString = string.Empty;

    using (var memoryStream = new MemoryStream(encryptedBytes))
    {
        using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
        {
            using (var reader = new StreamReader(cryptoStream))
            {
                decryptedString = reader.ReadToEnd();
            }
        }
    }

    return result;
}

¿Cómo se puede explicar el problema del acolchado? Justo antes de la encriptación, el programa Go comprueba el relleno:

// CBC mode always works in whole blocks.
if len(secretBytesDecrypted)%aes.BlockSize != 0 {
    numberNecessaryBlocks := int(math.Ceil(float64(len(secretBytesDecrypted)) / float64(aes.BlockSize)))
    enhanced := make([]byte, numberNecessaryBlocks*aes.BlockSize)
    copy(enhanced, secretBytesDecrypted)
    secretBytesDecrypted = enhanced
}

La parte importante es esta:

enhanced := make([]byte, numberNecessaryBlocks*aes.BlockSize)
copy(enhanced, secretBytesDecrypted)

Se crea una nueva matriz con una longitud adecuada, de modo que la longitud sea un múltiplo del tamaño del bloque. Esta nueva matriz está llena de ceros. El método de copia luego copia los datos existentes en él. Se garantiza que la nueva matriz sea más grande que los datos existentes. En consecuencia, hay ceros al final de la matriz.

Por lo tanto, el código C # puede usar PaddingMode.Zeros. La alternativa PaddingMode.Nonesimplemente ignora cualquier relleno, que también funciona. Espero que esta respuesta sea útil para cualquiera que tenga que transferir el código de Go a C #, etc.

SommerIngeniería
fuente
0

El cliente me informa del mismo error. Yo personalmente no puedo reprocharlo. Mirando el código de los métodos Encrypt y Decrypt , ambos tienen Padding establecido en PaddingMode.PKCS7 . Descifrar se ve así y no puedo ver el problema con él con respecto a ' FlushFinalBlock '. ¿Podría alguien arrojar algo de luz sobre esto?

public string Decrypt(string cipherText)
{
  if (string.IsNullOrEmpty(cipherText))
    return "";
  string result;
  Encoding byteEncoder = Encoding.Default;

  byte[] rijnKey = byteEncoder.GetBytes(Password);
  byte[] rijnIv = byteEncoder.GetBytes(InitialVector);
  RijndaelManaged rijn = new RijndaelManaged { Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };

  using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
  {
    using (ICryptoTransform decryptor = rijn.CreateDecryptor(rijnKey, rijnIv))
    {
      using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
      {
                    using (StreamReader swDecrypt = new StreamReader(csDecrypt))
                    {
                        result = swDecrypt.ReadToEnd();
                    }
                }
    }
  }
  rijn.Clear();      
  return result.Replace("\0", "");
}
Alejandro
fuente
0

Yo tenía el mismo error. En mi caso, la contraseña dada es mayor que 16 significa que está encriptada, pero mientras me descifro recibo este error. Encriptación:

string keyString = "CDFUYP@ssw0rd123";
            var key = Encoding.UTF8.GetBytes(keyString);            
            using (var aesAlg = Aes.Create())
            {
                using (var encryptor = aesAlg.CreateEncryptor(key, aesAlg.IV))
                {
                    using (var msEncrypt = new MemoryStream())
                    {
                        using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                        using (var swEncrypt = new StreamWriter(csEncrypt))
                        {
                            swEncrypt.Write(text);
                        }                          
                        var iv = aesAlg.IV;

                        var decryptedContent = msEncrypt.ToArray();

                        var result = new byte[iv.Length + decryptedContent.Length];

                        Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
                        Buffer.BlockCopy(decryptedContent, 0, result, iv.Length, decryptedContent.Length);

                        var encryptedString = Convert.ToBase64String(result);
                        var decryptedString = Decrypt(encryptedString);
                        if (decryptedString == null)
                        {
                            return null;
                        }
                        return encryptedString;

                    }
                }

Descifrado:

 string keyString = "CDFUYP@ssw0rd123";
            var fullCipher = Convert.FromBase64String(cipherText);
            var iv = new byte[16];
            var cipher = new byte[16];
            Buffer.BlockCopy(fullCipher, 0, iv, 0, iv.Length);
            Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, iv.Length);
            var key = Encoding.UTF8.GetBytes(keyString);

            using (var aesAlg = Aes.Create())
            {
                using (var decryptor = aesAlg.CreateDecryptor(key, iv))
                {
                    string result;
                    using (var msDecrypt = new MemoryStream(cipher))
                    {
                        using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                        {
                            using (var srDecrypt = new StreamReader(csDecrypt))
                            {
                                result = srDecrypt.ReadToEnd();
                            }
                        }
                    }

                    return result;
                }
            }
Sundarraj
fuente
Hola @sundarraj, ¿es esta una pregunta?
Tiago Martins Peres 李大仁