【问题标题】:Bad PKCS7 Padding error: Invalid length 106错误的 PKCS7 填充错误:长度无效 106
【发布时间】:2014-05-25 08:18:43
【问题描述】:

我正在尝试使用以下函数进行加密和解密,但是会导致错误的填充错误。

如果我将PaddingMode 设置为None,它会在日志中返回一些字母字符和随机符号。

我可能在设置正确的结构时遗漏了一些东西,如下所示:

  • 密码 Rijndael (AES)
  • 块大小 128 位(16 字节)
  • 模式 CBC(密码块链接)密钥
  • MD5 哈希密码
  • IV 与钥匙相同
  • 数据编码 Base64 字符
  • UTF-8 编码

任何解决此错误的帮助以及确保满足上述结构的任何帮助将不胜感激!谢谢

错误

CryptographicException: Bad PKCS7 padding. Invalid length 106.
Mono.Security.Cryptography.SymmetricTransform.ThrowBadPaddingException (PaddingMode padding, Int32 length, Int32 position) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/Mono.Security.Cryptography/SymmetricTransform.cs:363)
Mono.Security.Cryptography.SymmetricTransform.FinalDecrypt (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/Mono.Security.Cryptography/SymmetricTransform.cs:515)
Mono.Security.Cryptography.SymmetricTransform.TransformFinalBlock (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/Mono.Security.Cryptography/SymmetricTransform.cs:554)
System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Security.Cryptography/RijndaelManagedTransform.cs:94)
APIConnector.Decrypt (System.String toDecrypt) (at Assets/APIConnector.cs:85)

我的代码

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
using System.IO;

public class APIConnector : MonoBehaviour {

    // Use this for initialization
    void Start () {

        Debug.Log ("Starting API connector");


    }

    // Update is called once per frame
    void Update () {



    }

    static string data;
    string firstName="";
    string password="";

    void OnGUI() {

        firstName = GUILayout.TextField (firstName, GUILayout.Width(300));
        password = GUILayout.TextField (password, GUILayout.Width(300));

        if (GUILayout.Button ("Submit"))
                        submit ();

    }

    //Our functions

    void submit(){

        Debug.Log ("Name is: " + firstName + " encrypted is: " + Encrypt(firstName));
        Debug.Log ("Name is: " + firstName + " decrypted is: " + Decrypt(firstName));

    }


            public static string Encrypt (string toEncrypt)
            {
        byte[] keyArray = UTF8Encoding.UTF8.GetBytes ("SecretPassphrase");
                // 256-AES key
        int numBytes = System.Text.Encoding.UTF8.GetBytes(toEncrypt).Length;
        Debug.Log ("Bytes: " + numBytes);
                byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes (toEncrypt);
                RijndaelManaged rDel = new RijndaelManaged ();
                rDel.Key = keyArray;
                rDel.BlockSize = 128;
                rDel.Mode = CipherMode.CBC;
                // http://msdn.microsoft.com/en-us/library/system.security.cryptography.ciphermode.aspx
                rDel.Padding = PaddingMode.PKCS7;
                // better lang support
                ICryptoTransform cTransform = rDel.CreateEncryptor ();
                byte[] resultArray = cTransform.TransformFinalBlock (toEncryptArray, 0, toEncryptArray.Length);
                return Convert.ToBase64String (resultArray, 0, resultArray.Length);
            }

            public static string Decrypt (string toDecrypt)
            {
        byte[] keyArray = UTF8Encoding.UTF8.GetBytes ("SecretPassphrase");
                // AES-256 key
        byte[] encryptedData = System.Convert.FromBase64String(toDecrypt);
                //byte[] toEncryptArray = Convert.FromBase64String (toDecrypt);
                RijndaelManaged rDel = new RijndaelManaged ();
                rDel.Key = keyArray;
                rDel.BlockSize = 128;
                rDel.Mode = CipherMode.CBC;
                rDel.IV = rDel.Key;
                // http://msdn.microsoft.com/en-us/library/system.security.cryptography.ciphermode.aspx
                rDel.Padding = PaddingMode.PKCS7;
                // better lang support
                ICryptoTransform cTransform = rDel.CreateDecryptor ();
        byte[] resultArray = cTransform.TransformFinalBlock (encryptedData, 0, encryptedData.Length);
                return UTF8Encoding.UTF8.GetString (resultArray);
            }


}

【问题讨论】:

    标签: c# cryptography base64 rijndael rijndaelmanaged


    【解决方案1】:

    加密时您似乎没有设置 IV,因此将自动使用随机 IV。由于您在解密时正在设置 IV(并且它与加密期间使用的不同),因此第一个输出块将被损坏。如果消息足够短(

    像往常一样,我会注意到,在其他可能的问题中,使用相同的 IV 作为密钥是不好的做法,使用Encoding.UTF8.GetBytes() 进行密钥派生也是如此。

    【讨论】:

    • 感谢您的回答。我对 c# 还很陌生,甚至对 c# 加密也很陌生。您是否能够编辑您的答案以提供修复示例?谢谢!
    • @DT.DTDG - 您只需要将行:rDel.IV = rDel.Key; 添加到您的 Encrypt 方法中,与您的 Decrypt 方法中的位置相同。
    • 谢谢,非常感谢!接受了答案。您还提到了比使用“Encoding.UTF8.GetBytes()”更好的做法?随意权衡。
    • @DT.DTDG - 这可能是最好作为一个单独的问题提出的问题,尽管关于 SO 的主题可能有许多已经回答的问题。我建议研究 PBKDF2 关于从密码生成密钥的问题,我在这里的回答是:stackoverflow.com/questions/8041451/… 关于正确使用 IV。
    • 感谢@Iridum 的详细评论。干杯
    猜你喜欢
    • 2016-11-15
    • 1970-01-01
    • 2014-07-28
    • 2016-05-22
    • 1970-01-01
    • 2016-11-04
    • 2010-12-18
    • 1970-01-01
    • 2022-09-26
    相关资源
    最近更新 更多