2012-01-27 3 views
17

Я ищу очень простой метод шифрования/дешифрования. Я буду использовать всегда один и тот же статический ключ. Я знаю о рисках такого подхода. В настоящее время я использую следующий код, но он не генерирует тот же результат после шифрования и дешифровки одной и той же строки (в середине строки есть мусор).Действительно простое шифрование с C# и SymmetricAlgorithm

public static string Crypt(this string text) 
    { 
     string result = null; 

     if (!String.IsNullOrEmpty(text)) 
     { 
      byte[] plaintextBytes = Encoding.Unicode.GetBytes(text); 

      SymmetricAlgorithm symmetricAlgorithm = DES.Create(); 
      symmetricAlgorithm.Key = new byte[8] {1, 2, 3, 4, 5, 6, 7, 8}; 
      using (MemoryStream memoryStream = new MemoryStream()) 
      { 
       using (CryptoStream cryptoStream = new CryptoStream(memoryStream, symmetricAlgorithm.CreateEncryptor(), CryptoStreamMode.Write)) 
       { 
        cryptoStream.Write(plaintextBytes, 0, plaintextBytes.Length); 
       } 

       result = Encoding.Unicode.GetString(memoryStream.ToArray()); 
      } 
     } 

     return result; 
    } 

    public static string Decrypt(this string text) 
    { 
     string result = null; 

     if (!String.IsNullOrEmpty(text)) 
     { 
      byte[] encryptedBytes = Encoding.Unicode.GetBytes(text); 

      SymmetricAlgorithm symmetricAlgorithm = DES.Create(); 
      symmetricAlgorithm.Key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; 
      using (MemoryStream memoryStream = new MemoryStream(encryptedBytes)) 
      { 
       using (CryptoStream cryptoStream = new CryptoStream(memoryStream, symmetricAlgorithm.CreateDecryptor(), CryptoStreamMode.Read)) 
       { 
        byte[] decryptedBytes = new byte[encryptedBytes.Length]; 
        cryptoStream.Read(decryptedBytes, 0, decryptedBytes.Length); 
        result = Encoding.Unicode.GetString(decryptedBytes); 
       } 
      } 
     } 

     return result; 
    } 

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

Спасибо.

+0

Либо колодок данные кратного размера блока шифра или использовать потоковый алгоритм вместо блок-алгоритм. –

ответ

35

Если вы не хотите самостоятельно обращаться с ключами, позвольте операционной системе сделать это за вас. Например. использование Windows Data Protection (DPAPI).

Вы можете написать свою собственную, string основу, версию System.Security.Cryptography.ProtectedData.Protect и Unprotect методов, используя что-то вроде:

public static string Crypt (this string text) 
{ 
    return Convert.ToBase64String (
     ProtectedData.Protect (
      Encoding.Unicode.GetBytes (text))); 
} 

public static string Derypt (this string text) 
{ 
    return Encoding.Unicode.GetString (
     ProtectedData.Unprotect (
      Convert.FromBase64String (text))); 
} 
+3

Мне нравится, когда Framework делает все от вас. Спасибо –

+25

Будьте осторожны с этим, вы не можете расшифровать строку encrpyted на любом другом компьютере или даже с другим профилем на том же компьютере. Только хорошо для хранения вещей очень локально. –

+3

@JonathanDeMarks, последняя версия библиотек базового класса ** DO ** позволяет зашифровать/дешифровать это как ** CurrentUser **, так и ** LocalMachine **. Подпись для шифрования выглядит следующим образом: 'public static byte [] Protect (byte [] userData, byte [] optionalEntropy, область DataProtectionScope)' где 'scope' может быть' DataProtectionScope.CurrentUser' или 'DataProtectionScope.LocalMachine' –

6

Вам необходимо установить режим шифрования на CipherMode.ECB или использовать IV.

SymmetricAlgorithm symmetricAlgorithm = DES.Create(); 
symmetricAlgorithm.Key = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 }; 
symmetricAlgorithm.Mode = CipherMode.ECB; 
... 

Другим моментом является использование кодировки Unicode. Вместо этого используйте Base64. Unicode может «уничтожить» байты, которые не являются UTF-16.

+0

В любом случае, я получаю извращение струны. –

+0

+1. Альтернативой может быть просто вернуть (а затем использовать) необработанные байты, а не строку, но в любом случае проблема заключается в том, что 'Encoding.Unicode.GetString' собирается поймать и« исправить »случаи, когда зашифрованные байты не являются действительный UTF-16, который разрушает план. –

+0

Greeeeeeeat. Теперь это работает, спасибо!(Трудно, когда вам приходится работать с вещами, которые вы не понимаете, и вы не хотите их понимать;) Еще раз спасибо. –

-2

Переписать методы Crypt и Decrypt для извлечения параметра ввода байтов. Убедитесь, что байты правильно зашифрованы и дешифрованы.

18

Как насчет чего-то подобного?

Код

using System; 
using System.Security.Cryptography; 
using System.Text; 

public static class StringUtil 
{ 
    private static byte[] key = new byte[8] {1, 2, 3, 4, 5, 6, 7, 8}; 
    private static byte[] iv = new byte[8] {1, 2, 3, 4, 5, 6, 7, 8}; 

    public static string Crypt(this string text) 
    { 
     SymmetricAlgorithm algorithm = DES.Create(); 
     ICryptoTransform transform = algorithm.CreateEncryptor(key, iv); 
     byte[] inputbuffer = Encoding.Unicode.GetBytes(text); 
     byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length); 
     return Convert.ToBase64String(outputBuffer); 
    } 

    public static string Decrypt(this string text) 
    { 
     SymmetricAlgorithm algorithm = DES.Create(); 
     ICryptoTransform transform = algorithm.CreateDecryptor(key, iv); 
     byte[] inputbuffer = Convert.FromBase64String(text); 
     byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length); 
     return Encoding.Unicode.GetString(outputBuffer); 
    } 
} 

Unit Test

[Test] 
public void Test() 
{ 
    string expected = "this is my test string"; 
    string a = expected.Crypt(); 
    Debug.WriteLine(a); 
    string actual = a.Decrypt(); 
    Assert.AreEqual(expected, actual); 
} 

EDIT:

Для уточнения: Я знаю, что это не Goo d практика.

«Я знаю о рисках такого подхода.»

Iv'e сделал предположение о том, что OP также осознает и будет вносить соответствующие изменения в коде, прежде чем рассматривать использовать что-либо подобное в производственной среды.

Вопрос подчеркивает простоту в отношении передовой практики.

+1

IV должен быть случайным и храниться вместе с сообщением. – CodesInChaos

+0

, имеющий статический ключ в приложении, тоже не хорош – poupou

+0

Служил своей целью для моего маленького проекта просто отлично, спасибо :) – JARRRRG

Смежные вопросы