2017-04-05 9 views
1

私は、オブジェクトをシリアル化するためにbinaryformatterを使用するときに、ちょっとした不具合が発生しました。シリアライゼーションの全体のポイントは、値をバイト配列を必要とするハッシュ関数に渡すことができるようにすることです。C#バイナリフォーマッタのプロパティは同じ値を持っています

私は、newtonsoft Jsonconvertを使ってPOCOオブジェクトにファイルを読み込み、いくつかのチェックを行い、必要に応じて値を更新し、Json形式で同じファイルに保存し直しています。

チェックには、ファイルのハッシュ値がプロセスの最初に再生成されたものと一致しているかどうかが検証されます。私が取る手順は、ファイルを読み込んでPOCOに変換し、バイナリフォーマッタを使用してシリアル化し、ハッシュ値を生成し、正しい場合は両方の値を比較し、データを更新して、新しいハッシュ値とオブジェクトをJsonとしてファイルに保存します。

しかし、バイナリフォーマッタを使用してオブジェクトをシリアル化すると、私は突っ込んでしまいました。オブジェクトに値が同じプロパティがある場合、シリアライザからのバイト出力は、データがファイルから読み込まれたときとは異なり、書き出されるときとは異なります。バイト配列の値が異なるため、ハッシュ値も異なります。さらに、プロパティの値が異なる場合、同じハッシュ値が生成されるため、問題は発生しません。

私の質問は、オブジェクトが読み込まれてファイルに書き込まれたときに、同じ値を持つとバイト値が異なるのはなぜですか?

[Serializable] 
public class UserAuthorisationData 
{ 
    public string surname { get; set; } 
    public string forename { get; set; } 
    public string initials { get; set; } 

    public UserAuthorisationData() 
    { 
     surname = ""; 
     forename = ""; 
     initials = ""; 

    } 
} 

例:上記実施例で

var objectA = new UserAuthorisationData() 
objectA.surname = "Fred"; 
objectA.forename = "John"; 
objectA.initials = "FJ"; 

var objectB = new UserAuthorisationData() 
objectB.surname = "John"; 
objectB.forename = "John"; 
objectB.initials = "JJ"; 

ハッシュ値がファイルである場合、データが書き出されたときの間の両方に生成される場合、ObjectAにするためのバイト配列の値は、同じです

ただし、objectBの値は異なります。

バイトにオブジェクトを変換するには、以下の方法:

protected virtual byte[] ObjectToByteArray(object objectToSerialize) 
    { 
     BinaryFormatter formatter = new BinaryFormatter(); 
     MemoryStream fs = new MemoryStream(); 

     try 
     { 

      lock (locker) 
      {     
       formatter.Serialize(fs, objectToSerialize); 
       Logger.Debug($"Successfully converted object to bytes for serialization."); 
      } 
      File.WriteAllBytes(@"C:\ali.kamal\User1.txt", fs.ToArray()); 

      return fs.ToArray(); 
     } 
    } 

オブジェクト

ObjectToByteArray(objectA); 
ObjectToByteArray(objectB); 

上のメソッドを呼び出しますが、Update 1の

おかげハディ。ハッシュコードは、MicrosoftのHMACSHA256.computeHashメソッドを使用して生成されます。

protected override string ComputeHash(byte[] objectAsBytes, byte[] key) 
    { 
     byte[] hashValue = null; 
     try 
     { 
      using (HMACSHA256 hmac = new HMACSHA256(key)) 
      { 
       hashValue = hmac.ComputeHash(objectAsBytes); 

      } 
     }catch(Exception ex) 
     { 
      EventLogger.LogEvent($"Could not generate SHA256 hash value, exception:{ex.Message}", EventEntryType.Error); 
     } 

     return Convert.ToBase64String(hashValue); 
    } 

string hashvalue = ComputeHash(ObjectToByteArray(objectA), ObjectToByteArray("abcd")) 

答えて

0

私はむしろハッシュコード方式とは異なる方法でバイトを比較するために、あなたをお勧めします:Array1.SequenceEqual(Array2)、その明確ではない、あなたの問題の両方の配列のハッシュコードを比較しているが、私はそのあなたと仮定する方法GetHashCodeメソッドを使用しています。Array1.GetHashCode() == Array2.GetHashCode()は、HasCode関数をオーバーライドしない限り、あなたのケースには適しません。

using System; 
using System.IO; 
using System.Linq; 
using System.Runtime.Serialization.Formatters.Binary; 

namespace ConsoleApp1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var a = new UserData(); 
      var b = new UserData(); 

      var aS = ObjectToByte(a); 
      var bS = ObjectToByte(b); 
      Console.WriteLine("A : {0}", a); 
      Console.WriteLine("B : {0}", b); 
      // result for empty objects are equal 
      Console.WriteLine("A == B ? => {0} \n\n", aS.SequenceEqual(bS)); 

      a = new UserData() 
      { 
       ForeName = "A", 
       Initials = "CC", 
       SurName = "B", 
      }; 

      b = new UserData() 
      { 
       ForeName = "AX", 
       Initials = "CC", 
       SurName = "B", 
      }; 

      aS = ObjectToByte(a); 
      bS = ObjectToByte(b); 

      Console.WriteLine("A : {0}", a); 
      Console.WriteLine("B : {0}", b); 
      // result for same data type with same object values are equal 
      Console.WriteLine("A == B ? => {0} \n\n", aS.SequenceEqual(bS)); 

      a = new UserData() 
      { 
       ForeName = "AX", 
       Initials = "CC", 
       SurName = "B", 
      }; 
      b = a; 

      aS = ObjectToByte(a); 
      bS = ObjectToByte(b); 

      Console.WriteLine("A : {0}", a); 
      Console.WriteLine("B : {0}", b); 
      // result for different objects are not equal 
      Console.WriteLine("A == B ? => {0} \n\n", aS.SequenceEqual(bS)); 
     } 

     static byte[] ObjectToByte(object item) 
     { 
      var formatter = new BinaryFormatter(); 
      using (var memory = new MemoryStream()) 
      { 
       formatter.Serialize(memory, item); 
       return memory.ToArray(); 
      } 
     } 
    } 

    [Serializable] 
    public class UserData 
    { 
     public string SurName { get; set; } 
     public string ForeName { get; set; } 
     public string Initials { get; set; } 

     public override string ToString() 
     { 
      return string.Format("{{SurName: {0} , ForeName:{1}, Initials:{2}}}", SurName ?? "Empty", ForeName ?? "Empty", Initials ?? "Empty"); 
     } 
    } 
} 

ここでは、これはあなた

+0

おかげハディを助ける作業Demo

希望:以下はSequenceEqualメソッドを使用するためのコンソールアプリケーションを使用したサンプルです。ハッシュコードは、MicrosoftのHMACSHA256.computeHashを使用して生成されます。 –

+0

同じ 'HMACSHA256'オブジェクト、 'var h = new HMACSH256();を使っている限り、同じ結果が得られました。 var aS = h.ComputeHash(ObjectToByte(a)); bS.SequenceEqual(aS) 'は正常に動作しますが、異なるHMACSH256でオブジェクトを計算すると動作しません。 – Monah

+0

バイト配列の値が異なる理由は分かりますか? –

関連する問題