Симметричное шифрование / дешифрование в .NET - PullRequest
12 голосов
/ 28 января 2010

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

Обновление: Мне бы очень хотелось увидеть код, а не просто ссылки. Большое спасибо!

Ответы [ 6 ]

14 голосов
/ 28 января 2010

Посмотрите на пример кода внизу этой страницы .

Скопируйте его сюда:

int Rfc2898KeygenIterations= 100;
int AesKeySizeInBits = 128;
String Password = "VerySecret!";
byte[] Salt = new byte[16];
System.Random rnd = new System.Random(); 
rnd.NextBytes(Salt);
byte[] rawPlaintext = System.Text.Encoding.Unicode.GetBytes("This is all clear now!");
byte[] cipherText= null;
byte[] plainText= null;
using (Aes aes = new AesManaged())
{
    aes.Padding = PaddingMode.PKCS7;
    aes.KeySize = AesKeySizeInBits;
    int KeyStrengthInBytes= aes.KeySize/8;
    System.Security.Cryptography.Rfc2898DeriveBytes rfc2898 =
        new System.Security.Cryptography.Rfc2898DeriveBytes(Password, Salt, Rfc2898KeygenIterations);
    aes.Key = rfc2898.GetBytes(KeyStrengthInBytes);
    aes.IV = rfc2898.GetBytes(KeyStrengthInBytes);
    using (MemoryStream ms = new MemoryStream())
    {
        using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
        {
            cs.Write(rawPlaintext, 0, rawPlaintext.Length);
        }
        cipherText= ms.ToArray();
    }

    using (MemoryStream ms = new MemoryStream())
    {
        using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
        {
            cs.Write(cipherText, 0, cipherText.Length);
        }
        plainText = ms.ToArray();
    }
}
string s = System.Text.Encoding.Unicode.GetString(plainText);
Console.WriteLine(s);
7 голосов
/ 02 сентября 2011

Вот простое решение, которое я нашел на форуме VB.NET и преобразовал в C #. Это, безусловно, помогло мне лучше понять тему.

// Shamelessly lifted from http://discuss.itacumens.com/index.php?topic=62872.0, 
// then converted to C# (http://www.developerfusion.com/tools/convert/vb-to-csharp/) and
// changed where necessary.
public class Encryptor
{
    private static SymmetricAlgorithm _cryptoService = new TripleDESCryptoServiceProvider(); 
    // maybe use AesCryptoServiceProvider instead?

    // vector and key have to match between encryption and decryption
    public static string Encrypt(string text, byte[] key, byte[] vector)
    {
        return Transform(text, _cryptoService.CreateEncryptor(key, vector));
    }

    // vector and key have to match between encryption and decryption
    public static string Decrypt(string text, byte[] key, byte[] vector)
    {
        return Transform(text, _cryptoService.CreateDecryptor(key, vector));
    }

    private static string Transform(string text, ICryptoTransform cryptoTransform)
    {
        MemoryStream stream = new MemoryStream();
        CryptoStream cryptoStream = new CryptoStream(stream, cryptoTransform, CryptoStreamMode.Write);

        byte[] input = Encoding.Default.GetBytes(text);

        cryptoStream.Write(input, 0, input.Length);
        cryptoStream.FlushFinalBlock();

        return Encoding.Default.GetString(stream.ToArray());
    }
}
6 голосов
/ 28 января 2010

Ну, для начала ключи - это не строки, ключи - это двоичные двоичные объекты. PlainText - это то же самое, на самом деле это не текст, а снова двоичный двоичный объект.

Теперь, конечно, вы можете конвертировать строки в байтовые массивы, используя Encoding.UTF8.GetBytes(message), однако при преобразовании ключей назад и вперед это немного сложнее, обычно вы используете Convert.ToBase64String и Convert.FromBase64String.

Не забывайте, что блочным шифрам также нужна еще одна вещь, вектор инициализации, так что на самом деле ваши сигнатуры методов должны быть

byte[] Encrypt(byte[] plainText, byte[] key, byte[] iv)

byte[] Decrypt(byte[] cipherText, byte[] key, byte[] iv)

Ключ и IVs должны быть криптографически безопасными случайными числами , не просто набирать их и не использовать функцию Random в C #. Размер ключа и IV зависит от используемого алгоритма шифрования и может быть доступен через свойства классов.

Чтобы создать CSRPNG, вы должны сделать что-то вроде

RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] key = new byte[algorithm.KeySizeValue / 8];
rng.GetBytes(key);
byte[] iv = new byte[algorithm.BlockSizeValue / 8];
rng.GetBytes(iv);

Вы также можете использовать класс Rfc2898DeriveBytes для получения ключа и IV из пароля и соли, но опять же соль должна быть криптографически безопасным случайным числом. Вам также следует помнить, что при создании симметричного алгоритма для вас генерируется безопасный ключ и создается IV.

Таким образом, вы можете выбрать правильную кодировку для вашего текста, будь то UTF8, ASCII или что-то еще. В ссылках достаточно примеров, поэтому вырезать и вставлять их здесь бессмысленно.

2 голосов
/ 28 января 2010

Сначала преобразуйте текст, ключ и вектор инициализации в байты, используя выбранную кодировку. Затем используйте поставщика тройного DES, как показано здесь:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.tripledes.aspx

Или тот, что для AES, если вы думаете, что тройной DES слишком стар, или что-то в этом роде.

Из любопытства, как вы планируете передать секретный ключ?

2 голосов
/ 28 января 2010

что вы хотите, это криптосервисные провайдеры в библиотеке классов

как этот для AES

http://msdn.microsoft.com/en-us/library/system.security.cryptography.aescryptoserviceprovider_members.aspx

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