C#解密中的加密解密不起作用

时间:2018-11-29 05:48:08

标签: c# encryption

我有一个Java代码,必须在C#中对其进行如下转换

加密:

 public String encrypt(String value)
    {
        System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
        AesManaged tdes = new AesManaged();
        tdes.Key = UTF8.GetBytes(securityKey);
        tdes.Mode = CipherMode.ECB;
        tdes.Padding = PaddingMode.PKCS7;
        ICryptoTransform crypt = tdes.CreateEncryptor();
        byte[] plain = Encoding.UTF8.GetBytes(value);
        byte[] cipher = crypt.TransformFinalBlock(plain, 0, plain.Length);
        String encryptedText = Convert.ToBase64String(cipher);
        return encryptedText;
    }

现在我正在尝试编写冲销过程

public String decrypt(String value)
    {                   
        System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
        AesManaged tdes = new AesManaged();
        tdes.Key = UTF8.GetBytes(securityKey);
        tdes.Mode = CipherMode.ECB;
        tdes.Padding = PaddingMode.PKCS7;
        ICryptoTransform crypt = tdes.CreateDecryptor();
        byte[] plain = Encoding.UTF8.GetBytes(value);
        byte[] cipher = crypt.TransformFinalBlock(plain, 0, plain.Length);
        String encryptedText = Convert.ToBase64String(cipher);
        return encryptedText;
    }

但是逆转不起作用。

错误:类型异常

  

mscorlib.dll中发生了“ System.Security.Cryptography.CryptographicException”,但未在用户代码中处理

     

其他信息:填充无效,无法删除。

堆栈跟踪:

  

System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte [] inputBuffer,Int32 inputOffset,Int32 inputCount,Byte []&outputBuffer,Int32 outputOffset,PaddingMode paddingMode,Boolean fLast)      在System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte [] inputBuffer,Int32 inputOffset,Int32 inputCount)      位于e:\ TestApplication \ Redis \ redis2 \ redis2 \ Crypto \ AESECBPKCS5PaddingEncryptor.cs:line 53中的redis2.Crypto.AESECBPKCS5PaddingEncryptor.decrypt(String value)      在redis2.WebForm1.Page_Load(Object sender,EventArgs e)中的e:\ TestApplication \ Redis \ redis2 \ redis2 \ WebForm1.aspx.cs:第14行      在System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender,EventArgs e)      在System.Web.UI.Control.OnLoad(EventArgs e)      在System.Web.UI.Control.LoadRecursive()      在System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint,Boolean includeStagesAfterAsyncPoint)

更新1

 public String decrypt(String value)
    {                   
        System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
        AesManaged tdes = new AesManaged();
        tdes.Key = UTF8.GetBytes(securityKey);
        tdes.Mode = CipherMode.ECB;
        tdes.Padding = PaddingMode.PKCS7;
        ICryptoTransform crypt = tdes.CreateDecryptor();
       // value = Convert.FromBase64String(value);
        byte[] plain = Convert.FromBase64String(value);
        byte[] cipher = crypt.TransformFinalBlock(plain, 0, plain.Length);
        String encryptedText = Convert.ToBase64String(cipher);
        return encryptedText;
    }

2 个答案:

答案 0 :(得分:2)

使用加密和解密代码,至少要通过加密代码对数据执行另一次 转换,这种情况并不罕见。编写解密代码时,需要确保以相反的顺序应用每个转换的相反方向。

因此,在您的加密代码中,我们有

[string] --UTF8--> [byte[]] --Encrypt--> [byte[]] --Base64--> [string]

有了您的原始解密代码,我们就有了

[string] --UTF8--> [byte[]] --Decrypt--> [byte[]] --Base64--> [string]

但是,这并不是按照相反的顺序进行反向转换。让我们将它们彼此放在一起,将解密过程颠倒一遍:

[string] --UTF8--> [byte[]] --Encrypt--> [byte[]] --Base64--> [string] --|
                                                                         |
[gnirts] <--46esaB-- [[]etyb] <--tpyrceD-- [[]etyb] <--8FTU-- [gnirts] <-|

(末尾的额外箭头表示从string返回到将其作为参数提供给encrypt的其他代码转移了decrypt)。

当我们应该做一些与撤消Base 64编码有关的事情时,我们正在做与UTF8相关的事情,而当我们应该做与UTF8相关的事情时,我们在做与Base64相关的事情。

因此,更正的方法是将解密后的传入字符串以{64为基数解码为decrypt,并在解密后以UTF8解码结果:

public String decrypt(String value)
{                   
    System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
    AesManaged tdes = new AesManaged();
    tdes.Key = UTF8.GetBytes(securityKey);
    tdes.Mode = CipherMode.ECB;
    tdes.Padding = PaddingMode.PKCS7;
    ICryptoTransform crypt = tdes.CreateDecryptor();
    byte[] plain = Convert.FromBase64String(value);
    byte[] cipher = crypt.TransformFinalBlock(plain, 0, plain.Length);
    String encryptedText = Encoding.UTF8.GetString(cipher);
    return encryptedText;
}

我通常建议人们在进行解密时,他们尽可能以简单开始,然后从那里开始。首先要做的最简单的事情是接受byte[]并返回byte[](对于这两种方法),并且可以成功地往返字节数组。 然后添加对 纯文本或密文(但不能同时包含两者)的字符串编码支持。确认往返。然后添加另一种编码。拉链层。等

(这也是我建议使用语言1进行加密的策略,使用语言2进行解密。首先编写可以在两种语言之间进行所有必要转换并成功往返的编写方法,然后然后进行他们可以互操作)

答案 1 :(得分:2)

tdes.Key = UTF8.GetBytes(securityKey);

从字符串获取密钥始终是错误的方法。

  • 输入密码后,使用Rfc2898DeriveBytes
  • 当您需要传递随机二进制密钥时,请使用Convert.FromBase64String()

String encryptedText = Encoding.UTF8.GetString(cipher);

将二进制数据作为文本传输是错误的方法。因为UTF8具有转义序列来编码非ASCII令牌,所以这甚至不会往返。而且你不能将它们分解。

使用Convert.ToBase64String(byte[])