Reputation: 1
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
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
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
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
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