private void executeButton_Click(object sender, EventArgs e) { try { if (!CheckInput()) return; logger.Clear(); #region Read settings from UI var version = (BranchCacheVersion)branchCacheVersionComboBox.SelectedItem; var operationMode = (OperationMode)operationModeComboBox.SelectedItem; var transport = (ContentInformationTransport)transportComboBox.SelectedItem; var serverSecret = serverSecretTextBox.Text; var filePath = filePathTextBox.Text; var hashAlgoValue = (dwHashAlgo_Values)hashAlgorithmComboBox.SelectedItem; HashAlgorithm hashAlgorithm; HMAC hmacAlgorithm; int hashBlockSize; string server = null; string file = null; string sharedFolder = null; Match filePathMatch = null; switch (transport) { case ContentInformationTransport.PCCRTP: filePathMatch = Regex.Match(filePath, httpFilePathPattern); server = filePathMatch.Groups["Server"].Value; file = filePathMatch.Groups["FileName"].Value; break; case ContentInformationTransport.SMB2: filePathMatch = Regex.Match(filePath, smb2FilePathPattern); server = filePathMatch.Groups["Server"].Value; sharedFolder = filePathMatch.Groups["SharedFolder"].Value; file = filePathMatch.Groups["FileName"].Value; break; default: throw new NotImplementedException(); } SecurityPackageType securityPackageType = (SecurityPackageType)smb2AuthenticationComboBox.SelectedItem; string domainName = domainNameTextBox.Text; string userName = userNameTextBox.Text; string userPassword = userPasswordTextBox.Text; #endregion var timeout = TimeSpan.FromSeconds(60); byte[] content; byte[] contentInformation; Content_Information_Data_Structure contentInformationStructure = new Content_Information_Data_Structure(); Content_Information_Data_Structure_V2 contentInformationStructureV2 = new Content_Information_Data_Structure_V2(); #region Read content and content information if (operationMode == OperationMode.RemoteHashVerification) { switch (transport) { case ContentInformationTransport.PCCRTP: PccrtpClient pccrtpClient = new PccrtpClient(); PccrtpRequest pccrtpRequest = pccrtpClient.CreatePccrtpRequest( server, 80, file, version); PccrtpResponse pccrtpResponse = pccrtpClient.SendHttpRequest( HttpVersionType.HttpVersion11, pccrtpRequest, (int)timeout.TotalMilliseconds); if (pccrtpResponse.HttpResponse.ContentEncoding == "peerdist") { contentInformation = pccrtpResponse.PayloadData; content = Utility.DownloadHTTPFile(server, file); } else { content = pccrtpResponse.PayloadData; Thread.Sleep(5000); // Wait for hash generation pccrtpResponse = pccrtpClient.SendHttpRequest( HttpVersionType.HttpVersion11, pccrtpRequest, (int)timeout.TotalMilliseconds); contentInformation = pccrtpResponse.PayloadData; } break; case ContentInformationTransport.SMB2: using (Smb2ClientTransport smb2Client = new Smb2ClientTransport(timeout)) { smb2Client.OpenFile( server, sharedFolder, file, securityPackageType, domainName, userName, userPassword, AccessMask.GENERIC_READ); content = smb2Client.ReadAllBytes(); Thread.Sleep(5000); // Wait for hash generation HASH_HEADER hashHeader; smb2Client.ReadHash( SRV_READ_HASH_Request_HashType_Values.SRV_HASH_TYPE_PEER_DIST, version == BranchCacheVersion.V1 ? SRV_READ_HASH_Request_HashVersion_Values.SRV_HASH_VER_1 : SRV_READ_HASH_Request_HashVersion_Values.SRV_HASH_VER_2, version == BranchCacheVersion.V1 ? SRV_READ_HASH_Request_HashRetrievalType_Values.SRV_HASH_RETRIEVE_HASH_BASED : SRV_READ_HASH_Request_HashRetrievalType_Values.SRV_HASH_RETRIEVE_FILE_BASED, 0, uint.MaxValue, out hashHeader, out contentInformation); } break; default: throw new NotImplementedException(); } switch (version) { case BranchCacheVersion.V1: contentInformationStructure = PccrcUtility.ParseContentInformation(contentInformation); break; case BranchCacheVersion.V2: contentInformationStructureV2 = PccrcUtility.ParseContentInformationV2(contentInformation); break; default: throw new NotImplementedException(); } } else { content = File.ReadAllBytes(filePath); } #endregion #region Calculate hash and execute verification switch (version) { case BranchCacheVersion.V1: if (operationMode == OperationMode.RemoteHashVerification) PccrcUtility.GetHashAlgorithm(contentInformationStructure.dwHashAlgo, out hashAlgorithm, out hmacAlgorithm, out hashBlockSize); else PccrcUtility.GetHashAlgorithm(hashAlgoValue, out hashAlgorithm, out hmacAlgorithm, out hashBlockSize); hmacAlgorithm.Key = hashAlgorithm.ComputeHash(Encoding.Unicode.GetBytes(serverSecret)); logger.LogInfo( "Ks = Hash(ServerSecret): {0}", Utility.ToHexString(hmacAlgorithm.Key)); logger.NewLine(); int blockTotalCount = content.Length / BLOCKBYTECOUNT; if (content.Length > BLOCKBYTECOUNT * blockTotalCount) { blockTotalCount = blockTotalCount + 1; } int segmentCount = blockTotalCount / SEGMENTBLOCKCOUNT; if (blockTotalCount > SEGMENTBLOCKCOUNT * segmentCount) { segmentCount = segmentCount + 1; } for (int segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++) { logger.LogInfo("Segment{0}", segmentIndex); logger.NewLine(); logger.Indent(); List<byte> blockHashList = new List<byte>(); List<byte> tempList = new List<byte>(); int blockCount = (segmentIndex == segmentCount - 1) ? (blockTotalCount % SEGMENTBLOCKCOUNT) : (SEGMENTBLOCKCOUNT); for (int blockIndex = 0; blockIndex < blockCount; blockIndex++) { logger.LogInfo( "Block{0} Offset {1} Length {2}", blockIndex, BLOCKBYTECOUNT * SEGMENTBLOCKCOUNT * segmentIndex + BLOCKBYTECOUNT * blockIndex, BLOCKBYTECOUNT); logger.NewLine(); logger.Indent(); var block = content.Skip(BLOCKBYTECOUNT * SEGMENTBLOCKCOUNT * segmentIndex + BLOCKBYTECOUNT * blockIndex).Take(BLOCKBYTECOUNT).ToArray(); byte[] blockHash = hashAlgorithm.ComputeHash(block); logger.LogInfo("BlockHash{0} = Hash(Block): {1}", blockIndex, Utility.ToHexString(blockHash)); if (operationMode == OperationMode.RemoteHashVerification && !blockHash.SequenceEqual(contentInformationStructure.blocks[segmentIndex].BlockHashes.Skip(blockIndex * hashBlockSize).Take(hashBlockSize))) { logger.LogError("Server Returned: {0}", Utility.ToHexString(contentInformationStructure.blocks[segmentIndex].BlockHashes.Skip(blockIndex * hashBlockSize).Take(hashBlockSize).ToArray())); } blockHashList.AddRange(blockHash); logger.Unindent(); logger.NewLine(); } byte[] hod = hashAlgorithm.ComputeHash(blockHashList.ToArray()); logger.LogInfo( "HoD = Hash(BlockHash0 + BlockHash1 + ... + BlockHashN): {0}", Utility.ToHexString(hod)); if (operationMode == OperationMode.RemoteHashVerification && !hod.SequenceEqual(contentInformationStructure.segments[segmentIndex].SegmentHashOfData)) { logger.LogError("Server Returned: {0}", Utility.ToHexString(contentInformationStructure.segments[segmentIndex].SegmentHashOfData)); } logger.NewLine(); byte[] kp = hmacAlgorithm.ComputeHash(hod); logger.LogInfo( "Kp = HMAC(Ks, HoD): {0}", Utility.ToHexString(kp)); if (operationMode == OperationMode.RemoteHashVerification && !kp.SequenceEqual(contentInformationStructure.segments[segmentIndex].SegmentSecret)) { logger.LogError("Server Returned: {0}", Utility.ToHexString(contentInformationStructure.segments[segmentIndex].SegmentSecret)); } logger.NewLine(); tempList.AddRange(hod); tempList.AddRange(Encoding.Unicode.GetBytes(HOHODK_APPEND_STRING)); byte[] hoHoDK = hashAlgorithm.ComputeHash(tempList.ToArray()); logger.LogInfo( "hoHoDK = HMAC(HoD + \"MS_P2P_CACHING\"): {0}", Utility.ToHexString(hoHoDK)); logger.NewLine(); logger.Unindent(); } break; case BranchCacheVersion.V2: PccrcUtility.GetHashAlgorithm(dwHashAlgoV2_Values.TRUNCATED_SHA512, out hashAlgorithm, out hmacAlgorithm); hmacAlgorithm.Key = hashAlgorithm.ComputeHash(Encoding.Unicode.GetBytes(serverSecret)).Take(32).ToArray(); logger.LogInfo( "Ks = Hash(ServerSecret): {0}", Utility.ToHexString(hmacAlgorithm.Key)); logger.NewLine(); int segmentLength = BLOCKBYTECOUNT; int chunkCount = 1; if (operationMode == OperationMode.RemoteHashVerification) chunkCount = contentInformationStructureV2.chunks.Length; int segmentOffset = 0; for (int chunkIndex = 0; chunkIndex < chunkCount; chunkIndex++) { logger.LogInfo("Chunk{0}", chunkIndex); logger.NewLine(); logger.Indent(); segmentCount = content.Length / segmentLength; if (content.Length > segmentCount * segmentLength) segmentCount++; if (operationMode == OperationMode.RemoteHashVerification) segmentCount = contentInformationStructureV2.chunks[chunkIndex].chunkData.Length; for (int segmentIndex = 0; segmentIndex < segmentCount; ++segmentIndex) { logger.LogInfo( "Segment{0} Offset {1} Length {2}", segmentIndex, segmentOffset, BLOCKBYTECOUNT); logger.NewLine(); logger.Indent(); if (operationMode == OperationMode.RemoteHashVerification) segmentLength = (int)contentInformationStructureV2.chunks[chunkIndex].chunkData[segmentIndex].cbSegment; List<byte> tempList = new List<byte>(); var segment = content.Skip(segmentOffset).Take(segmentLength).ToArray(); segmentOffset += segmentLength; //TRANCATED_SHA_512 byte[] hod = hashAlgorithm.ComputeHash(segment).Take(32).ToArray(); logger.LogInfo( "HoD = Hash(Segment): {0}", Utility.ToHexString(hod)); if (operationMode == OperationMode.RemoteHashVerification && !hod.SequenceEqual(contentInformationStructureV2.chunks[chunkIndex].chunkData[segmentIndex].SegmentHashOfData)) { logger.LogError("Server Returned: {0}", Utility.ToHexString(contentInformationStructureV2.chunks[chunkIndex].chunkData[segmentIndex].SegmentHashOfData)); } logger.NewLine(); byte[] kp = hmacAlgorithm.ComputeHash(hod).Take(32).ToArray(); logger.LogInfo( "Kp = HMAC(Ks, HoD): {0}", Utility.ToHexString(kp)); if (operationMode == OperationMode.RemoteHashVerification && !kp.SequenceEqual(contentInformationStructureV2.chunks[chunkIndex].chunkData[segmentIndex].SegmentSecret)) { logger.LogError("Server Returned: {0}", Utility.ToHexString(contentInformationStructureV2.chunks[chunkIndex].chunkData[segmentIndex].SegmentSecret)); } logger.NewLine(); tempList.AddRange(hod); tempList.AddRange(Encoding.Unicode.GetBytes(HOHODK_APPEND_STRING)); byte[] hoHoDK = hashAlgorithm.ComputeHash(tempList.ToArray()); logger.LogInfo( "hoHoDK = HMAC(HoD + \"MS_P2P_CACHING\"): {0}", Utility.ToHexString(hoHoDK)); logger.NewLine(); logger.Unindent(); } } break; default: throw new NotImplementedException(); } if (operationMode == OperationMode.RemoteHashVerification) { if (logger.HasError) { Utility.ShowMessageBox("Hash verification error found!", MessageBoxIcon.Error); } else { Utility.ShowMessageBox("Hash verification passed!", MessageBoxIcon.Information); } } #endregion } catch (Exception ex) { Utility.ShowMessageBox(ex.Message + "\r\n\r\n" + ex.StackTrace, MessageBoxIcon.Error); } }
/// <summary> /// Create BATCHED_OFFER_MESSAGE package. /// </summary> /// <param name="connectionInfoPort"> /// A 16-bit unsigned integer that MUST be set by the client to the port /// on which it is listening as a server-role peer, for use with the retrieval protocol. /// </param> /// <param name="contentInfo">A Content Information V2 data structure.</param> /// <returns>Return the BATCHED_OFFER_MESSAGE.</returns> public BATCHED_OFFER_MESSAGE CreateBatchedOfferMessage( int connectionInfoPort, Content_Information_Data_Structure_V2 contentInfo) { MESSAGE_HEADER messageHeader; messageHeader.MajorVersion = 2; messageHeader.MinorVersion = 0; messageHeader.MsgType = PCHC_MESSAGE_TYPE.BATCHED_OFFER_MESSAGE; messageHeader.Padding = new byte[4]; CONNECTION_INFORMATION connectionInfo; connectionInfo.Padding = new byte[6]; connectionInfo.Port = (ushort)connectionInfoPort; BATCHED_OFFER_MESSAGE batchedOfferMessage; batchedOfferMessage.MessageHeader = messageHeader; batchedOfferMessage.ConnectionInfo = connectionInfo; List<SegmentDescriptor> segmentDescriptors = new List<SegmentDescriptor>(); for (int i = 0; i < contentInfo.chunks.Length; i++) { var chunk = contentInfo.chunks[i]; for (int j = 0; j < chunk.chunkData.Length; j++) { var segment = chunk.chunkData[j]; SegmentDescriptor segmentDescriptor = new SegmentDescriptor(); segmentDescriptor.BlockSize = segment.cbSegment; segmentDescriptor.SegmentSize = segment.cbSegment; segmentDescriptor.SizeOfContentTag = 16; segmentDescriptor.ContentTag = new byte[16]; segmentDescriptor.HashAlgorithm = (byte)contentInfo.dwHashAlgo; segmentDescriptor.SegmentHoHoDk = contentInfo.GetSegmentId(i, j); segmentDescriptors.Add(segmentDescriptor); } } batchedOfferMessage.SegmentDescriptors = segmentDescriptors.ToArray(); return batchedOfferMessage; }
public Content_Information_Data_Structure_V2 CreateContentInformationV2() { var contentInformation = new Content_Information_Data_Structure_V2 { bMajorVersion = 2, bMinorVersion = 0, ullIndexOfFirstSegment = 0, ullLengthOfRange = DefaultBlockSize, dwOffsetInFirstSegment = 0, ullStartInContent = 0, dwHashAlgo = dwHashAlgoV2_Values.TRUNCATED_SHA512, chunks = new ChunkDescription[] { new ChunkDescription { dwChunkDataLength = DefaultBlockSize, chunkData = new SegmentDescriptionV2[] { new SegmentDescriptionV2 { cbSegment = DefaultBlockSize, SegmentHashOfData = TestUtility.GenerateRandomArray(32), SegmentSecret = TestUtility.GenerateRandomArray(32) } } } } }; return contentInformation; }
public void Start(int port, CryptoAlgoId_Values cryptoAlgoId, Content_Information_Data_Structure_V2 contentInformationV2, byte[] content, EventQueue eventQueue) { this.contentInformationV2 = contentInformationV2; base.Start(port, cryptoAlgoId, content, eventQueue); }
public void VerifyHashGenerationV2(byte[] content, Content_Information_Data_Structure_V2 contentInfoV2) { dwHashAlgoV2_Values hashAlgo = contentInfoV2.dwHashAlgo; HashAlgorithm hashAlgorithm; HMAC hmacAlgorithm; PccrcUtility.GetHashAlgorithm(hashAlgo, out hashAlgorithm, out hmacAlgorithm); hmacAlgorithm.Key = hashAlgorithm.ComputeHash(testConfig.ServerSecret).Take(32).ToArray(); // Local calculate SegmentHashOfData and SegmentSecret ChunkDescription[] chunkDescription = contentInfoV2.chunks; int chunkCount = contentInfoV2.chunks.Length; int segmentOffset = 0; for (int chunkIndex = 0; chunkIndex < chunkCount; chunkIndex++) { SegmentDescriptionV2[] segmentDescription = chunkDescription[chunkIndex].chunkData; int segmentCount = segmentDescription.Length; for (int segmentIndex = 0; segmentIndex < segmentCount; ++segmentIndex) { var segment = content.Skip(segmentOffset).Take((int)(segmentDescription[segmentIndex].cbSegment)).ToArray(); segmentOffset += (int)(segmentDescription[segmentIndex].cbSegment); //TRANCATED_SHA_512 byte[] hod = hashAlgorithm.ComputeHash(segment).Take(32).ToArray(); testSite.Assert.IsTrue( hod.SequenceEqual((chunkDescription[chunkIndex].chunkData)[segmentIndex].SegmentHashOfData), "The local calculated Hod should cosistent with the received value."); byte[] kp = hmacAlgorithm.ComputeHash(hod).Take(32).ToArray(); testSite.Assert.IsTrue( kp.SequenceEqual((chunkDescription[chunkIndex].chunkData)[segmentIndex].SegmentSecret), "The local calculated Kp should be consistent with the received value."); } } }