1

所以我使用了一些我在网上看到的 AES 加密/解密方法,我做了一些修改。方法写在下面。

public void EncryptStringAES(Object threadContext)
        {
            if (string.IsNullOrEmpty(inputData))
            {
                outputData = string.Empty;
                doneEventProperty.Set();
                return;
            }
            if (string.IsNullOrEmpty(sharedSecretData))
                throw new ArgumentNullException("sharedSecret");

            string outStr = null;
            RijndaelManaged aesAlg = null;

            try
            {
                Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecretData, saltData);

                aesAlg = new RijndaelManaged();
                aesAlg.Padding = PaddingMode.PKCS7;
                aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);

                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    msEncrypt.Write(BitConverter.GetBytes(aesAlg.IV.Length), 0, sizeof(int));
                    msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length);
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            swEncrypt.Write(inputData);
                        }
                    }
                    outStr = Convert.ToBase64String(msEncrypt.ToArray());
                }
            }
            finally
            {
                if (aesAlg != null)
                    aesAlg.Clear();
            }

            outputData = outStr;
            doneEventProperty.Set();
        }

        public void DecryptStringAES(Object threadContext)
        {
            if (string.IsNullOrEmpty(inputData))
            {
                outputData = string.Empty;
                doneEventProperty.Set();
                return;
            }
            if (string.IsNullOrEmpty(sharedSecretData))
                throw new ArgumentNullException("sharedSecret");

            RijndaelManaged aesAlg = null;

            string plaintext = null;

            try
            {
                Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecretData, saltData);

                byte[] bytes = Convert.FromBase64String(inputData.ToString());
                using (MemoryStream msDecrypt = new MemoryStream(bytes))
                {
                    aesAlg = new RijndaelManaged();
                    aesAlg.Padding = PaddingMode.PKCS7;
                    aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
                    aesAlg.IV = ReadByteArray(msDecrypt);

                    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }
            finally
            {
                if (aesAlg != null)
                    aesAlg.Clear();
            }

            outputData = plaintext;
            doneEventProperty.Set();
        }

我对其进行了修改,以便使用这些代码的对象可以在线程池中排队,并希望使整个加密/解密过程更快。在我修改线程代码之前,它可以工作。但是我添加线程功能后,总是遇到这个错误:

输入不是有效的 Base-64 字符串,因为它包含非 base 64 字符、两个以上的填充字符或填充字符中的非法字符。

当我解密我加密的字符串时,总是会发生这种情况。以下是我加密的数据示例。

EAAAALlZu0F1HmtQ0pNO/xPoOBgr4zRJvhIyr43van78dDED
EAAAAIvlxL+vtqhAf3HCFpRc6xeb76KFqhfe6Tbu1SN7LZH1

我已经检查了 Base64 字符串的要求,这些几乎符合要求。我还尝试了我在 stackoverflow 中看到的所有可能的答案,但仍然无济于事。更糟糕的是,有时有效,有时无效。我在这里没有选择,所以有人可以帮助我吗?

更新:

下面是一些使用上述方法的代码。

class AESHandler
    {
        private string outputDataProperty;
        private string inputDataProperty;
        private byte[] saltDataProperty;
        private string sharedSecretDataProperty;
        private ManualResetEvent doneEventProperty;
        private Guid signatureDataProperty;

        public string outputData
        {
            get
            {
                return outputDataProperty;
            }
            private set
            {
                outputDataProperty = value;
            }
        }

        private string inputData
        {
            get
            {
                return inputDataProperty;
            }
            set
            {
                inputDataProperty = value;
            }
        }

        private byte[] saltData
        {
            get
            {
                return saltDataProperty;
            }
            set
            {
                saltDataProperty = value;
            }
        }

        private string sharedSecretData
        {
            get
            {
                return sharedSecretDataProperty;
            }
            set
            {
                sharedSecretDataProperty = value;
            }
        }

        public ManualResetEvent doneEvent
        {
            get
            {
                return doneEventProperty;
            }
        }

        public Guid signatureData
        {
            get
            {
                return signatureDataProperty;
            }
            private set
            {
                signatureDataProperty = value;
            }
        }


        private byte[] ReadByteArray(Stream s)
        {
            byte[] rawLength = new byte[sizeof(int)];
            if (s.Read(rawLength, 0, rawLength.Length) != rawLength.Length)
            {
                throw new SystemException("Stream did not contain properly formatted byte array");
            }

            byte[] buffer = new byte[BitConverter.ToInt32(rawLength, 0)];
            if (s.Read(buffer, 0, buffer.Length) != buffer.Length)
            {
                throw new SystemException("Did not read byte array properly");
            }

            return buffer;
        }


        public void EncryptStringAES(Object threadContext)
        {
            if (string.IsNullOrEmpty(inputData))
            {
                outputData = string.Empty;
                doneEventProperty.Set();
                return;
            }
            if (string.IsNullOrEmpty(sharedSecretData))
                throw new ArgumentNullException("sharedSecret");

            string outStr = null;
            RijndaelManaged aesAlg = null;

            try
            {
                Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecretData, saltData);

                aesAlg = new RijndaelManaged();
                aesAlg.Padding = PaddingMode.PKCS7;
                aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);

                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    msEncrypt.Write(BitConverter.GetBytes(aesAlg.IV.Length), 0, sizeof(int));
                    msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length);
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            swEncrypt.Write(inputData);
                        }
                    }
                    outStr = Convert.ToBase64String(msEncrypt.ToArray());
                }
            }
            finally
            {
                if (aesAlg != null)
                    aesAlg.Clear();
            }

            outputData = outStr;
            doneEventProperty.Set();
        }

        public void DecryptStringAES(Object threadContext)
        {
            if (string.IsNullOrEmpty(inputData))
            {
                outputData = string.Empty;
                doneEventProperty.Set();
                return;
            }
            if (string.IsNullOrEmpty(sharedSecretData))
                throw new ArgumentNullException("sharedSecret");

            RijndaelManaged aesAlg = null;

            string plaintext = null;

            try
            {
                Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecretData, saltData);

                byte[] bytes = Convert.FromBase64String(inputData.ToString());
                using (MemoryStream msDecrypt = new MemoryStream(bytes))
                {
                    aesAlg = new RijndaelManaged();
                    aesAlg.Padding = PaddingMode.PKCS7;
                    aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
                    aesAlg.IV = ReadByteArray(msDecrypt);

                    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }
            finally
            {
                if (aesAlg != null)
                    aesAlg.Clear();
            }

            outputData = plaintext;
            doneEventProperty.Set();
        }


        public AESHandler(string input, string sharedSecret, Guid signature, byte[] salt)
        {
            if (!string.IsNullOrEmpty(input))
            {
                inputData = input;
            }
            else
            {
                inputData = string.Empty;
            }

            sharedSecretData = sharedSecret;
            signatureData = signature;
            saltData = salt;
            doneEventProperty = new ManualResetEvent(false);
        }
    }

那是处理加密/解密过程的实际代码。下面的代码创建了上面类的一个实例,并在线程池中排队。

public sealed partial class AESCore
    {
        private static List<AESHandler> encryptThreadList = new List<AESHandler>();

        public static Guid AESQueueEncrypt(string input, string sharedSecret)
        {
            return AESQueueEncrypt(input, sharedSecret, EncryptionCore._salt);
        }

        public static Guid AESQueueEncrypt(string input, string sharedSecret, byte[] salt)
        {
            Guid queueID = Guid.NewGuid();

            AESHandler handle = new AESHandler(input, sharedSecret, queueID, EncryptionCore._salt);

            ThreadPool.QueueUserWorkItem(handle.EncryptStringAES);

            encryptThreadList.Add(handle);

            return queueID;
        }

        public static Guid AESQueueDecrypt(string input, string sharedSecret)
        {
            return AESQueueDecrypt(input, sharedSecret, EncryptionCore._salt);
        }

        public static Guid AESQueueDecrypt(string input, string sharedSecret, byte[] salt)
        {
            Guid queueID = Guid.NewGuid();

            AESHandler handle = new AESHandler(input, sharedSecret, queueID, EncryptionCore._salt);

            ThreadPool.QueueUserWorkItem(handle.DecryptStringAES);

            encryptThreadList.Add(handle);

            return queueID;
        }

        public static string AESFetchData(Guid signature)
        {
            var data = encryptThreadList.Where(s => s.signatureData == signature).FirstOrDefault();
            string output = data.outputData;
            encryptThreadList.Remove(data);

            return output;
        }

        public static void AESProcessWait()
        {
            foreach (var d in encryptThreadList)
            {
                d.doneEvent.WaitOne();
            }
        }
    }

用法是这样的:

加密

Guid strnNameLast = Encryption.AESCore.AESQueueEncrypt(user.strnNameLast, publicKeyToken);
Guid strnNameFirst = Encryption.AESCore.AESQueueEncrypt(user.strnNameFirst, publicKeyToken);

Encryption.AESCore.AESProcessWait();

string strnNameLastEncrypted = Encryption.AESCore.AESFetchData(strnNameLast);
string strnNameFirstEncrypted = Encryption.AESCore.AESFetchData(strnNameFirst);

解密:

Guid strnNameLast = Encryption.AESCore.AESQueueDecrypt(user.strnNameLast, publicKeyToken);
Guid strnNameFirst = Encryption.AESCore.AESQueueDecrypt(user.strnNameFirst, publicKeyToken);

Encryption.AESCore.AESProcessWait();

string strnNameLastDecrypted = Convert.ToString(Encryption.AESCore.AESFetchData(strnNameLast));
string strnNameFirstDecrypted = Convert.ToString(Encryption.AESCore.AESFetchData(strnNameFirst));
4

1 回答 1

0

我终于找到了问题所在。实际上,我在每个字符串属性上设计了一个简单的 Blowfish 实现。显然,解密中存在一些我现在无法解释的问题(尽管根据调试器的输出是有效的 base-64 字符串)。我删除了加密并且它起作用了。

于 2013-05-16T08:36:24.790 回答