Avatar billede coden Nybegynder
27. juni 2012 - 13:27 Der er 6 kommentarer og
1 løsning

Rijndael kryptering af streams fejler: tekst mangler samt exception"Padding is invalid and cannot be removed"

Hej

Jeg har et problem med følgende kode der smider exceptionen "Padding is invalid and cannot be removed". Den gør det bare ikke konsekvent, men alt afhængigt af hvilken tekst den "fodres med".

Koden er en omskrivning af noget jeg har fundet på nettet som arbejdede med filer og ikke streams som jeg har brug for (ufravigeligt krav). Jeg har derfor omskrevet metoderne med streams i stedet for filnavne som parametre. Det skal siges at på filer virker koden som den skal, men min kryptering skal foregå i memory og ikke på disken.

Min kode ser således ud:

using System.IO;
using System.Security.Cryptography;

namespace Cryptotest
{
    class Scrambler
    {
        private string password;
        private byte[] salt;

        public Scrambler(string Password, string Salt)
        {
            password = Password;
            salt = Encoding.ASCII.GetBytes(Salt);

        }
        public void EncrypStream(MemoryStream inStream, MemoryStream outStream)
        {
            // Step 1. Create the Symetrical algo object
            SymmetricAlgorithm symAlgo = new RijndaelManaged();
            symAlgo.Padding = PaddingMode.ISO10126;

            // Step 3. Specify a key (optional)
            Rfc2898DeriveBytes theKey = new Rfc2898DeriveBytes(password, salt);
            symAlgo.Key = theKey.GetBytes(symAlgo.KeySize / 8);
            symAlgo.IV = theKey.GetBytes(symAlgo.BlockSize / 8);

            // Read the unencrypted file file into fileData
            byte[] StreamData = new byte[inStream.Length];
            inStream.Position = 0;
            inStream.Read(StreamData, 0, (int)inStream.Length);

            // Step 4. Create the ICryptoTransfor object
            ICryptoTransform encryptor = symAlgo.CreateEncryptor();

            // Step 5. Create teh Crypto Stream object
            CryptoStream encryptStream = new CryptoStream(outStream, encryptor, CryptoStreamMode.Write);

            // Step 6. Write the contents to the CryptoStream
            encryptStream.Write(StreamData, 0, StreamData.Length);
            outStream.Position = 0;
        }
        public void DecryptStream(MemoryStream inStream, MemoryStream outStream)
        {
            // Step 2. Create the Symetrical algo object
            SymmetricAlgorithm symAlgo = new RijndaelManaged();
            symAlgo.Padding = PaddingMode.ISO10126;

            // Step 3. Specify a key (optional)
            Rfc2898DeriveBytes theKey = new Rfc2898DeriveBytes(password, salt);
            symAlgo.Key = theKey.GetBytes(symAlgo.KeySize / 8);
            symAlgo.IV = theKey.GetBytes(symAlgo.BlockSize / 8);

            // Step 4. Create the ICryptoTransfor object
            ICryptoTransform decryptor = symAlgo.CreateDecryptor();

            // Step 5. Create the Crypto Stream object
            CryptoStream decryptStream = new CryptoStream(inStream, decryptor, CryptoStreamMode.Read);

            // Step 6. Write the contents to the CryptoStream
            // Read the encrypted file file into fileData
            byte[] StreamData = new byte[inStream.Length];
            inStream.Position = 0;
            decryptStream.Read(StreamData, 0, (int)inStream.Length);

            // Save unecrypted data
            outStream.Write(StreamData, 0, StreamData.Length);
            outStream.Position = 0;
           
        }
    }
}

Anvender jeg teksten "Mit password" som Password og "This is my salt" som SALT samt følgende som den klar tekst jeg fylder i streamen der anvendes som inStream på EncrypStream, så kan jeg godt kryptere teksten.
"<Vault>
<Box>
<BoxID>25</BoxID>
<Description>En Test</Description>
</Box>
<Box>
<BoxID>15</BoxID>
<Description>Mere Test</Description>
</Box>
</Vault>
"
Jeg viser den stream jeg får retur i en tekstbox, for at se at streamen indeholdt data og de er blevet krypteret, og anvender indholdet af denne tekstboks som det der fyldes i den stream der anvendes som inStream på DecryptStream.
Det jeg så får tilbage er teksten:
"<Vault>
<Box>
<BoxID>25</BoxID>
<Description>En Test</Description>
</Box>
<Box>
<BoxID>15</BoxID>
<Description>Mere Test</Description>
</Bo"

der mangler altså:
"x>
</Vault>
".

Fjerner man det fra klarteksten og prøver igen, så kommer exceptionen.

Dette spørgsmål http://www.eksperten.dk/spm/703843 lugter af samme problemstilling, men jeg kan se lyset i den tråd til at løse mit problem.

Mine spørgsmål er nu - Why not work?:
1.
Hvorfor får jeg ikke hele teksten dekrypteret?
2.
Hvorfor fejler det 2. gang, den tekst der skal krypteres burde da ikke have indflydelse på om det går godt eller skidt, eller har jeg misforstået noget i denne sammenhæng.

Jeg ser frem til løsningen på mit problem fra den kompetente skare af kloge hoveder der findes her på Eksperten.

/Morten
Avatar billede arne_v Ekspert
27. juni 2012 - 15:04 #1
encryptStream.Write(StreamData, 0, StreamData.Length);

->

            encryptStream.Write(StreamData, 0, StreamData.Length);
            encryptStream.FlushFinalBlock();
Avatar billede arne_v Ekspert
27. juni 2012 - 15:04 #2
Uden FlushFinalBlock faar du ikke skrevet det hele ud.
Avatar billede arne_v Ekspert
27. juni 2012 - 15:05 #3
Ioeverigt mener jeg at der er mange ting i den kode som burde forbedres.
Avatar billede coden Nybegynder
28. juni 2012 - 08:27 #4
Hej Arne

Tak for dit indspark, jeg skal få det testet ASAP og se om det løser problemet, og så vender jeg tilbage.

Jeg er godt klar over at koden er mangelfuld, hvilket jeg også har tænkt mig at rette op på. Bl.a. skal det sikres at salt har den længde den skal have - det problem er jeg stødt på i mit forsøg på at tilpasse den kode jeg har fundet til mit behov. Derudover mangler der try catch, nedlæggelse af f.eks. cryptostreamen osv.

Min ide er, at når min tilpasning af koden virker, så finpudser jeg den ikke før. På den måde føler jeg mig sikker på at det ikke er min "finpudsning" af koden der evt. får den til at fejle.

Dermed ikke sagt at jeg har styr på hvad der burde gøres for at koden bliver optimal og sikret bedst muligt - langt fra. Ethvert indspark til hvad jeg bør gøre er derfor yderst velkommen.

Jeg får testet og vender tilbage.

/Morten
Avatar billede coden Nybegynder
28. juni 2012 - 08:37 #5
Hej

Det virker - NICE!

Så skal jeg bare have fundet ud af hvordan jeg overdrager point.

/Morten
Avatar billede arne_v Ekspert
28. juni 2012 - 14:55 #6
jeg skal smide et svar som du kan acceptere
Avatar billede arne_v Ekspert
30. juni 2012 - 02:43 #7
Her er et indspark til at goere koden kortere:

    public class Scrambler
    {
        private SymmetricAlgorithm symAlgo;
        public Scrambler(string password, string salt)
        {
            symAlgo = new RijndaelManaged();
            symAlgo.Padding = PaddingMode.ISO10126;
            Rfc2898DeriveBytes theKey = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt));
            symAlgo.Key = theKey.GetBytes(symAlgo.KeySize / 8);
            symAlgo.IV = theKey.GetBytes(symAlgo.BlockSize / 8);
        }
        public byte[] EncryptBytes(byte[] input)
        {
            ICryptoTransform encryptor = symAlgo.CreateEncryptor();
            return encryptor.TransformFinalBlock(input, 0, input.Length);
        }
        public byte[] DecryptBytes(byte[] input)
        {
            ICryptoTransform decryptor = symAlgo.CreateDecryptor();
            return decryptor.TransformFinalBlock(input, 0, input.Length);
        }
        public string EncryptString(string input)
        {
            return Convert.ToBase64String(EncryptBytes(Encoding.UTF8.GetBytes(input)));
        }
        public string DecryptString(string input)
        {
            return Encoding.UTF8.GetString(DecryptBytes(Convert.FromBase64String(input)));
        }
    }
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester