Шифрования/дешифрования данных


Я пытаюсь работать с некоторыми шифрования/дешифрования данных. Для меня это было немного потрудиться, чтобы заставить его работать с буферами, а что нет.

Это код, который я придумал:

public static string Encrypt(string dataToEncrypt, byte[] publicKeyInfo)
{
    //// Our bytearray to hold all of our data after the encryption
    byte[] encryptedBytes = new byte[0];
    using (var rsa = new RSACryptoServiceProvider())
    {
        try
        {
            var encoder = new UTF8Encoding();

            byte[] encryptThis = encoder.GetBytes(dataToEncrypt);

            //// Importing the public key
            rsa.ImportCspBlob(publicKeyInfo);

            int blockSize = (rsa.KeySize / 8) - 32;

            //// buffer to write byte sequence of the given block_size
            byte[] buffer = new byte[blockSize];

            byte[] encryptedBuffer = new byte[blockSize];

            //// Initializing our encryptedBytes array to a suitable size, depending on the size of data to be encrypted
            encryptedBytes = new byte[encryptThis.Length + blockSize - (encryptThis.Length % blockSize) + 32];

            for (int i = 0; i < encryptThis.Length; i += blockSize)
            {
                //// If there is extra info to be parsed, but not enough to fill out a complete bytearray, fit array for last bit of data
                if (2 * i > encryptThis.Length && ((encryptThis.Length - i) % blockSize != 0))
                {
                    buffer = new byte[encryptThis.Length - i];
                    blockSize = encryptThis.Length - i;
                }

                //// If the amount of bytes we need to decrypt isn't enough to fill out a block, only decrypt part of it
                if (encryptThis.Length < blockSize)
                {
                    buffer = new byte[encryptThis.Length];
                    blockSize = encryptThis.Length;
                }

                //// encrypt the specified size of data, then add to final array.
                Buffer.BlockCopy(encryptThis, i, buffer, 0, blockSize);
                encryptedBuffer = rsa.Encrypt(buffer, false);
                encryptedBuffer.CopyTo(encryptedBytes, i);
            }
        }
        catch (CryptographicException e)
        {
            Console.Write(e);
        }
        finally
        {
            //// Clear the RSA key container, deleting generated keys.
            rsa.PersistKeyInCsp = false;
        }
    }
    //// Convert the byteArray using Base64 and returns as an encrypted string
    return Convert.ToBase64String(encryptedBytes);
}




public static string Decrypt(string dataToDecrypt, byte[] privateKeyInfo)
{
    //// The bytearray to hold all of our data after decryption
    byte[] decryptedBytes;

    //Create a new instance of RSACryptoServiceProvider.
    using (var rsa = new RSACryptoServiceProvider())
    {
        try
        {
            byte[] bytesToDecrypt = Convert.FromBase64String(dataToDecrypt);

            //// Import the private key info
            rsa.ImportCspBlob(privateKeyInfo);

            //// No need to subtract padding size when decrypting
            int blockSize = rsa.KeySize / 8;

            //// buffer to write byte sequence of the given block_size
            byte[] buffer = new byte[blockSize];

            //// buffer containing decrypted information
            byte[] decryptedBuffer = new byte[blockSize];

            //// Initializes our array to make sure it can hold at least the amount needed to decrypt.
            decryptedBytes = new byte[dataToDecrypt.Length];

            for (int i = 0; i < bytesToDecrypt.Length; i += blockSize)
            {
                if (2 * i > bytesToDecrypt.Length && ((bytesToDecrypt.Length - i) % blockSize != 0))
                {
                    buffer = new byte[bytesToDecrypt.Length - i];
                    blockSize = bytesToDecrypt.Length - i;
                }

                //// If the amount of bytes we need to decrypt isn't enough to fill out a block, only decrypt part of it
                if (bytesToDecrypt.Length < blockSize)
                {
                    buffer = new byte[bytesToDecrypt.Length];
                    blockSize = bytesToDecrypt.Length;
                }

                Buffer.BlockCopy(bytesToDecrypt, i, buffer, 0, blockSize);
                decryptedBuffer = rsa.Decrypt(buffer, false);
                decryptedBuffer.CopyTo(decryptedBytes, i);
            }
        }
        finally
        {
            //// Clear the RSA key container, deleting generated keys.
            rsa.PersistKeyInCsp = false;
        }
    }

    //// We encode each byte with UTF8 and then write to a string while trimming off the extra empty data created by the overhead.
    var encoder = new UTF8Encoding();
    return encoder.GetString(decryptedBytes).TrimEnd(new[] { '\0' });

}

Я пытался увидеть, если я мог бы разбить его, но в моих усилий, чтобы сделать так, я придумал, что я считал бы более сложный способ (высшее цикломатическая сложность). У меня было много , если с заявлениями все вдруг, приходится заботиться о безопасности, но и обработка кодировку из utf8 или base64.



2265
5
задан 9 декабря 2011 в 06:12 Источник Поделиться
Комментарии
2 ответа

У меня нет никаких комментариев на стороне криптографии, но у меня есть несколько общих вопросов программирования:


  • Это не обязательно иметь четыре Слэш персонажи для встроенных комментариев, вам нужно только два.

  • Нет необходимости инициализировать encryptedBytes такие как пустой массив, так как вы повторно инициализировать его позже.

  • Вы должны использовать систему.Текст.Кодирование.В utf8 вместо создания utf8encoding дополнительно вручную.

  • Может быть, стоит разделить встроенные расчеты внутри условных и массив для удобства чтения (строки 24, при инициализации encryptedBytes массив, а строка 29, при проверке 'дополнительная информация, которая будет проанализирована').

  • Хотя я поддерживаю использование места для комментариев, чтобы объяснить алгоритм или шагов программы (особенно если это сложный алгоритм), я думаю, что вы, возможно, пошел немного перебор в некоторых местах. Как таковой, это может быть идея, чтобы удалить более очевидные комментарии, такие как "наши ByteArray для хранения всех наших данных после шифрования" - имя переменной уже указывает на это. Это не главный пункт, но это поможет с длиной вашей методе.

  • Касаемо обработки исключений, я бы предложил прекращение выполнения кода, когда вы достигнете поймать положение, как вы не хотите, чтобы программа и дальше с этим алгоритмом, если она не смогла. Кроме того, я хотел бы предложить, ломая код внутри попробовать пункт немного больше, так что вы должны только попробовать-поймать блоков, окружающих точных линий, что может привести к CryptographicException. Это не важно, но это помогает читателю легко идентифицировать строку(ы), которые могли бы эту проблему.

Кроме вышеуказанных пунктов, сам код выглядит довольно хорошо структурировано и логично.

4
ответ дан 10 декабря 2011 в 10:12 Источник Поделиться

Вы используете RSA как блочное шифрование в режиме ECB. Это не так, как он обычно используется. Если у вас есть очень веская причина, в противном случае, вы должны просто сделать одну шифрования RSA, безопасных случайных ключей для блочного шифрования (например, AES) и затем использовать этот ключ, чтобы зашифровать сообщение.

Поскольку вы преобразование строки к строке, очевидно, что ни памяти, ни задержки-это вопрос, так что вы можете избежать много возиться с байт[]с помощью потоке MemoryStream и поток cryptostream. Вы можете также использовать кодирование.В utf8 , чтобы упростить кодирование/декодирование, шаг слегка.

4
ответ дан 9 декабря 2011 в 09:12 Источник Поделиться