AesCryptoServiceProvider

AesCryptoServiceProvider

我有两种使用AesCryptoServiceProvider加密/解密byte []的非常简单的方法。但是我对该方法的性能感到非常惊讶。

我尝试加密和解密计算机所能使用的尽可能多的字节[],并且在开始的4秒钟内可以加密大约2000次,但是在接下来的4秒钟内,大约加密1000次,在接下来的4秒钟内,加密大约500次...最后,我每4秒可以进行约80次操作。为什么?

看代码。

namespace Encrypttest
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Security.Cryptography;
    using System.IO;
    using System.Globalization;

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("AES provider");

            var key = GenerateKey();
            DateTime now = DateTime.Now.AddSeconds(2);
            var toStop = now.AddSeconds(120);
            long operations = 0;

            byte[] buffer = new byte[16];
            byte[] result = new byte[buffer.Length];
            for (int i = 0; i < buffer.Length; i++)
            {
                buffer[i] = 2;
            }

            for (long i = 0; i < 10000000; i++)
            {
                result = Encrypt(buffer, key);
                Decrypt(result, key);
                buffer = result;
                operations++;

                if (DateTime.Now > now)
                {
                    Console.WriteLine(now.ToLongTimeString() + ";" + operations + ";" + System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64);
                    operations = 0;
                    now = DateTime.Now.AddSeconds(2);
                }

                if (toStop < DateTime.Now)
                {
                    break;
                }
            }
        }

        /// <summary>
        /// Encrypts the specified data.
        /// </summary>
        /// <param name="data">The data to encrypt</param>
        /// <param name="key">The key to encrypt data.</param>
        /// <returns>
        /// The data encrypted.
        /// </returns>
        public static byte[] Encrypt(byte[] data, SymmetricKey key)
        {
            if (data == null || data.Length == 0)
            {
                throw new ArgumentNullException("data");
            }

            if (key == null)
            {
                throw new ArgumentNullException("key");
            }


            using (AesCryptoServiceProvider providerInLine = new AesCryptoServiceProvider())
            {
                using (MemoryStream stream = new MemoryStream())
                {
                    using (ICryptoTransform cryptoEncryptor = providerInLine.CreateEncryptor(key.Key, key.IV))
                    {
                        using (CryptoStream writerStream = new CryptoStream(stream, cryptoEncryptor, CryptoStreamMode.Write))
                        {
                            writerStream.Write(data, 0, data.Length);
                            writerStream.FlushFinalBlock();
                            return stream.ToArray();
                        }
                    }
                }
            }

        }


        /// <summary>
        /// Decrypts the specified data.
        /// </summary>
        /// <param name="data">The data to decrypt</param>
        /// <param name="key">The key to decrypt data.</param>
        /// <returns>
        /// The data encrypted.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
        public static byte[] Decrypt(byte[] data, SymmetricKey key)
        {
            if (data == null || data.Length == 0)
            {
                throw new ArgumentNullException("data");
            }

            if (key == null)
            {
                throw new ArgumentNullException("key");
            }


            using (AesCryptoServiceProvider provider = new AesCryptoServiceProvider())
            {
                using (MemoryStream memStreamEncryptData = new MemoryStream(data))
                {
                    using (ICryptoTransform cryptoDecryptor = provider.CreateDecryptor(key.Key, key.IV))
                    {
                        using (CryptoStream stream = new CryptoStream(memStreamEncryptData, cryptoDecryptor, CryptoStreamMode.Read))
                        {
                            byte[] plainTextBytes = new byte[data.Length];
                            stream.Read(plainTextBytes, 0, plainTextBytes.Length);
                            return plainTextBytes;
                        }
                    }
                }
            }

        }

        /// <summary>
        /// Generates a random key and initialization vector
        /// </summary>
        /// <returns>
        /// The key and initialization vector.
        /// </returns>
        public static SymmetricKey GenerateKey()
        {
            using (AesCryptoServiceProvider provider = new AesCryptoServiceProvider())
            {
                provider.GenerateKey();
                SymmetricKey key = new SymmetricKey(provider.Key, provider.IV);
                return key;
            }
        }
    }

    public class SymmetricKey
    {
        /// <summary>
        /// The key.
        /// </summary>
        private byte[] key;

        /// <summary>
        /// The initialization vector.
        /// </summary>
        private byte[] iv;

        /// <summary>
        /// Initializes a new instance of the <see cref="SymmetricKey"/> class.
        /// </summary>
        public SymmetricKey()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SymmetricKey"/> class.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="iv">The iv.</param>
        public SymmetricKey(byte[] key, byte[] iv)
        {
            this.Init(key, iv);
        }

        /// <summary>
        /// Gets the key.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Byte[] is what the providers need")]
        public byte[] Key
        {
            get { return this.key; }
        }

        /// <summary>
        /// Gets the iv.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Byte[] is what the providers need")]
        public byte[] IV
        {
            get { return this.iv; }
        }

        /// <summary>
        /// Loads the specified key and iv
        /// </summary>
        /// <param name="newKey">The key.</param>
        /// <param name="newIV">The iv.</param>
        public void Init(byte[] newKey, byte[] newIV)
        {
            this.key = newKey;
            this.iv = newIV;
        }
    }
}

最佳答案

由于填充,密文比纯文本大16个字节。由于您将一次迭代的密文用作下一次的明文,因此缓冲区的长度随到目前为止的迭代次数线性增长。这解释了减速。

在2000次迭代之后,它需要每次迭代加密30kB,在6000次迭代之后,它需要每次迭代加密100kB ...

关于c# - AesCryptoServiceProvider,性能问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9307932/

10-09 03:20