AesCryptoServiceProvider, проблемы с производительностью - PullRequest
2 голосов
/ 16 февраля 2012

У меня есть два очень простых метода для шифрования / дешифрования байта [] с помощью AesCryptoServiceProvider.Но я очень удивлен производительностью метода.

Я пытался зашифровать и расшифровать столько байтов [], сколько может мой компьютер, и в первые 4 секунды я мог зашифровать около 2000 раз, носледующие 4 секунды, около 1000, в следующие четыре секунды, около 500 ... в конце я могу выполнить около 80 операций за 4 секунды.Почему?

Посмотрите на код.

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;
        }
    }
}

1 Ответ

2 голосов
/ 16 февраля 2012

Зашифрованный текст на 16 байтов больше, чем открытый текст из-за заполнения.Поскольку вы используете зашифрованный текст одной итерации в качестве открытого текста следующей, длина буфера до сих пор линейно увеличивается с количеством итераций.Это объясняет замедление.

После 2000 итераций необходимо зашифровать 30 КБ за каждую итерацию, а после 6000 итераций необходимо зашифровать 100 КБ за итерацию ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...