Le remplissage n'est pas valide et ne peut pas être supprimé?

126

J'ai cherché en ligne ce que cette exception signifie par rapport à mon programme, mais je ne parviens pas à trouver une solution ou la raison pour laquelle cela arrive à mon programme spécifique. J'ai utilisé l'exemple fourni avec mon msdn pour crypter et décrypter un XmlDocument à l'aide de l'algorithme Rijndael. Le cryptage fonctionne bien mais lorsque j'essaie de décrypter, j'obtiens l'exception suivante:

Le remplissage n'est pas valide et ne peut pas être supprimé

Quelqu'un peut-il me dire ce que je peux faire pour résoudre ce problème? Mon code ci-dessous est l'endroit où j'obtiens la clé et d'autres données. Si le cryptoMode est false, il appellera la méthode decrypt, qui est là où l'exception se produit:

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

}
Amour brun
la source
12
Pouvez-vous essayer en définissant explicitement le mode de remplissage pour qu'il soit identique à la fois sur le cryptage et le décryptage pour être identique. Par exemple: alg.Padding = PaddingMode.NONE;
NetSquirrel
À quoi ressemble la méthode Encrypt ()?
csharptest.net
1
Merci les gars qui ont travaillé.
Brown Love
2
@NetSquirrel: merci pour le rappel pour PaddingMode.NONE. Cela me sort de cette erreur (à une autre) ... Faire AES à la fois en Java et en C #, et maintenant je ne sais pas pourquoi C # se plaint du remplissage de Java, bien que les deux utilisent PKCS # 7
Hoàng Long

Réponses:

81

Rijndael / AES est un chiffrement par blocs. Il crypte les données en blocs de 128 bits (16 caractères). Le remplissage cryptographique est utilisé pour s'assurer que le dernier bloc du message est toujours de la bonne taille.

Votre méthode de décryptage attend quel que soit son remplissage par défaut et ne le trouve pas. Comme le dit @NetSquirrel, vous devez définir explicitement le remplissage pour le cryptage et le décryptage. Sauf si vous avez une raison de faire autrement, utilisez le remplissage PKCS # 7.

Rossum
la source
7
comment définir explicitement le remplissage ??
Ahmad Hajjar le
7
Merci je l'ai trouvé rj.Padding = PaddingMode.none; :)
Ahmad Hajjar
7
@AhmadHajjar Aucun rembourrage n'a des implications de sécurité, ne l'utilisez pas.
deviantfan
1
Salut, j'ai défini le rembourrage explicitement, mais ne fonctionne pas. Je ne sais pas quelles étapes j'ai mal faites. Veuillez aider. alg.Padding = PaddingMode.PKCS7;
Johnny
21
Je me rends compte que c'est un vieux fil. Mais, pour ceux qui visitent, assurez-vous de vider le dernier bloc lors du cryptage des données.
Markus
53

Assurez-vous que les clés que vous utilisez pour crypter et décrypter sont les mêmes . La méthode de remplissage, même si elle n'est pas explicitement définie, devrait toujours permettre un décryptage / cryptage correct (si elle n'est pas définie, elle sera la même). Toutefois , si pour une raison quelconque utilisez un autre jeu de clés pour le décryptage que celle utilisée pour le chiffrement , vous aurez obtenir cette erreur:

Le remplissage n'est pas valide et ne peut pas être supprimé

Si vous utilisez un algorithme pour générer dynamiquement des clés qui ne fonctionneront pas. Ils doivent être les mêmes pour le cryptage et le décryptage. Une manière courante consiste à demander à l'appelant de fournir les clés dans le constructeur de la classe des méthodes de chiffrement, pour éviter que le processus de chiffrement / déchiffrement ne participe à la création de ces éléments. Il se concentre sur la tâche à accomplir (cryptage et décryptage des données) et nécessite que ivet keysoit fourni par l'appelant.

atconway
la source
Cette astuce a été très utile, car parfois les clés sont stockées sur app.config et il faut toujours être sûr que les clés utilisées pour crypter sont les mêmes que celles utilisées pour décrypter.
Mário Meyrelles
@atconway Pourriez-vous jeter un œil à ma question? J'ai un problème similaire mais en C ++ / CLI: stackoverflow.com/questions/57139447/...
Simple
1
Je suggérerais que dans l'utilisation quotidienne, c'est probablement la raison la plus probable pour laquelle les gens rencontreront cette erreur. Surtout si vous ne jouez pas avec les paramètres de remplissage.
Dan
28

Pour les utilisateurs qui recherchent, il peut être utile de vérifier l'entrée en cours de déchiffrement. Dans mon cas, les informations envoyées pour le décryptage étaient (à tort) entrées sous forme de chaîne vide. Cela a entraîné une erreur de remplissage.

Cela peut être lié à la réponse de Rossum, mais cela vaut la peine d'être mentionné.

HockeyJ
la source
Je suis d'accord, m'est arrivé la même chose, en vérifiant l'entrée en cours de décryptage AVANT de faire d'autres vérifications. Je recevais 1 octet de plus que ce que j'ai encodé ...
Andrea Antonangeli
Une chaîne vide était aussi le coupable pour moi.
dotNET
Mon cas était que la phrase de passe n'était pas définie (ouais je sais), mais cette réponse m'a amené dans la bonne direction.
Jim
2
Mon problème était que la chaîne à déchiffrer était convertie en minuscules avant que j'essaye de la déchiffrer. J'étais obsédée par le rembourrage, les chiffrements et tout ça, mais il s'est avéré que c'était juste une mauvaise entrée. Parfois, il suffit de prendre du recul!
Tom Gerken
15

Si la même clé et le même vecteur d'initialisation sont utilisés pour le codage et le décodage, ce problème ne vient pas du décodage des données mais du codage des données.

Après avoir appelé la méthode Write sur un objet CryptoStream, vous devez TOUJOURS appeler la méthode FlushFinalBlock avant la méthode Close.

La documentation MSDN sur la méthode CryptoStream.FlushFinalBlock indique:
"L' appel de la méthode Close appellera FlushFinalBlock ... "
https://msdn.microsoft.com/en-US/library/system.security.cryptography.cryptostream.flushfinalblock(v=vs .110) .aspx
C'est faux. L'appel de la méthode Close ferme simplement le CryptoStream et le Stream de sortie.
Si vous n'appelez pas FlushFinalBlock avant Close après avoir écrit des données à chiffrer, lors du déchiffrement des données, un appel à la méthode Read ou CopyTo sur votre objet CryptoStream lèvera une exception CryptographicException (message: "Le remplissage est invalide et ne peut pas être supprimé").

Cela est probablement vrai pour tous les algorithmes de chiffrement dérivés de SymmetricAlgorithm (Aes, DES, RC2, Rijndael, TripleDES), bien que je viens de vérifier cela pour AesManaged et un MemoryStream comme flux de sortie.

Ainsi, si vous recevez cette exception CryptographicException lors du déchiffrement, lisez la valeur de la propriété Stream Length de sortie après avoir écrit vos données à chiffrer, puis appelez FlushFinalBlock et relisez sa valeur. S'il a changé, vous savez que l'appel de FlushFinalBlock n'est PAS facultatif.

Et vous n'avez pas besoin d'effectuer de remplissage par programme ou de choisir une autre valeur de propriété de remplissage. Le remplissage est un travail de méthode FlushFinalBlock.

.........

Remarque supplémentaire pour Kevin:

Oui, CryptoStream appelle FlushFinalBlock avant d'appeler Close, mais il est trop tard: lorsque la méthode CryptoStream Close est appelée, le flux de sortie est également fermé.

Si votre flux de sortie est un MemoryStream, vous ne pouvez pas lire ses données après sa fermeture. Vous devez donc appeler FlushFinalBlock sur votre CryptoStream avant d'utiliser les données chiffrées écrites sur le MemoryStream.

Si votre flux de sortie est un FileStream, les choses sont pires car l'écriture est mise en mémoire tampon. La conséquence est que les derniers octets écrits peuvent ne pas être écrits dans le fichier si vous fermez le flux de sortie avant d'appeler Flush sur FileStream. Donc, avant d'appeler Close sur CryptoStream, vous devez d'abord appeler FlushFinalBlock sur votre CryptoStream, puis appeler Flush sur votre FileStream.

figolu
la source
1
Pourquoi dites-vous que c'est faux? Le code des Stream.Close()appels this.Dispose(true). Le code pour CryptoStream.Dispose(bool)est:if (disposing) { if (!this._finalBlockTransformed) { this.FlushFinalBlock(); } this._stream.Close(); }
Kevin Doyon
1
Cela a résolu mon problème. Je supprimais correctement le cryptoStream, mais l'appel de suppression se produisait "trop ​​tard", comme vous le dites. Cela a entraîné l'erreur "de remplissage non valide", comme décrit. En ajoutant cryptoStream.FlushFinalBlock (), l'erreur de remplissage non valide a été résolue. Merci!
Daniel Lambert
14

Un temps serval de combats, j'ai finalement résolu le problème.
(Remarque: j'utilise AES standard comme algorithme symétrique. Cette réponse peut ne pas convenir à tout le monde.)

  1. Changez la classe d'algorithme. Remplacez la RijndaelManagedclasse par AESManagedune.
  2. Ne définissez pas explicitement la KeySizeclasse d'algorithme, laissez- les par défaut.
    (C'est l'étape très importante. Je pense qu'il y a un bogue dans la propriété KeySize.)

Voici une liste que vous souhaitez vérifier quel argument vous avez peut-être manqué:

  • Clé
    (tableau d'octets, la longueur doit être exactement l'un des 16, 24, 32 octets pour différentes tailles de clé.)
  • IV
    (tableau d'octets, 16 octets)
  • CipherMode
    (l'un des CBC, CFB, CTS, ECB, OFB)
  • PaddingMode
    (l'un des ANSIX923, ISO10126, Aucun, PKCS7, Zéros)
Johnny
la source
3
Pas de réglage explicite l'a KeySizecorrigé pour moi tout de suite. Oh les bizarreries de .NET :-(
John
Notez que cela semble être une régression dans le .NET Framework lui-même. J'ai du code qui fonctionnait avec RijndaelManaged, mais qui a cessé de fonctionner, et en le changeant simplement en AesManaged / AesCryptoServiceProvider, il fonctionne à nouveau. Je n'avais même pas de code définissant explicitement le KeySize. Donc, si vous êtes mordu par cela, sentez-vous mieux - la faute n'est peut-être pas à vous, mais au .NET Framework lui-même.
Usas
6

Mon problème était que le passPhrase du chiffrement ne correspondait pas au passPhrase du déchiffrement ... donc il a jeté cette erreur ... un peu trompeur.

Ecklerpa
la source
En fait, il est vrai que nous utilisons PaddingMode.PKCS7 pour Encrypt and Decrypt mais j'ai eu le même message d'erreur. Nous avons également un environnement Stage et Dev avec différentes valeurs clés. Lorsque j'ai utilisé la clé appropriée - spécifique à l'environnement -, cette exception a été résolue ...
Majeur
Bien que toutes les réponses ci-dessus soient bonnes et que vous deviez utiliser le même rembourrage pour Chiffrer et Déchiffrer (aucune n'est PAS recommandée!) En fait, cette réponse peut également être vraie. Lorsque j'ai utilisé la clé appropriée spécifique à l'environnement, l'exception "System.Security.Cryptography.CryptographicException: le remplissage n'est pas valide et ne peut pas être supprimé." a été résolu. Alors oui, cela peut être trompeur.
Majeur
Si par "passPhrase" vous parlez de la valeur exacte à crypter / décrypter (pas un problème avec l'utilisation de la mauvaise clé), alors oui, c'était mon problème. Mon cas était que la valeur cryptée d'origine était plus longue que le champ de la table de ma base de données ne le permettait, donc elle était tronquée pour tenir sans que je m'en rende compte. Ensuite, lors du déchiffrement de cette valeur tronquée, cette exception a été levée.
David Gunderson le
2

La solution qui a corrigé la mienne était que j'avais appliqué par inadvertance différentes clés aux méthodes de cryptage et de décryptage.

Rondakay
la source
1

Je suis tombé sur cette erreur en essayant de transmettre un chemin de fichier non chiffré à la méthode Decrypt.La solution était de vérifier si le fichier passé est chiffré avant d'essayer de déchiffrer

if (Sec.IsFileEncrypted(e.File.FullName))
{
    var stream = Sec.Decrypt(e.File.FullName);
} 
else
{
    // non-encrypted scenario  
}
utileBee
la source
1
Je conteste tout Hit and Run Coward sur la validité de cette solution.
utileBee
+1 car cette exception est déclenchée lorsque vous déchiffrez deux fois ou que vous déchiffrez quelque chose qui n'est pas chiffré. J'ai donc lu cette réponse comme "êtes-vous sûr que les données sont réellement cryptées?".
Gerardo Grignoli du
0

Un autre scénario, toujours au profit des personnes qui recherchent.

Pour moi, cette erreur s'est produite lors de la méthode Dispose () qui masquait une erreur précédente sans rapport avec le chiffrement.

Une fois que l'autre composant a été corrigé, cette exception a disparu.

Clay Lenhart
la source
3
Quelle était l'erreur précédente sans rapport avec le chiffrement?
NStuke
0

J'ai rencontré cette erreur de remplissage lorsque je modifiais manuellement les chaînes cryptées dans le fichier (à l'aide du bloc-notes), car je voulais tester le comportement de la fonction de décryptage si mon contenu crypté était modifié manuellement.

La solution pour moi était de placer un

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

Comme je l'ai dit, mon erreur de remplissage était due au fait que je tapais manuellement sur le texte déchiffré à l'aide du bloc-notes. Peut-être que ma réponse peut vous guider vers votre solution.

webzy
la source
0

J'ai eu la même erreur. Dans mon cas, c'est parce que j'ai stocké les données cryptées dans une base de données SQL. La table dans laquelle les données sont stockées a un type de données binaire (1000). Lors de la récupération des données de la base de données, il décrypterait ces 1000 octets, alors qu'il y en avait en fait 400 octets. Donc, en supprimant les zéros de fin (600) du résultat, le problème a été résolu.

Martijn
la source
0

J'ai eu cette erreur et je définissais explicitement la taille du bloc: aesManaged.BlockSize = 128;

Une fois que j'ai supprimé cela, cela a fonctionné.

Barry Franklin
la source
0

J'ai eu le même problème en essayant de porter un programme Go vers C #. Cela signifie que de nombreuses données ont déjà été cryptées avec le programme Go. Ces données doivent maintenant être déchiffrées avec C #.

La solution finale était PaddingMode.Noneou plutôt PaddingMode.Zeros.

Les méthodes cryptographiques de 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
}

... et ...

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

Maintenant, décryptage 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;
}

Comment expliquer le problème du rembourrage? Juste avant le chiffrement, le programme Go vérifie le remplissage:

// 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 partie importante est la suivante:

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

Un nouveau tableau est créé avec une longueur appropriée, de sorte que la longueur soit un multiple de la taille du bloc. Ce nouveau tableau est rempli de zéros. La méthode de copie y copie ensuite les données existantes. Il est garanti que le nouveau tableau est plus grand que les données existantes. En conséquence, il y a des zéros à la fin du tableau.

Ainsi, le code C # peut utiliser PaddingMode.Zeros. L'alternative PaddingMode.Noneignore simplement tout remplissage, ce qui fonctionne également. J'espère que cette réponse est utile pour quiconque doit porter le code de Go vers C #, etc.

SommerIngénierie
la source
0

Je suis signalé la même erreur par le client. Je ne peux personnellement pas le reprocher. En regardant le code des méthodes Encrypt et Decrypt , les deux ont Padding défini sur PaddingMode.PKCS7 . Decrypt ressemble à ceci et je ne vois pas le problème avec ' FlushFinalBlock '. Quelqu'un pourrait-il s'il vous plaît faire la lumière là-dessus?

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", "");
}
Alexandre
la source
0

J'ai eu la même erreur. Dans mon cas, le mot de passe donné est supérieur à 16 signifie qu'il est crypté, mais lors du décryptage, j'obtiens cette erreur. Chiffrement:

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;

                    }
                }

Décryptage:

 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
la source
Salut @sundarraj, est-ce une question?
Tiago Martins Peres 李大仁