我知道有人问过其他问题,但到目前为止没有一个问题提供解决方案,或者正是我所遇到的问题。

下面的类处理字符串的加密和解密,传入的密钥和向量始终相同。

加密和解密的字符串始终是数字,大多数工作,但偶尔在解密时失败(但仅在生产服务器上)。我应该提到本地和生产环境都在Windows Server 2003的IIS6中,使用该类的代码位于.ashx处理程序中。在生产服务器上失败的示例是“ 0000232668”

错误消息是

System.Security.Cryptography.CryptographicException:填充无效,无法删除。
位于System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte [] inputBuffer,Int32 inputOffset,Int32 inputCount,Byte []&outputBuffer,Int32 outputOffset,PaddingMode paddingMode,Boolean fLast)

而对于代码

 public class Aes
    {
        private byte[] Key;
        private byte[] Vector;

        private ICryptoTransform EncryptorTransform, DecryptorTransform;
        private System.Text.UTF8Encoding UTFEncoder;

        public Aes(byte[] key, byte[] vector)
        {
            this.Key = key;
            this.Vector = vector;

            // our encyption method
            RijndaelManaged rm = new RijndaelManaged();

            rm.Padding = PaddingMode.PKCS7;

            // create an encryptor and decyptor using encryption method. key and vector
            EncryptorTransform = rm.CreateEncryptor(this.Key, this.Vector);
            DecryptorTransform = rm.CreateDecryptor(this.Key, this.Vector);

            // used to translate bytes to text and vice versa
            UTFEncoder = new System.Text.UTF8Encoding();
        }

        /// Encrypt some text and return a string suitable for passing in a URL.
        public string EncryptToString(string TextValue)
        {
            return ByteArrToString(Encrypt(TextValue));
        }

        /// Encrypt some text and return an encrypted byte array.
        public byte[] Encrypt(string TextValue)
        {
            //Translates our text value into a byte array.
            Byte[] bytes = UTFEncoder.GetBytes(TextValue);
            Byte[] encrypted = null;

            //Used to stream the data in and out of the CryptoStream.
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(memoryStream, EncryptorTransform, CryptoStreamMode.Write))
                {
                    cs.Write(bytes, 0, bytes.Length);
                }

                encrypted = memoryStream.ToArray();
            }

            return encrypted;
        }

        /// The other side: Decryption methods
        public string DecryptString(string EncryptedString)
        {
            return Decrypt(StrToByteArray(EncryptedString));
        }

        /// Decryption when working with byte arrays.
        public string Decrypt(byte[] EncryptedValue)
        {
            Byte[] decryptedBytes = null;

            using (MemoryStream encryptedStream = new MemoryStream())
            {
                using (CryptoStream decryptStream = new CryptoStream(encryptedStream, DecryptorTransform, CryptoStreamMode.Write))
                {
                    decryptStream.Write(EncryptedValue, 0, EncryptedValue.Length);
                }

                decryptedBytes = encryptedStream.ToArray();
            }

            return UTFEncoder.GetString(decryptedBytes);
        }

        /// Convert a string to a byte array.  NOTE: Normally we'd create a Byte Array from a string using an ASCII encoding (like so).
        //      System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
        //      return encoding.GetBytes(str);
        // However, this results in character values that cannot be passed in a URL.  So, instead, I just
        // lay out all of the byte values in a long string of numbers (three per - must pad numbers less than 100).
        public byte[] StrToByteArray(string str)
        {
            if (str.Length == 0)
                throw new Exception("Invalid string value in StrToByteArray");

            byte val;
            byte[] byteArr = new byte[str.Length / 3];
            int i = 0;
            int j = 0;
            do
            {
                val = byte.Parse(str.Substring(i, 3));
                byteArr[j++] = val;
                i += 3;
            }
            while (i < str.Length);
            return byteArr;
        }

        // Same comment as above.  Normally the conversion would use an ASCII encoding in the other direction:
        //      System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
        //      return enc.GetString(byteArr);
        public string ByteArrToString(byte[] byteArr)
        {
            byte val;
            string tempStr = "";
            for (int i = 0; i <= byteArr.GetUpperBound(0); i++)
            {
                val = byteArr[i];
                if (val < (byte)10)
                    tempStr += "00" + val.ToString();
                else if (val < (byte)100)
                    tempStr += "0" + val.ToString();
                else
                    tempStr += val.ToString();
            }
            return tempStr;
        }


编辑:谢谢您的所有帮助,但是您的答案并没有发现问题,事实证明这很简单。我在一个服务器上生成一个加密的字符串,然后将其交给另一个服务器上的处理程序进行解密和处理,但是事实证明,加密结果在不同的服务器上运行时会有所不同,因此接收服务器无法对其进行解密。答案之一偶然地偶然发现了这个提示,这就是为什么我接受了

最佳答案

当加密和解密由于某种原因未使用相同的密钥或初始化向量时,有时会收到有关无效填充的消息。填充是添加到纯文本末尾的字节数,以使其达到用于密码工作的完整块数。在PKCS7填充中,每个字节等于添加的字节数,因此解密后始终可以将其删除。您的解密导致了一个字符串,其中最后n个字节不等于最后一个字节的值n(希望这句话有意义)。所以我会仔细检查您所有的钥匙。

或者,对于您的情况,我建议您确保为每个加密和解密操作创建并配置RijndaelManagedTransform的实例,并使用密钥和向量对其进行初始化。重用此变换对象很可能导致此问题,这意味着在首次使用后,它不再处于正确的初始状态。

09-04 16:54
查看更多