Matt Johnson
Matt Johnson

Reputation: 1

C# encrypts successfully, won't decrypt

I'll try to keep this as brief as possible.

Please be nice, I don't generally write C#, and neither does the developer who initially wrote this class.

Anyway simple enough concept, call the EncryptString static method with the string and the key. Then call DecryptString with the encrypted string and the key (same as before).

This is used to output a file which is saved on the filesystem, and then get the contents (via another class).

The problem I'm having is that encryption is working perfectly well, but on decryption I get an exception about the key. Been scratching my head for a couple of hours on this now, after the other developer also scratching his head for a couple of hours.

Class Responsible:

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

namespace MySoftwarePackage.Pakages
{
    public class Encrypt
    {

        public static string DecryptString(string cipherText, string encryptionKey)
        {

            Console.WriteLine("ENCRYPTION KEY: " + encryptionKey);

            var fullCipher = Convert.FromBase64String(cipherText);

            var iv = new byte[16];
            var cipher = new byte[32];

            Buffer.BlockCopy(fullCipher, 0, iv, 0, iv.Length);
            Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, iv.Length);
            var key = Encoding.UTF8.GetBytes(encryptionKey);

            Console.WriteLine("ENCODED: " + key);

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

Exceptions:

fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HL83721K735O": An unhandled exception was thrown by the application.
System.Security.Cryptography.CryptographicException: Specified padding mode is not valid for this algorithm.
   at Internal.Cryptography.UniversalCryptoDecryptor.DepadBlock(Byte[] block, Int32 offset, Int32 count)
   at Internal.Cryptography.UniversalCryptoDecryptor.UncheckedTransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   at Internal.Cryptography.UniversalCryptoTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   at System.Security.Cryptography.CryptoStream.FlushFinalBlock()
   at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()
   at System.IO.StreamReader.Dispose(Boolean disposing)
   at System.IO.TextReader.Dispose()
   at MySoftwarePackage.Pakages.Encrypt.DecryptString(String cipherText, String encryptionKey) in /Users/matt/SoftwarePackage-desktop/src/api/Pakages/Encrypt.cs:line 39
   at MySoftwarePackage.Pakages.DataRetriever.UnencryptData() in /Users/matt/SoftwarePackage-desktop/src/api/Pakages/DataRetriever.cs:line 39
   at MySoftwarePackage.Pakages.DataRetriever..ctor(String entityType, String entityId) in /Users/matt/SoftwarePackage-desktop/src/api/Pakages/DataRetriever.cs:line 24
   at MySoftwarePackage.Controllers.BusinessController.TestGet() in /Users/matt/SoftwarePackage-desktop/src/api/Controllers/BusinessController.cs:line 292
   at lambda_method(Closure , Object , Object[] )
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__27.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__25.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextResourceFilter>d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ResourceExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeAsync>d__20.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.<Invoke>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame`1.<RequestProcessingAsync>d__2.MoveNext()

Upvotes: 0

Views: 3512

Answers (4)

Adel Helal
Adel Helal

Reputation: 670

Since it seems you are attempting to encrypt/decrypt in AES you should probably look for an existing library in the Nuget repository (nuget.org). There are plenty of them.

Just to name a couple of popular ones:

SimpleAesEncryption https://github.com/ArtisanCode/SimpleAesEncryption

csharp-aes https://gitlab.com/czubehead/csharp-aes

There are examples of usage for each in their README files.

Upvotes: 0

Designysis
Designysis

Reputation: 9

Just ran into the same problem, with identical code, gratefully borrowed from http://mikaelkoskinen.net/post/encrypt-decrypt-string-asp-net-core. I found that this would throw the exception noted above if the original cleartext was more than 16 characters (bytes?). Anyway, the fix is: This line:

var cipher = new byte[32];

should be:

var cipher = new byte[fullCipher.Length - iv.Length];

Then, this line:

Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, iv.Length);

should be:

Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, cipher.Length);

as noted by Kevin previously.

Upvotes: -1

Kevin Ford
Kevin Ford

Reputation: 270

I think the line

     Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, iv.Length);

should actually be

     Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, cipher.Length);

You aren't setting all of cipher.

Edit to please the pedant:

This assumes that you created your encryption key by extracting the first 16 bytes to use as the initialisation vector and the next 32 to use as your key.

If you symmetrically used 16 in both cases then I haven't got a clue why it isn't working.

Upvotes: 0

Alander
Alander

Reputation: 813

Rijndael/AES is a block cypher.

It encrypts data in 128 bit (16 character) blocks. Cryptographic padding is used to make sure that last block of the message is always the correct size.

You need to explicitly set the padding for both encryption and decryption by setting PaddingMode

Try setting PaddingMode to PaddingMode.PKCS7

Also, make your key to be of 16 characters blocks (16, 32, etc.)

Upvotes: 2

Related Questions