c#加密成功,不会解密

时间:2022-05-18 18:21:41

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.

请注意,我一般不写c#,最初编写这个类的开发人员也不写c#。

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).

不管怎样,这个概念很简单,用字符串和密钥调用EncryptString静态方法。然后使用加密的字符串和密钥调用解密字符串(与前面一样)。

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()

4 个解决方案

#1


1  

Rijndael/AES is a block cypher.

Rijndael/AES是一个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.

它对128位(16个字符)块中的数据进行加密。密码填充用于确保消息的最后一个块始终是正确的大小。

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

您需要通过设置PaddingMode显式地设置加密和解密的填充

Try setting PaddingMode to PaddingMode.PKCS7

试着将划桨模式设置为划桨模式。

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

另外,将键设置为16个字符块(16、32等)。

#2


0  

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.

这假定您创建了加密密钥,方法是提取前16个字节作为初始化向量,然后提取下32个字节作为密钥。

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

如果你在这两种情况下都对称地使用了16,那么我就不知道为什么它不工作了。

#3


0  

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.

由于您似乎正在尝试在AES中加密/解密,所以您应该在Nuget存储库(nuget.org)中查找现有的库。有很多。

Just to name a couple of popular ones:

举几个流行的例子:

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

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

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

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

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

他们的自述文件中有各自的用法示例。

#4


-1  

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:

刚刚遇到了同样的问题,使用相同的代码,感激地从http://mikaelkoskinen.net/post/encrypt-decrypt-string-asp-net-core中借用。我发现,如果原始的cleartext超过16个字符(字节?),就会抛出异常。不管怎样,解决办法是:

var cipher = new byte[32];

var cipher =新字节[32];

should be:

应该是:

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

var密码=新的字节[fullCipher]。长度- iv.Length];

Then, this line:

然后,这条线:

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

缓冲区。块拷贝(fullCipher, iv.Length, cipher, 0, iv.Length);

should be:

应该是:

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

缓冲区。块拷贝(全密码,iv.Length, cipher, 0, cipher.Length);

as noted by Kevin previously.

如Kevin先前所说。

#1


1  

Rijndael/AES is a block cypher.

Rijndael/AES是一个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.

它对128位(16个字符)块中的数据进行加密。密码填充用于确保消息的最后一个块始终是正确的大小。

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

您需要通过设置PaddingMode显式地设置加密和解密的填充

Try setting PaddingMode to PaddingMode.PKCS7

试着将划桨模式设置为划桨模式。

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

另外,将键设置为16个字符块(16、32等)。

#2


0  

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.

这假定您创建了加密密钥,方法是提取前16个字节作为初始化向量,然后提取下32个字节作为密钥。

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

如果你在这两种情况下都对称地使用了16,那么我就不知道为什么它不工作了。

#3


0  

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.

由于您似乎正在尝试在AES中加密/解密,所以您应该在Nuget存储库(nuget.org)中查找现有的库。有很多。

Just to name a couple of popular ones:

举几个流行的例子:

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

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

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

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

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

他们的自述文件中有各自的用法示例。

#4


-1  

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:

刚刚遇到了同样的问题,使用相同的代码,感激地从http://mikaelkoskinen.net/post/encrypt-decrypt-string-asp-net-core中借用。我发现,如果原始的cleartext超过16个字符(字节?),就会抛出异常。不管怎样,解决办法是:

var cipher = new byte[32];

var cipher =新字节[32];

should be:

应该是:

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

var密码=新的字节[fullCipher]。长度- iv.Length];

Then, this line:

然后,这条线:

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

缓冲区。块拷贝(fullCipher, iv.Length, cipher, 0, iv.Length);

should be:

应该是:

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

缓冲区。块拷贝(全密码,iv.Length, cipher, 0, cipher.Length);

as noted by Kevin previously.

如Kevin先前所说。