// HMAC_hash(MAC_write_secret, seq_num + TLSCompressed.type + // TLSCompressed.version + TLSCompressed.length + // TLSCompressed.fragment)); /// <summary> /// Computes the TLS 1.0 MD5 HMAC for a record. /// </summary> /// <param name="secret">The secret to use for the HMAC calculation.</param> /// <param name="contentType">The TLS record content type.</param> /// <param name="sequenceNumber">The sequence number of the fragment.</param> /// <param name="fragment">The data sent.</param> /// <returns>The 16 byte HMAC hash.</returns> public static byte[] ComputeTlsMD5Hmac(byte[] secret, byte contentType, long sequenceNumber, byte[] fragment) { _HmacMd5.Key = secret; return(_HmacMd5.ComputeHash( ByteUtilities.ConcatBytes( BitConverter.GetBytes(IPAddress.HostToNetworkOrder(sequenceNumber)), new [] { contentType }, new byte[] { 3, 1 }, // version BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)fragment.Length)), fragment))); }
private void btnGenerateHmac_Click(object sender, EventArgs e) { try { byte[] keyBytes = txtHmacKeyString.Text.ToAsciiBytes(); txtHmacKeyAsciiBytes.Text = keyBytes.ToDisplayByteString(); byte[] dataBytes = txtHmacDataString.Text.ToAsciiBytes(); txtHmacDataAsciiBytes.Text = dataBytes.ToDisplayByteString(); const int blockSize = 64; Func <byte, byte[]> getPad = padByte => Enumerable.Range(1, blockSize).Select(n => padByte).ToArray(); // SHA-1 byte[] sha1Key = keyBytes.Length > blockSize?Hasher.ComputeSHA1Hash(keyBytes) : keyBytes; byte[] sha1Opad = getPad(0x5c); txtHmacSha1Opad.Text = sha1Opad.ToDisplayByteString(); byte[] sha1KeyXorOpad = sha1Key.Xor(sha1Opad); txtHmacSha1KeyXorOpad.Text = sha1KeyXorOpad.ToDisplayByteString(); byte[] sha1Ipad = getPad(0x36); txtHmacSha1IpadBytes.Text = sha1Ipad.ToDisplayByteString(); byte[] sha1KeyXorIpad = sha1Key.Xor(sha1Ipad); txtHmacSha1KeyXorIpad.Text = sha1KeyXorIpad.ToDisplayByteString(); byte[] sha1TotalInnerToHash = ByteUtilities.ConcatBytes(sha1KeyXorIpad, dataBytes); byte[] sha1InnerHash = Hasher.ComputeSHA1Hash(sha1TotalInnerToHash); txtHmacSha1InnerHash.Text = sha1InnerHash.ToDisplayByteString(); byte[] sha1Hmac = Hasher.ComputeSHA1Hash(ByteUtilities.ConcatBytes(sha1KeyXorOpad, sha1InnerHash)); byte[] sha1ExpectedHmac = Hasher.ComputeSHA1Hmac(keyBytes, dataBytes); Debug.Assert(ByteUtilities.AreEqual(sha1ExpectedHmac, sha1Hmac)); txtHmacSha1Result.Text = sha1Hmac.ToDisplayByteString(); // MD5 byte[] md5Key = keyBytes.Length > blockSize?Hasher.ComputeMD5(keyBytes) : keyBytes; byte[] md5Opad = getPad(0x5c); txtHmacMd5Opad.Text = md5Opad.ToDisplayByteString(); byte[] md5KeyXorOpad = md5Key.Xor(md5Opad); txtHmacMd5KeyXorOpad.Text = md5KeyXorOpad.ToDisplayByteString(); byte[] md5Ipad = getPad(0x36); txtHmacMd5IpadBytes.Text = md5Ipad.ToDisplayByteString(); byte[] md5KeyXorIpad = md5Key.Xor(md5Ipad); txtHmacMd5KeyXorIpad.Text = md5KeyXorIpad.ToDisplayByteString(); byte[] md5TotalInnerToHash = ByteUtilities.ConcatBytes(md5KeyXorIpad, dataBytes); byte[] md5InnerHash = Hasher.ComputeMD5(md5TotalInnerToHash); txtHmacMd5InnerHash.Text = md5InnerHash.ToDisplayByteString(); byte[] md5Hmac = Hasher.ComputeMD5(ByteUtilities.ConcatBytes(md5KeyXorOpad, md5InnerHash)); byte[] md5ExpectedHmac = Hasher.ComputeMD5Hmac(keyBytes, dataBytes); Debug.Assert(ByteUtilities.AreEqual(md5ExpectedHmac, md5Hmac)); txtHmacMd5Result.Text = md5Hmac.ToDisplayByteString(); } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); } }
private void btnGo_Click(object sender, EventArgs e) { try { byte[] preMasterSecret = FirefoxSslDebugFileUtilities.GetPremasterSecretKey(txtPremasterSecret.Text); string label = txtMasterSecretLabel.Text; byte[] serverHelloRandom = txtServerRandomBytes.Text.FromWireshark(); byte[] clientHelloRandom = txtClientRandomBytes.Text.FromWireshark(); byte[] clientHelloAndServerHello = ByteUtilities.ConcatBytes(clientHelloRandom, serverHelloRandom); byte[] masterSecret = Prf10.GenerateBytes(preMasterSecret, label, clientHelloAndServerHello, 48); txtMasterSecret.Text = masterSecret.ToDisplayByteString(); byte[] serverHelloAndClientHello = ByteUtilities.ConcatBytes(serverHelloRandom, clientHelloRandom); byte[] keyBlock = Prf10.GenerateBytes(masterSecret, txtKeyExpansionLabel.Text, serverHelloAndClientHello, 96); byte[] client_write_MAC_secret = new byte[16]; byte[] server_write_MAC_secret = new byte[16]; byte[] client_write_key = new byte[16]; byte[] server_write_key = new byte[16]; byte[] client_write_IV = new byte[16]; byte[] server_write_IV = new byte[16]; Buffer.BlockCopy(keyBlock, 0, client_write_MAC_secret, 0, 16); txtClientWriteMacKey.Text = client_write_MAC_secret.ToDisplayByteString(); Buffer.BlockCopy(keyBlock, 16, server_write_MAC_secret, 0, 16); txtServerWriteMacKey.Text = server_write_MAC_secret.ToDisplayByteString(); Buffer.BlockCopy(keyBlock, 32, client_write_key, 0, 16); txtClientWriteKey.Text = client_write_key.ToDisplayByteString(); Buffer.BlockCopy(keyBlock, 48, server_write_key, 0, 16); txtServerWriteKey.Text = server_write_key.ToDisplayByteString(); Buffer.BlockCopy(keyBlock, 64, client_write_IV, 0, 16); txtClientIV.Text = client_write_IV.ToDisplayByteString(); Buffer.BlockCopy(keyBlock, 80, server_write_IV, 0, 16); txtServerIV.Text = server_write_IV.ToDisplayByteString(); byte[] clientHello = txtClientHello.Text.FromWireshark(); byte[] serverHello = txtServerHello.Text.FromWireshark(); byte[] certificate = txtServerHelloCertificate.Text.FromWireshark(); byte[] serverHelloDone = txtServerHelloDone.Text.FromWireshark(); byte[] clientKeyExchangeEncrypted = txtClientKeyExchange.Text.FromWireshark(); byte[] handshakeMessages = ByteUtilities.ConcatBytes(clientHello, serverHello, certificate, serverHelloDone, clientKeyExchangeEncrypted); txtHandshakeMessages.Text = handshakeMessages.ToDisplayByteString(16); var md5Handshake = Hasher.ComputeMD5(handshakeMessages); txtMd5HandshakeMessages.Text = md5Handshake.ToDisplayByteString(); var sha1Handshake = Hasher.ComputeSHA1Hash(handshakeMessages); txtSha1HandshakeMessages.Text = sha1Handshake.ToDisplayByteString(); byte[] clientVerifyData = Prf10.GenerateBytes(masterSecret, txtClientFinishedLabel.Text, ByteUtilities.ConcatBytes(md5Handshake, sha1Handshake), 12); txtClientFinishedVerifyData.Text = clientVerifyData.ToDisplayByteString(); var clientFinishedHeaderBytes = txtClientFinishedHeader.Text.FromWireshark(); var clientFinishedHash = Hasher.ComputeTlsMD5Hmac(client_write_MAC_secret, 0x16, 0, ByteUtilities.ConcatBytes(clientFinishedHeaderBytes, clientVerifyData)); txtClientFinishedHmacMd5.Text = clientFinishedHash.ToDisplayByteString(); var clientFinishedHeaderAndVerify = ByteUtilities.ConcatBytes(clientFinishedHeaderBytes, clientVerifyData); var clientFinishedDecrypted = ByteUtilities.ConcatBytes(clientFinishedHeaderBytes, clientVerifyData, clientFinishedHash); Arc4 clientWriteArc4 = new Arc4(client_write_key); var clientFinishedEncrypted = clientWriteArc4.Encrypt(clientFinishedDecrypted); var expectedClientFinishedEncrypted = txtClientEncryptedFinishedMessage.Text.FromWireshark(); Debug.Assert(ByteUtilities.AreEqual(expectedClientFinishedEncrypted, clientFinishedEncrypted)); byte[] clientApplicationData = txtClientApplicationDataInput.Text.FromWireshark(); byte[] decryptedBytes = clientWriteArc4.Encrypt(clientApplicationData); byte[] plainTextBytes = new byte[decryptedBytes.Length - 16]; Buffer.BlockCopy(decryptedBytes, 0, plainTextBytes, 0, plainTextBytes.Length); string plainText = ASCIIEncoding.ASCII.GetString(plainTextBytes); txtDecryptedClientApplicationData.Text = plainText; byte[] hmacClientBytesReceived = new byte[16]; Buffer.BlockCopy(decryptedBytes, plainTextBytes.Length, hmacClientBytesReceived, 0, 16); txtClientApplicationDataHmac.Text = hmacClientBytesReceived.ToDisplayByteString(); var hmacFirstClientPacket = Hasher.ComputeTlsMD5Hmac(client_write_MAC_secret, 23, 1, plainTextBytes); Debug.Assert(ByteUtilities.AreEqual(hmacFirstClientPacket, hmacClientBytesReceived)); // get server reply var serverHandshakeMessages = ByteUtilities.ConcatBytes(handshakeMessages, clientFinishedHeaderAndVerify); var serverFinishedHeader = txtServerFinishedHeader.Text.FromWireshark(); md5Handshake = Hasher.ComputeMD5(serverHandshakeMessages); sha1Handshake = Hasher.ComputeSHA1Hash(serverHandshakeMessages); var serverVerifyData = Prf10.GenerateBytes(masterSecret, txtServerFinishedLabel.Text, ByteUtilities.ConcatBytes(md5Handshake, sha1Handshake), 12); txtServerFinishedVerifyData.Text = serverVerifyData.ToDisplayByteString(); var serverFirstHash = Hasher.ComputeTlsMD5Hmac(server_write_MAC_secret, 0x16, 0, ByteUtilities.ConcatBytes(serverFinishedHeader, serverVerifyData)); txtServerFinishedHmacMd5.Text = serverFirstHash.ToDisplayByteString(); var serverArc4 = new Arc4(server_write_key); var serverFinishedMessage = ByteUtilities.ConcatBytes(serverFinishedHeader, serverVerifyData, serverFirstHash); var encryptedServerFinishedMessage = serverArc4.Encrypt(serverFinishedMessage); Debug.Assert(ByteUtilities.AreEqual(encryptedServerFinishedMessage, txtServerEncryptedHandshakeMessage.Text.FromWireshark())); var serverApplicationDataBytes = txtServerApplicationDataInput.Text.FromWireshark(); var decryptedServerApplicationDataBytes = serverArc4.Encrypt(serverApplicationDataBytes); var serverPlainTextBytes = new byte[decryptedServerApplicationDataBytes.Length - 16]; Buffer.BlockCopy(decryptedServerApplicationDataBytes, 0, serverPlainTextBytes, 0, serverPlainTextBytes.Length); var hmacServerFirstPacketReceived = new byte[16]; Buffer.BlockCopy(decryptedServerApplicationDataBytes, serverPlainTextBytes.Length, hmacServerFirstPacketReceived, 0, 16); txtDecryptedServerApplicationData.Text = ASCIIEncoding.ASCII.GetString(serverPlainTextBytes); var hmacServerFirstPacketComputed = Hasher.ComputeTlsMD5Hmac(server_write_MAC_secret, 23, 1, serverPlainTextBytes); txtServerApplicationDataHmac.Text = hmacServerFirstPacketComputed.ToDisplayByteString(); Debug.Assert(ByteUtilities.AreEqual(hmacServerFirstPacketComputed, hmacServerFirstPacketComputed)); } catch (Exception ex) { MessageBox.Show("Error calculating derived handshake info: " + ex.Message); } }