public void VerifyHashGenerationV1(byte[] content, Content_Information_Data_Structure contentInfo) { const int BLOCKBYTECOUNT = 0x10000; const int SEGMENTBLOCKCOUNT = 512; dwHashAlgo_Values hashAlgo = contentInfo.dwHashAlgo; int blockTotalCount = content.Length / BLOCKBYTECOUNT; if (content.Length > BLOCKBYTECOUNT * blockTotalCount) { blockTotalCount = blockTotalCount + 1; } int segmentCount = blockTotalCount / SEGMENTBLOCKCOUNT; if (blockTotalCount > SEGMENTBLOCKCOUNT * segmentCount) { segmentCount = segmentCount + 1; } HashAlgorithm hashAlgorithm; HMAC hmacAlgorithm; int blockHashSize; PccrcUtility.GetHashAlgorithm(hashAlgo, out hashAlgorithm, out hmacAlgorithm, out blockHashSize); hmacAlgorithm.Key = hashAlgorithm.ComputeHash(testConfig.ServerSecret); for (int segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++) { List <byte> blockHashList = new List <byte>(); int blockCount = (segmentIndex == segmentCount - 1) ? (blockTotalCount % SEGMENTBLOCKCOUNT) : (SEGMENTBLOCKCOUNT); for (int blockIndex = 0; blockIndex < blockCount; blockIndex++) { var block = content.Skip(BLOCKBYTECOUNT * SEGMENTBLOCKCOUNT * segmentIndex + BLOCKBYTECOUNT * blockIndex).Take(BLOCKBYTECOUNT).ToArray(); byte[] blockHash = hashAlgorithm.ComputeHash(block); testSite.Assert.IsTrue( blockHash.SequenceEqual((contentInfo.blocks[segmentIndex].BlockHashes).Skip(blockIndex * blockHashSize).Take(blockHashSize).ToArray()), "The local calculated block hash in Segment: {0} Block: {1} should cosistent with the received value.", segmentIndex, blockIndex); blockHashList.AddRange(blockHash); } byte[] hod = hashAlgorithm.ComputeHash(blockHashList.ToArray()); testSite.Assert.IsTrue( hod.SequenceEqual(contentInfo.segments[segmentIndex].SegmentHashOfData), "The local calculated Hod should cosistent with the received value."); byte[] kp = hmacAlgorithm.ComputeHash(hod); testSite.Assert.IsTrue( kp.SequenceEqual(contentInfo.segments[segmentIndex].SegmentSecret), "The local calculated Kp should cosistent with the received value."); } }
/// <summary> /// Get the hash algorithm and hmac algorithm for V1. /// </summary> /// <param name="hashAlgo">The hash algorithm value</param> /// <returns>The hash algorithm and hmac algorithm</returns> public static void GetHashAlgorithm(dwHashAlgo_Values hashAlgo, out HashAlgorithm hashAlgorithm, out HMAC hmacAlgorithm, out int blockHashSize) { switch (hashAlgo) { case dwHashAlgo_Values.SHA256: hashAlgorithm = HashAlgorithm.Create("SHA256"); hmacAlgorithm = HMAC.Create("HMACSHA256"); blockHashSize = 32; break; case dwHashAlgo_Values.SHA384: hashAlgorithm = HashAlgorithm.Create("SHA384"); hmacAlgorithm = HMAC.Create("HMACSHA384"); blockHashSize = 48; break; case dwHashAlgo_Values.SHA512: hashAlgorithm = HashAlgorithm.Create("SHA512"); hmacAlgorithm = HMAC.Create("HMACSHA512"); blockHashSize = 64; break; default: throw new NotImplementedException(); } }
/// <summary> /// Compute the segment HoD. /// </summary> /// <param name="kp">The Kp data</param> /// <param name="hod">The segment HoD</param> /// <param name="hashAlgo">The HoHoDk hash algorithm.</param> /// <returns>The HoHoDk data</returns> public static byte[] GetHoHoDkBytes(byte[] kp, byte[] hod, dwHashAlgo_Values hashAlgo) { HMAC hohodkAlgo = null; List <byte> tempList = new List <byte>(); switch (hashAlgo) { case dwHashAlgo_Values.SHA256: hohodkAlgo = HMAC.Create(ALGOHMACSHA256); break; case dwHashAlgo_Values.SHA384: hohodkAlgo = HMAC.Create(ALGOHMACSHA384); break; case dwHashAlgo_Values.SHA512: hohodkAlgo = HMAC.Create(ALGOHMACSHA512); break; default: throw new NotImplementedException(); } hohodkAlgo.Key = kp; tempList.AddRange(hod); tempList.AddRange(Encoding.Unicode.GetBytes(HOHODKAPPENDSTRING)); var hash = hohodkAlgo.ComputeHash(tempList.ToArray()); return(hash); }
/// <summary> /// Convert the structure to byte array. /// </summary> /// <param name="algo">The hash algorithm to use.</param> /// <returns>The byte array.</returns> public byte[] ToByteArray(dwHashAlgo_Values algo) { List <byte> byteList = new List <byte>(); byteList.Add((byte)this.cBlocks); byteList.Add((byte)(this.cBlocks >> 8)); byteList.Add((byte)(this.cBlocks >> 16)); byteList.Add((byte)(this.cBlocks >> 24)); byteList.AddRange(this.BlockHashes); return(byteList.ToArray()); }
/// <summary> /// Parse the information of the block. /// </summary> /// <param name="dwHashAlgo">The hash algorithm to use.</param> /// <param name="cSegments">The number of segments which intersect the content range and hence are contained /// in the Content Information structure.</param> /// <param name="data">The byte data in little-endian order.</param> /// <param name="index">The start index.</param> /// <returns>Returns the block infromation.</returns> private static SegmentContentBlocks[] ParseBlocks( dwHashAlgo_Values dwHashAlgo, uint cSegments, byte[] data, ref int index) { SegmentContentBlocks[] retBlocks = new SegmentContentBlocks[cSegments]; int dataSize = GetDataSizeByHashAlgo(dwHashAlgo); for (int i = 0; i < retBlocks.Length; i++) { retBlocks[i].cBlocks = GetUInt32(data, ref index); retBlocks[i].BlockHashes = GetBytes( data, ref index, (int)(dataSize * retBlocks[i].cBlocks)); } return(retBlocks); }
/// <summary> /// Get data size by hash algorithm. /// </summary> /// <param name="dwHashAlgo">The hash algorithm</param> /// <returns>The data size</returns> private static int GetDataSizeByHashAlgo(dwHashAlgo_Values dwHashAlgo) { int dataSize = 0; switch (dwHashAlgo) { case dwHashAlgo_Values.SHA256: dataSize = 32; break; case dwHashAlgo_Values.SHA384: dataSize = 48; break; case dwHashAlgo_Values.SHA512: dataSize = 64; break; } return(dataSize); }
/// <summary> /// Parse the information of segment. /// </summary> /// <param name="dwHashAlgo">The hash algorithm to use.</param> /// <param name="cSegments">The number of segments which intersect the content range and hence are contained /// in the Content Information structure.</param> /// <param name="data">The byte data.</param> /// <param name="index">The start index.</param> /// <returns>Returns the segment infromation.</returns> private static SegmentDescription[] ParseSements( dwHashAlgo_Values dwHashAlgo, uint cSegments, byte[] data, ref int index) { SegmentDescription[] retSegments = new SegmentDescription[cSegments]; int dataSize = GetDataSizeByHashAlgo(dwHashAlgo); for (int i = 0; i < retSegments.Length; i++) { retSegments[i].ullOffsetInContent = GetUInt64(data, ref index); retSegments[i].cbSegment = GetUInt32(data, ref index); retSegments[i].cbBlockSize = GetUInt32(data, ref index); byte[] tempSegmentHashOfData = GetBytes(data, ref index, dataSize); retSegments[i].SegmentHashOfData = tempSegmentHashOfData; byte[] tempSegmentSecret = GetBytes(data, ref index, dataSize); retSegments[i].SegmentSecret = tempSegmentSecret; } return(retSegments); }
/// <summary> /// Compute the segment HoD. /// </summary> /// <param name="kp">The Kp data</param> /// <param name="hod">The segment HoD</param> /// <param name="hashAlgo">The HoHoDk hash algorithm.</param> /// <returns>The HoHoDk data</returns> public static byte[] GetHoHoDkBytes(byte[] kp, byte[] hod, dwHashAlgo_Values hashAlgo) { HMAC hohodkAlgo = null; List<byte> tempList = new List<byte>(); switch (hashAlgo) { case dwHashAlgo_Values.SHA256: hohodkAlgo = HMAC.Create(ALGOHMACSHA256); break; case dwHashAlgo_Values.SHA384: hohodkAlgo = HMAC.Create(ALGOHMACSHA384); break; case dwHashAlgo_Values.SHA512: hohodkAlgo = HMAC.Create(ALGOHMACSHA512); break; default: throw new NotImplementedException(); } hohodkAlgo.Key = kp; tempList.AddRange(hod); tempList.AddRange(Encoding.Unicode.GetBytes(HOHODKAPPENDSTRING)); var hash = hohodkAlgo.ComputeHash(tempList.ToArray()); return hash; }
/// <summary> /// Convert the structure to byte array. /// </summary> /// <param name="algo">The hash algorithm to use.</param> /// <returns>The byte array.</returns> public byte[] ToByteArray(dwHashAlgo_Values algo) { List<byte> byteList = new List<byte>(); byteList.Add((byte)this.cBlocks); byteList.Add((byte)(this.cBlocks >> 8)); byteList.Add((byte)(this.cBlocks >> 16)); byteList.Add((byte)(this.cBlocks >> 24)); byteList.AddRange(this.BlockHashes); return byteList.ToArray(); }
/// <summary> /// Get data size by hash algorithm. /// </summary> /// <param name="dwHashAlgo">The hash algorithm</param> /// <returns>The data size</returns> private static int GetDataSizeByHashAlgo(dwHashAlgo_Values dwHashAlgo) { int dataSize = 0; switch (dwHashAlgo) { case dwHashAlgo_Values.SHA256: dataSize = 32; break; case dwHashAlgo_Values.SHA384: dataSize = 48; break; case dwHashAlgo_Values.SHA512: dataSize = 64; break; } return dataSize; }
/// <summary> /// Compute the segment HoD. /// </summary> /// <param name="kp">The Kp data</param> /// <param name="hod">The segment HoD</param> /// <param name="hashAlgo">The HoHoDk hash algorithm.</param> /// <returns>The HoHoDk data</returns> public static string GetHoHoDkString(byte[] kp, byte[] hod, dwHashAlgo_Values hashAlgo) { byte[] hohodk = GetHoHoDkBytes(kp, hod, hashAlgo); return ToHexString(hohodk); }
/// <summary> /// Parse the information of the block. /// </summary> /// <param name="dwHashAlgo">The hash algorithm to use.</param> /// <param name="cSegments">The number of segments which intersect the content range and hence are contained /// in the Content Information structure.</param> /// <param name="data">The byte data in little-endian order.</param> /// <param name="index">The start index.</param> /// <returns>Returns the block infromation.</returns> private static SegmentContentBlocks[] ParseBlocks( dwHashAlgo_Values dwHashAlgo, uint cSegments, byte[] data, ref int index) { SegmentContentBlocks[] retBlocks = new SegmentContentBlocks[cSegments]; int dataSize = GetDataSizeByHashAlgo(dwHashAlgo); for (int i = 0; i < retBlocks.Length; i++) { retBlocks[i].cBlocks = GetUInt32(data, ref index); retBlocks[i].BlockHashes = GetBytes( data, ref index, (int)(dataSize * retBlocks[i].cBlocks)); } return retBlocks; }
/// <summary> /// Compute the segment HoD. /// </summary> /// <param name="kp">The Kp data</param> /// <param name="hod">The segment HoD</param> /// <param name="hashAlgo">The HoHoDk hash algorithm.</param> /// <returns>The HoHoDk data</returns> public static string GetHoHoDkString(byte[] kp, byte[] hod, dwHashAlgo_Values hashAlgo) { byte[] hohodk = GetHoHoDkBytes(kp, hod, hashAlgo); return(ToHexString(hohodk)); }
/// <summary> /// Parse the information of segment. /// </summary> /// <param name="dwHashAlgo">The hash algorithm to use.</param> /// <param name="cSegments">The number of segments which intersect the content range and hence are contained /// in the Content Information structure.</param> /// <param name="data">The byte data.</param> /// <param name="index">The start index.</param> /// <returns>Returns the segment infromation.</returns> private static SegmentDescription[] ParseSements( dwHashAlgo_Values dwHashAlgo, uint cSegments, byte[] data, ref int index) { SegmentDescription[] retSegments = new SegmentDescription[cSegments]; int dataSize = GetDataSizeByHashAlgo(dwHashAlgo); for (int i = 0; i < retSegments.Length; i++) { retSegments[i].ullOffsetInContent = GetUInt64(data, ref index); retSegments[i].cbSegment = GetUInt32(data, ref index); retSegments[i].cbBlockSize = GetUInt32(data, ref index); byte[] tempSegmentHashOfData = GetBytes(data, ref index, dataSize); retSegments[i].SegmentHashOfData = tempSegmentHashOfData; byte[] tempSegmentSecret = GetBytes(data, ref index, dataSize); retSegments[i].SegmentSecret = tempSegmentSecret; } return retSegments; }
/// <summary> /// Initializes a new instance of the HashGeneration class with server secret and hash algorithm. /// </summary> /// <param name="secret">The unicode string of the server secret.</param> /// <param name="algo">The hash algorithm.</param> public HashGeneration(string secret, dwHashAlgo_Values algo) { this.ServerSecret = Encoding.Unicode.GetBytes(secret); this.DwHashAlgo = algo; }
/// <summary> /// Initializes a new instance of the HashGeneration class with server secret and hash algorithm. /// </summary> /// <param name="secret">The binary array of the server secret.</param> /// <param name="algo">The hash algorithm.</param> public HashGeneration(byte[] secret, dwHashAlgo_Values algo) { this.ServerSecret = secret; this.DwHashAlgo = algo; }