2012-01-27 16 views
17

私はを非常に単純な暗号化/復号化方法を探しています。私は常に同じ静的キーを使用します。私はこのアプローチのリスクを認識しています。現在、次のコードを使用していますが、同じ文字列を暗号化して解読した後に同じ結果が生成されることはありません(文字列の途中にゴミがいくつかあります)。C#と対称アルゴリズムを使用した単純な暗号化

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

私は必要とされているものは何でも変更することができ、制限は(私はちょうど陰窩する方法と、それらの間で変数を共有することなく復号化する別の1に持っていると思います)。

ありがとうございました。

+0

パッドいずれかのデータを、またはその代わりのストリームアルゴリズムを使用しますブロックアルゴリズム –

答えて

35

自分でキーを処理したくない場合は、オペレーティングシステムが自分のためにそれを行うようにします。例えば。 Windows Data Protection(DPAPI)を使用します。

あなたが好きなものを使用してSystem.Security.Cryptography.ProtectedData.ProtectUnprotect方法のあなた自身、stringベース、バージョンを書くことができます:暗号のブロックサイズの倍数に

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

フレームワークがすべてのことをするとき、私は大好きです。ありがとう –

+25

これに注意してください。暗号化された文字列を他のコンピュータや同じマシンの別のプロファイルでも復号化することはできません。非常にローカルに物事を格納するためにのみ良いです。 –

+3

@JonathanDeMarks、基本クラスライブラリの最新バージョン** DO **は** CurrentUser **と** LocalMachine **の両方で暗号化/復号化が可能です。 'public static byte [] protected(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; 
... 

もう1つのポイントは、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); 
    } 
} 

ユニットテスト

[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:

を明確にする:私は、これはグーではありません承知していますdの練習。

は、「私は、このアプローチの危険性を認識してね。」

Iv'eはOPも認識しており、このようなものを使用して検討する前に、関連するコードを変更することを前提に作られましたプロダクション環境。

質問は、優れた実践よりも単純さを強調しています。

+1

IVはランダムであり、メッセージと共に格納されるべきです。 – CodesInChaos

+0

アプリケーションで静的なキーを持っていてもどちらでも良いとはいいません – poupou

+0

私の小さなプロジェクトのために役立ちました。ありがとうございました:) – JARRRRG