我会尽量保持这个简短。
请保持良好,我一般不会写C#,最初写这个类的开发人员也不会。
无论如何简单的概念,用字符串和密钥调用EncryptString静态方法。然后使用加密的字符串和密钥调用DecryptString(与之前相同)。
这用于输出保存在文件系统上的文件,然后获取内容(通过另一个类)。
我遇到的问题是加密工作得非常好,但在解密时,我得到一个关于密钥的例外。在另一位开发人员也搔了几个小时之后,现在已经在我的头上刮了几个小时。
负责类:
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;
}
}
}
}
}
例外:
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()
答案 0 :(得分:2)
Rijndael / AES是一个块密码。
以128位(16个字符)块加密数据。加密填充用于确保消息的最后一个块始终是正确的大小。
您需要通过设置PaddingMode
显式设置加密和解密的填充尝试将PaddingMode设置为PaddingMode.PKCS7
此外,将您的密钥设为16个字符的块(16,32等)
答案 1 :(得分:0)
我认为该行
Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, iv.Length);
实际应该是
Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, cipher.Length);
您并未设置所有密码。
编辑以取悦学童:
这假定您通过提取前16个字节用作初始化向量并使用下一个32作为密钥来创建加密密钥。
如果你在两种情况下对称地使用了16,那么我还没有找到它为什么不起作用的线索。
答案 2 :(得分:0)
由于您似乎在尝试使用AES加密/解密,因此您应该在Nuget存储库(nuget.org)中查找现有库。有很多。
仅举几个受欢迎的名称:
SimpleAesEncryption https://github.com/ArtisanCode/SimpleAesEncryption
csharp-aes https://gitlab.com/czubehead/csharp-aes
每个README文件中都有一些使用示例。
答案 3 :(得分:-1)
使用相同的代码遇到同样的问题,感激地从http://mikaelkoskinen.net/post/encrypt-decrypt-string-asp-net-core借来。我发现如果原始明文超过16个字符(字节?),这将抛出上述异常。无论如何,修复是: 这一行:
var cipher = new byte[32];
应该是:
var cipher = new byte[fullCipher.Length - iv.Length];
然后,这一行:
Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, iv.Length);
应该是:
Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, cipher.Length);
正如凯文先前所说。