locked
AES Encryption - Encrypting byte array RRS feed

  • Question

  • Hello guys. I am trying to encrypt my byte array. However, I am getting some weird output. I am sharing my encryption and decryption functions. Am I doing something wrong? Thank you

    public static byte[] encryptStream(byte[] plain, byte[] Key, byte[] IV)
            {
                byte[] encrypted; ;
                using (MemoryStream mstream = new MemoryStream())
                {
                    using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
                    {
                        using (CryptoStream cryptoStream = new CryptoStream(mstream,
                            aesProvider.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
                        {
                            cryptoStream.Write(plain, 0, plain.Length);
                        }
    
                    }
                    encrypted = mstream.ToArray();
                }
                return encrypted;
            }
    
            public static byte[] decryptStream(byte[] encrypted, byte[] Key, byte[] IV)
            {
                byte[] plain;
                using (MemoryStream mStream = new MemoryStream())
                {
                    using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
                    {
                        using (CryptoStream cryptoStream = new CryptoStream(mStream,
                            aesProvider.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
                        {
                            cryptoStream.Read(encrypted, 0, encrypted.Length);
                        }
                    }
                    plain = mStream.ToArray();
                }
                return plain;
            }

    Thursday, November 13, 2014 5:05 AM

Answers

  • You reading from an empty MemoryStream. You should put the encrypted data inside the MemoryStream and the read will return the decrypted bytes.

    Use following line the create MemoryStream with the encrypted data:

    using (MemoryStream mStream = new MemoryStream(encrypted)) {

    Reading out is harder, you can't ask the stream its size. So if you don't it up front you should read (multiple times) until the of the stream is reached.

    • Marked as answer by Kristin Xie Monday, November 24, 2014 9:39 AM
    Thursday, November 13, 2014 7:44 AM
  • Hi basag,

    I am not sure what weird output you have got. I made a simple program which achieved encryption and

    decryption functions. Below is the code:

    public static byte[] encryptStream(byte[] plain, byte[] Key, byte[] IV)
             {
                 byte[] encrypted; ;
                 using (MemoryStream mstream = new MemoryStream())
                 {
                     using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
                     {
                         using (CryptoStream cryptoStream = new CryptoStream(mstream,
                             aesProvider.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
                         {
                             cryptoStream.Write(plain, 0, plain.Length);                      
                         }
                         encrypted = mstream.ToArray();
                     }                 
                 }
                 return encrypted;
             }
    public static byte[] mydec(byte[] encrypted, byte[] Key, byte[] IV)
            {
                byte[] plain;
                using (MemoryStream mStream = new MemoryStream(encrypted)) //add encrypted
                {
                    using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
                    {
                        using (CryptoStream cryptoStream = new CryptoStream(mStream,
                            aesProvider.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
                        {
                           //cryptoStream.Read(encrypted, 0, encrypted.Length);
                            using (StreamReader stream = new StreamReader(cryptoStream))
                            {
                               string sf= stream.ReadToEnd();
                               plain = System.Text.Encoding.Default.GetBytes(sf);
                            }
                        }
                    }           
               }
                return plain;
            }

    Encryption and decryption functions are used by aescryptoserviceprovider class, you might get more information from the link below.

    #AesCryptoServiceProvider Class

    http://msdn.microsoft.com/en-us/library/system.security.cryptography.aescryptoserviceprovider(v=vs.110).aspx

    If you have any further questions, please feel free to post in this forum.

    Best regards,

    Leo

    • Edited by Leo ZT Thursday, November 20, 2014 11:27 AM
    • Marked as answer by Kristin Xie Monday, November 24, 2014 9:39 AM
    Friday, November 14, 2014 11:27 AM
  • I think that your decrypt needs to look more like this:

    public static byte[] decryptStream(byte[] encrypted, byte[] Key, byte[] IV)
    {
     byte[] plain;
     int count;
     using (MemoryStream mStream = new MemoryStream(encrypted)) 
     {
      using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
      {
       aesProvider.Mode = CipherMode.CBC; 
       using (CryptoStream cryptoStream = new CryptoStream(mStream,
        aesProvider.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
       {
        plain = new byte[encrypted.Length];
        count = cryptoStream.Read(plain, 0, plain.Length);
       }
      }
     }
      
     // My method was written quite some time ago, and I don't remember why we had to copy the Array
     // but I'm pretty sure that it's necessary
     byte[] returnval = new byte[count];
     Array.Copy(plain, returnval, count);
     return returnval;
    }
    


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    • Marked as answer by Kristin Xie Monday, November 24, 2014 9:39 AM
    Friday, November 14, 2014 11:28 PM

All replies

  • You reading from an empty MemoryStream. You should put the encrypted data inside the MemoryStream and the read will return the decrypted bytes.

    Use following line the create MemoryStream with the encrypted data:

    using (MemoryStream mStream = new MemoryStream(encrypted)) {

    Reading out is harder, you can't ask the stream its size. So if you don't it up front you should read (multiple times) until the of the stream is reached.

    • Marked as answer by Kristin Xie Monday, November 24, 2014 9:39 AM
    Thursday, November 13, 2014 7:44 AM
  • Hi basag,

    I am not sure what weird output you have got. I made a simple program which achieved encryption and

    decryption functions. Below is the code:

    public static byte[] encryptStream(byte[] plain, byte[] Key, byte[] IV)
             {
                 byte[] encrypted; ;
                 using (MemoryStream mstream = new MemoryStream())
                 {
                     using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
                     {
                         using (CryptoStream cryptoStream = new CryptoStream(mstream,
                             aesProvider.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
                         {
                             cryptoStream.Write(plain, 0, plain.Length);                      
                         }
                         encrypted = mstream.ToArray();
                     }                 
                 }
                 return encrypted;
             }
    public static byte[] mydec(byte[] encrypted, byte[] Key, byte[] IV)
            {
                byte[] plain;
                using (MemoryStream mStream = new MemoryStream(encrypted)) //add encrypted
                {
                    using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
                    {
                        using (CryptoStream cryptoStream = new CryptoStream(mStream,
                            aesProvider.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
                        {
                           //cryptoStream.Read(encrypted, 0, encrypted.Length);
                            using (StreamReader stream = new StreamReader(cryptoStream))
                            {
                               string sf= stream.ReadToEnd();
                               plain = System.Text.Encoding.Default.GetBytes(sf);
                            }
                        }
                    }           
               }
                return plain;
            }

    Encryption and decryption functions are used by aescryptoserviceprovider class, you might get more information from the link below.

    #AesCryptoServiceProvider Class

    http://msdn.microsoft.com/en-us/library/system.security.cryptography.aescryptoserviceprovider(v=vs.110).aspx

    If you have any further questions, please feel free to post in this forum.

    Best regards,

    Leo

    • Edited by Leo ZT Thursday, November 20, 2014 11:27 AM
    • Marked as answer by Kristin Xie Monday, November 24, 2014 9:39 AM
    Friday, November 14, 2014 11:27 AM
  • I think that your decrypt needs to look more like this:

    public static byte[] decryptStream(byte[] encrypted, byte[] Key, byte[] IV)
    {
     byte[] plain;
     int count;
     using (MemoryStream mStream = new MemoryStream(encrypted)) 
     {
      using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
      {
       aesProvider.Mode = CipherMode.CBC; 
       using (CryptoStream cryptoStream = new CryptoStream(mStream,
        aesProvider.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
       {
        plain = new byte[encrypted.Length];
        count = cryptoStream.Read(plain, 0, plain.Length);
       }
      }
     }
      
     // My method was written quite some time ago, and I don't remember why we had to copy the Array
     // but I'm pretty sure that it's necessary
     byte[] returnval = new byte[count];
     Array.Copy(plain, returnval, count);
     return returnval;
    }
    


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    • Marked as answer by Kristin Xie Monday, November 24, 2014 9:39 AM
    Friday, November 14, 2014 11:28 PM
  • Regarding why we need to copy, i believe it's because the length of the original array will be shorter then the encrypted so you need to do a copy to get the actual array length after it's been decrypted
    Tuesday, May 5, 2015 6:51 AM
  • Yes, you're correct. Thanks for making me dig into this further!  ;0)

    I did some more testing and the encrypted array gets padded (with  byte values of 0) to bring the total array size to 16, 32, 64, etc. ... whatever the next larger size is. And, when decrypting, the CryptoStream.Read() returns a count of the number of bytes read into the buffer (which apparently ignores those padded 0-value bytes at the end).

    So, yes, the copy removes those extra bytes and that's why it's necessary so that the decrypt returns the original array (content *and* size).


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Tuesday, May 5, 2015 2:55 PM

  • That's necessary because the plain has the padding stuff
    Friday, March 2, 2018 10:24 AM
  • Uh, yeah ... isn't that what Donovan and I said almost 3 years ago?

    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Friday, March 2, 2018 4:32 PM