2016-09-02 16 views
1

私はシンプルなdtoを文字列として安全に渡す手段としてシリアライズし、暗号化しようとしています。.NetのAES + HMAC暗号化

これについて質問するとほとんどの人がEncrypt and decrypt a stringに私を指しているようです。 @jbtuleは、2つの可能な解決法で本当に詳細な答えを提供する時間を費やしました。

私は彼の要旨https://gist.github.com/jbtule/4336842#file-aesthenhmac-cs(「AESThenHMAC.cs」という名前のファイルから2番目の例のコピーを取り、私のプロジェクトへのそれを入れている。

私はそれを包むために良い方法かもしれないと思ったし、 。?すぐにこのソリューションをテストが、私はそれが働くように見えることはできません

誰かが私がここで間違ってやっているものを説明してもらえ

をここでjbtuleのコード@私のラッパーのラウンドです:

using Newtonsoft.Json; 
using System.Text; 

namespace Core.Data 
{ 
    public class AesCrypto<T> : ICrypto<T> 
    { 
     public string Encrypt(T source, string salt) 
     { 
      var enc = Encoding.Unicode; 
      var rawData = JsonConvert.SerializeObject(source); 
      return enc.GetString(AESThenHMAC.SimpleEncryptWithPassword(enc.GetBytes(rawData), salt)); 
     } 

     public T Decrypt(string source, string salt) 
     { 
      var enc = Encoding.Unicode; 
      var decryptedBytes = AESThenHMAC.SimpleDecryptWithPassword(enc.GetBytes(source), salt); 
      return JsonConvert.DeserializeObject<T>(enc.GetString(decryptedBytes)); 
     } 
    } 
} 
点の

そしてシンプルなユニットテストを確認するには、このすべての作品:何らかの理由で

public void TestAesCrypto() 
{ 
    var testInput = new EncryptableObject { Id = 123, Name = "Victim", When = DateTimeOffset.UtcNow }; 
    var crypto = new AesCrypto<EncryptableObject>(); 

    var saltBytes = new byte[32]; 
    new Random().NextBytes(saltBytes); 
    var testSalt = Encoding.Unicode.GetString(saltBytes); 

    var magicString = crypto.Encrypt(testInput, testSalt); 
    var testOutput = crypto.Decrypt(magicString, testSalt); 

    Assert.AreEqual(testInput.Id, testOutput.Id); 
    Assert.AreEqual(testInput.Name, testOutput.Name); 
    Assert.AreEqual(testInput.When, testOutput.When); 
} 

jbtuleの要旨のライン261上で実行チェックは0

に値255を比較するため、復号化方法は、nullを返します

これは、.NETタイプ(「AesEncryption doesn't appear to decrypt right?」を参照してください)と直接対話する私の試みに続くものです。この時点で一貫して機能するソリューションが必要です。

+1

すべてのバイトペアが有効なUnicode文字にマップされるわけではありません。 'GetString()'が有効な 'char'ではないバイトペアに遭遇すると、[fallback strategy](https://msdn.microsoft.com/en-us/library/ms404377(v=vs.110) ).aspx#Anchor_3)を使用してペアを有効な文字に置き換えます。つまり、データを失うことになります。代わりに、[Convert.ToBase64String() '](https://msdn.microsoft.com/en-us/library/dhx0d524(v=vs.110).aspx)のようなものを使用してください。私はあなたの塩をコード化するbase64について確信が持てませんが、エントロピーを失うかもしれませんか?確かに言えば、私はセキュリティについて十分に分かりません。 – dbc

+0

hmmm ...ここではユニコードが問題になるとは思わなかった...いいですが、私はそれを再加工できるかどうかを見てください。 – War

+1

[Pbkdf2を使用した完全パスワードハッシングソリューション](http://stackoverflow.com/documentation/c%23/2774/hash-functions/15470/complete-password-hashing-solution-using-pbkdf2)を参照してください。完全な例の一番下にはユーティリティクラス 'ByteConverter'があります。これは' byte [] 'を16進文字列に変換するのに使うことができます。これにより、文字列変換プロセスで何かを失うことを心配することなく、バイト配列の真の文字列表現が保証されます。厳密なバイト配列の比較(文字列変換なし)を行う場合は、メソッド 'CompareHashes'(同じ例)を使用することもできます。 – Igor

答えて

0

私は、@ dbcのおかげで、そこに行く...私は私が知らないことをどのようにしなかったか!

using Newtonsoft.Json; 
using System; 
using System.Text; 

namespace Core.Data 
{ 
    public class AesCrypto<T> : ICrypto<T> 
    { 
     public string Encrypt(T source, string salt) 
     { 
      var e = Encoding.UTF8; 
      var rawData = e.GetBytes(JsonConvert.SerializeObject(source)); 
      var cipherData = AESThenHMAC.SimpleEncryptWithPassword(rawData, salt); 
      return Convert.ToBase64String(cipherData); 
     } 

     public T Decrypt(string source, string salt) 
     { 
      var e = Encoding.UTF8; 
      var decryptedBytes = AESThenHMAC.SimpleDecryptWithPassword(Convert.FromBase64String(source), salt); 
      return JsonConvert.DeserializeObject<T>(e.GetString(decryptedBytes)); 
     } 
    } 
} 
+0

ソースの種類が「T」であり、コード内でUTF-8でエンコードされたデータが想定されています。 – zaph

+0

問題の内容についても説明できますか? –

+0

私は安全で確認可能な方法でアプリケーション間でデータを送ることを可能にする多目的暗号化システムが必要です。例:上記の例では、要求の署名を表す単純なDTOオブジェクトを定義し、Json APIへのリモート呼び出しを行い、リモートのエンドポイントがオブジェクトの復号化によって確認できるカスタムヘッダーとして出力文字列を追加します。 AESを使用すると暗号化が可能になりますが、HMACを追加すると、復号化されたデータが成功すると改ざんされていないという確認も加えられます。 – War