private void SendClientHello() { var random = TLS12.GetRandom(); _session.ClientRandom = random; var clientHello = new ClientHello { Random = random, RSAPublicPem = _rsa.PublicPem }; var request = new SecurityLayerMessage { Type = SecurityMessageType.ClientHello, Data = _serializer.Serialize <ClientHello>(clientHello) }; var requestBytes = _serializer.Serialize <SecurityLayerMessage>(request); Send(requestBytes); var responseBytes = Receive(); var message = _serializer.Deserialize <SecurityLayerMessage>(responseBytes); var serverHello = _serializer.Deserialize <ServerHello>(message.Data); _session.Id = serverHello.SessionId; _session.ServerRandom = serverHello.Random; _session.RSAPublicPem = serverHello.RSAPublicPem; }
protected override void OnClientHello(byte[] buf, int size, IPEndPoint remoteEP) { if (ClientHello.TryUnpack(buf, 0, size, out _)) { m_Socket.Send(m_ServerHello, 0, m_ServerHello.Length, remoteEP); } }
public override string ToString() { return(ClientHello.ToString() + Environment.NewLine + ServerHello.ToString() + Environment.NewLine + ClientKeyExchange.ToString() + Environment.NewLine + Finished.ToString()); }
public static void HandleClientHello(LobbySession session, ClientHello hello) { session.CalculateNetworkKey(hello.Time, hello.Seed); session.SessionHash = XxHash.CalculateHash(Guid.NewGuid().ToByteArray()); session.Send(new ServerHello { SessionHash = session.SessionHash }); }
//Define the same method for the server side. public override Task <ServerHello> GetMessage(ClientHello request, ServerCallContext context) { string serverMessage = $@"Hello there {request.ClientName}"; Console.WriteLine($@"Recevied message from client {request.ClientName}: {request.ClientMessage}"); return(Task.FromResult(new ServerHello { ServerMessage = serverMessage, ServerName = _serverName, ServerNumber = _serverNumber })); }
public static bool TryUnpack(byte[] buf, int offset, int size, out ClientHello packet) { if (size <= 2) { packet = default; return(false); } packet = new ClientHello(buf[offset], buf[offset + 1]); return(true); }
public void TestJsonByteArrayIsBase64Encoded() { var rdm = new byte[] { 1, 2, 3 }; var obj = new ClientHello { ephDHKey = rdm }; var json = obj.ToJson(); Assert.AreEqual("{\"ephDHKey\":\"" + rdm.ToBase64String() + "\"}", json); }
public static void ParseClientHelloRecord(BytesSegment bs, ref ClientHello ch, out int size) { var payloadLen = GetRecordPayloadLength(bs, ref ch.Version); size = 5 + payloadLen; if (bs.Len < size) { return; } bs.SubSelf(5); bs.Len = Math.Min(bs.Len, payloadLen); ParseClientHello(bs, ref ch); }
public async Task <ClientConnectionImpl> Run() { try { m_Socket = new UdpSocket(); m_Socket.Bind(m_Settings.EndPoint.AddressFamily); if (!m_Settings.UseP2P) { m_Socket.Connect(m_Settings.EndPoint); } byte[] cookie; if (m_Settings.Cookie == null) { var buf = new ClientHello(Protocol.MajorVersion, Protocol.MinorVersion).Pack(); var req = new TimeoutRetryableRequester <ServerHello>(WaitServerHello(), () => Send(buf), m_Token); var res = await req.Run(); cookie = res.Cookie; } else { cookie = m_Settings.Cookie; } { m_Token.ThrowIfCancellationRequested(); var payload = new HandshakeRequestPayload(Random.GenInt(), m_Randam); byte[] payloadBuf = payload.Pack(); if (m_Settings.RSA != null) { payloadBuf = m_Settings.RSA.Encrypt(payloadBuf, RSAEncryptionPadding.Pkcs1); } var request = new HandshakeRequest(cookie, payloadBuf); m_EncryptorKey = new EncryptorKey(request, payload, 0); var res = await(new TimeoutRetryableRequester <HandshakeResult>(WaitHandshakeAccept(), () => Send(request.Pack()), m_Token)).Run(); m_Token.ThrowIfCancellationRequested(); return(new ClientConnectionImpl(res.ConnectionId, m_Socket, m_Settings, res.Encryptor, m_EncryptorGenerator)); } } catch (Exception ex) { Log.Exception(ex); m_Socket.Dispose(); m_EncryptorGenerator.Dispose(); throw; } }
public bool ConnectToServer(IPEndPoint serverAddress, bool playerIsRed, string playerName) { var clientHello = new ClientHello(playerIsRed, playerName); server = new TcpClient(); server.Connect(serverAddress); serverConnection = server.GetStream(); Network.SendPacket(clientHello, serverConnection); var serverHello = (ServerHello)Network.ReceivePacket(serverConnection); this.playerName = playerName; this.playerIsRed = serverHello.ColorIsRed; if (serverHello.EnemyName == null) { return(false); } enemyName = serverHello.EnemyName; return(true); }
private static async Task <Record> SendClientHelloAsync(TlsRequestParameters requestParameters) { if (requestParameters.CipherSuites == null) { requestParameters.CipherSuites = new CipherSuites[] { Tls.CipherSuites.TLS_AES_128_GCM_SHA256, Tls.CipherSuites.TLS_AES_256_GCM_SHA384, Tls.CipherSuites.TLS_CHACHA20_POLY1305_SHA256, Tls.CipherSuites.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, Tls.CipherSuites.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, Tls.CipherSuites.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, Tls.CipherSuites.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, Tls.CipherSuites.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, Tls.CipherSuites.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, Tls.CipherSuites.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, Tls.CipherSuites.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, Tls.CipherSuites.TLS_RSA_WITH_AES_128_GCM_SHA256, Tls.CipherSuites.TLS_RSA_WITH_AES_256_GCM_SHA384, Tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA, Tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA, Tls.CipherSuites.TLS_RSA_WITH_3DES_EDE_CBC_SHA }; } using (TcpClient client = new TcpClient()) { await client.ConnectAsync(requestParameters.Host, requestParameters.Port); NetworkStream s = client.GetStream(); s.ReadTimeout = ServerReadTimeoutInSeconds * 1000; ClientHello hello = new ClientHello( requestParameters.HandshakeVersion, requestParameters.CipherSuites, requestParameters.RecordVersion); await WriteRecordToStreamAsync(hello, s); return(await HandleResponse(s, requestParameters)); } }
public byte[] ConstructClientHello(ClientMessageType type, ushort clientId, string playerName) { fbBuilder.Clear(); StringOffset playerNameOffset = fbBuilder.CreateString(playerName); ClientHello.StartClientHello(fbBuilder); ClientHello.AddPlayerName(fbBuilder, playerNameOffset); Offset <ClientHello> clientHelloOffset = ClientHello.EndClientHello(fbBuilder); ClientMessage.StartClientMessage(fbBuilder); //var clientIdOffset = clientId; ClientMessage.AddClientId(fbBuilder, clientId); ClientMessage.AddMsgType(fbBuilder, type); ClientMessage.AddMsg(fbBuilder, clientHelloOffset.Value); Offset <ClientMessage> clientMessageOffset = ClientMessage.EndClientMessage(fbBuilder); ClientMessage.FinishClientMessageBuffer(fbBuilder, clientMessageOffset); return(fbBuilder.SizedByteArray()); }
public async Task <ClientHello> ReadClientHello() { var recordHeader = new BytesSegment(new byte[5]); await RealBaseStream.ReadFullAsyncR(recordHeader); MyStreamWrapper.Queue = recordHeader; ushort ver = 0; int recordPayloadLength = GetRecordPayloadLength(recordHeader, ref ver); var record = new BytesSegment(new byte[5 + recordPayloadLength]); recordHeader.CopyTo(record); var msg = record.Sub(5); await RealBaseStream.ReadFullAsyncR(msg); MyStreamWrapper.Queue = record; var ch = new ClientHello(); ParseClientHello(msg, ref ch); return(ch); }
public bool GetServerHello(byte[] clientHello, out byte[] serverHello) { serverHello = null; if (!ClientHello.Parse(clientHello, out ClientHello ch)) { return(false); } var nonce = ByteHelper.GetRandom(32); var proofOfWorkDetails = ByteHelper.GetRandom(32); proofOfWorkDetails[0] = 15; serverHello = ByteHelper.Combine(nonce, proofOfWorkDetails); Session.ClientEphDHPubKey = ch.ephDHKey; return(true); }
public static ByteSpan Test_CompressionLengthOverrunClientHello(ClientHello clientHello, ByteSpan writer) { ByteSpanBigEndianExtensions.WriteBigEndian16(writer, (ushort)ProtocolVersion.DTLS1_2); writer = writer.Slice(2); clientHello.Random.CopyTo(writer); writer = writer.Slice(Hazel.Dtls.Random.Size); // Do not encode session ids writer[0] = (byte)0; writer = writer.Slice(1); writer[0] = (byte)clientHello.Cookie.Length; clientHello.Cookie.CopyTo(writer.Slice(1)); writer = writer.Slice(1 + clientHello.Cookie.Length); ByteSpanBigEndianExtensions.WriteBigEndian16(writer, (ushort)clientHello.CipherSuites.Length); clientHello.CipherSuites.CopyTo(writer.Slice(2)); writer = writer.Slice(2 + clientHello.CipherSuites.Length); // ============ Here is the corruption. writer[0] should be 1. ============ writer[0] = 255; writer[1] = (byte)CompressionMethod.Null; writer = writer.Slice(2); // Extensions size ByteSpanBigEndianExtensions.WriteBigEndian16(writer, (ushort)(6 + clientHello.SupportedCurves.Length)); writer = writer.Slice(2); // Supported curves extension ByteSpanBigEndianExtensions.WriteBigEndian16(writer, (ushort)ExtensionType.EllipticCurves); ByteSpanBigEndianExtensions.WriteBigEndian16(writer, (ushort)(2 + clientHello.SupportedCurves.Length), 2); ByteSpanBigEndianExtensions.WriteBigEndian16(writer, (ushort)clientHello.SupportedCurves.Length, 4); clientHello.SupportedCurves.CopyTo(writer.Slice(6)); return(writer); }
/// <summary> /// Reads the TLS Client Hello from the tcp stream, parsing out the server name provided by the Server Name extension. Returns a stream that behaves as if nothing had been read. /// </summary> /// <param name="tcpStream">The stream that is expected to begin a TLS 1.0, 1.1, or 1.2 handshake.</param> /// <param name="serverName">The server name from the TLS Server Name extension. Or null.</param> /// <returns></returns> /// <exception cref="Exception">Throws if there is a problem parsing the TLS Client Hello.</exception> public static Stream Read(Stream tcpStream, out string serverName) { UnreadableStream unread = new UnreadableStream(tcpStream); FragmentStream readerOfClientHello = new FragmentStream(() => { TLSPlaintext fragment = new TLSPlaintext(tcpStream); unread.Unread(fragment.data_header); unread.Unread(fragment.data_fragment); if (fragment.type != ContentType.handshake) { throw new Exception("TLS protocol error: Fragment began with byte " + (byte)fragment.type + ". Expected " + (byte)ContentType.handshake); } if (!fragment.version.IsSupported()) { throw new Exception("Unsupported TLS protocol version: " + fragment.version); } return(fragment); }); HandshakeMessage firstHandshakeMessage = new HandshakeMessage(new BasicDataStream(readerOfClientHello)); if (firstHandshakeMessage.msg_type == HandshakeType.client_hello) { ClientHello clientHello = firstHandshakeMessage.body as ClientHello; serverName = clientHello.serverName; } else { serverName = null; } return(unread); }
public async Task Handshake() { var client_hello = new ClientHello() { HumanReadableName = HumanReadableName, Name = Name, Version = Version, License = License, Capabilities = Capabilities.ToList() }; await Connection.Send(client_hello); var server_hello = await Connection.Receive(); if (!(server_hello is ServerHello)) { throw new Exception($"Expected ServerHello, received {server_hello?.GetType()}"); } await RegisterCommands(); Connected.Set(); }
//[Fact] public void Test1() { var buff = new byte[PacketBuffer.MaxPacketSize]; var pBuff = Utils.ParseHexString("060040f1010000ed0303ebf8fa56f12939b9584a3896472ec40bb863cfd3e86804fe3a47f06a2b69484c00000413011302010000c000000010000e00000b6578616d706c652e636f6dff01000100000a00080006001d0017001800100007000504616c706e000500050100000000003300260024001d00209370b2c9caa47fbabaf4559fedba753de171fa71f50f1ce15d43e994ec74d748002b0003020304000d0010000e0403050306030203080408050806002d00020101001c00024001ffa500320408ffffffffffffffff05048000ffff07048000ffff0801100104800075300901100f088394c8f03e51570806048000ffff"); var hBuff = Utils.ParseHexString("c3ff000020088394c8f03e5157080000449e00000002"); Array.Resize(ref pBuff, 1162); Array.Copy(hBuff, buff, hBuff.Length); Array.Copy(pBuff, 0, buff, hBuff.Length, pBuff.Length); Array.Resize(ref buff, hBuff.Length + pBuff.Length); var encryptedBuff = new byte[PacketBuffer.MaxPacketSize]; var aead = Cipher.TLS_AES_128_GCM_SHA256.CreateAead(Utils.ParseHexString("6b26114b9cba2b63a9e8dd4f"), Utils.ParseHexString("175257a31eb09dea9366d8bb79ad80ba")); //var token = aead.StartEncryption(pBuff, encryptedBuff); //token.UseSequenceNumber(2); //token.UseAssociatedData(hBuff); //aead.Finish(token); //var encryptedHex = Utils.ToHexString(token.Result.ToArray()); var c = new MemoryCursor(buff); var res1 = InitialPacket.TryParse(c, out var p); using (p.Payload.SetCursor(c)) { var res2 = CryptoFrame.TryParse(c, out var f); } var res3 = c.IsEnd(); var buffer = new byte[PacketBuffer.MaxPacketSize]; var cursor = new MemoryCursor(buffer); using (InitialPacket.StartWriting( cursor, PacketVersion.CreateByDraft(29), PacketConnectionId.Generate(), PacketConnectionId.Generate(), PacketNumber.Initial, PacketToken.Empty)) { using (CryptoFrame.StartWriting(cursor, 0)) { using (ClientHello.StartWriting(cursor, HandshakeRandom.Generate(), Cipher.Supported, SessionId.Generate())) { using (cursor.StartSupportedGroupsWriting()) { foreach (var group in NamedGroup.Supported.Span) { group.WriteBytes(cursor); } } using (cursor.StartSignatureAlgorithmsWriting()) { foreach (var scheme in SignatureScheme.Supported.Span) { scheme.WriteBytes(cursor); } } using (cursor.StartKeySharesWriting()) { using (KeyShareEntry.StartWriting(cursor, NamedGroup.X25519)) { Utils.ParseHexString("358072d6365880d1aeea329adf9121383851ed21a28e3b75e965d0d2cd166254").CopyTo(cursor); } } using (cursor.StartPskKeyExchangeModesWriting()) { PskKeyExchangeMode.PskDheKe.WriteBytes(cursor); } using (cursor.StartSupportedVersionsWriting()) { ProtocolVersion.Tls13.WriteBytes(cursor); } cursor.StartTransportParametersWriting().Dispose(); } for (int i = 0; i < 1000; i++) { PaddingFrame.WriteBytes(cursor); } } } var t = Utils.ParseHexString("c0ff00001d08d0076f25b832934b0841f39c4f6381d72e0044ba00060041060100010203036e3828a258f4a7488d105acd6da670a41b28c2b601c58c4530486df585ec54a6000006130213011303010000d30033004700450017004104e46de65fb3e4fa258e1f03c551fa6a4507411e09bdc32e4dc597084db1852caf9d5b783243ebc748bf644ca31e108f4fdea2c19ae3c94ad99714dfa38a6a244500000021001f00001c68747470332d746573742e6c6974657370656564746563682e636f6d0010000800060568332d3239002b0003020304000d000a00080804040304010201000a000600040017001dffa5002d050480004000070480004000040480008000080101090103010267100e0104030245c00f0841f39c4f6381d72e002d000302000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); var client = new UdpClient(0); var endPoint = new IPEndPoint(IPAddress.Parse("52.55.120.73"), 443); client.Send(t, t.Length, endPoint); IPEndPoint ep = null; var response = client.Receive(ref ep); var h1 = Utils.ToHexString(response); cursor = new MemoryCursor(response); var result = InitialPacket.TryParse(cursor, out var packet); using (packet.Payload.SetCursor(cursor)) { var h2 = Utils.ToHexString(cursor.PeekEnd().ToArray()); CryptoFrame.TryParse(cursor, out var cryptoFrame); using (cryptoFrame.Data.SetCursor(cursor)) { ServerHello.TryParse(cursor, out var sh); } } Assert.True(true); //var snBuff = new byte[100]; //var snIter = snBuff.AsSpan(); //ServerNameExtension.WriteHostName(ref snIter, "example.ulfheim.net"); //var snResult = Parse(snBuff.AsSpan().Slice(0, snBuff.Length - snIter.Length).ToArray()); //var keyShareBuff = new byte[1000]; //var keyShareSpan = keyShareBuff.AsSpan(); //var privateKey = Parse("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"); //var publicKey = NamedGroup.X25519.GeneratePublicKey(privateKey); //KeyShareExtension.WriteClientEntry(ref keyShareSpan, NamedGroup.X25519, publicKey); //var keyShareData = Parse(keyShareBuff.AsSpan().Slice(0, keyShareBuff.Length - keyShareSpan.Length).ToArray()); //var secret = Parse("ff0e5b965291c608c1e8cd267eefc0afcc5e98a2786373f0db47b04786d72aea"); //var hash = Parse("22844b930e5e0a59a09d5ac35fc032fc91163b193874a265236e568077378d8b"); //var expected = Parse("976017a77ae47f1658e28f7085fe37d149d1e9c91f56e1aebbe0c6bb054bd92b"); //var verifyData = Hash.Sha256.CreateVerifyData(secret, hash); //var result = verifyData.Span.SequenceEqual(expected); //var bytes = GetData(); //InitialPacket.TryParse(bytes, out var initial, out var remainings); //CryptoFrame.TryParse(initial.Payload, out var crypto, out var afterCrypto); //ClientHello.TryParse(crypto.Data, out var hello, out var afterHello); //KeyShareExtension.TryParse(hello.Payload, out var keyShare, out var afterKeyShare); //var unknownBytes = UnknownExtension.SliceBytes(afterKeyShare, out var afterUnknown); //AlpnExtension.TryParse(afterUnknown, out var alpn, out var afterAlpn); //SupportedVersionExtension.TryParse(afterAlpn, out var supportedVersion, out var afterSupportedVersion); //SignatureAlgorithmsExtension.TryParse(afterSupportedVersion, out var signatureAlgorithms, out var afterSignatureAlgorithms); //SupportedGroupsExtension.TryParse(afterSignatureAlgorithms, out var supportedGroups, out var afterSupportedGroups); //TransportParametersExtension.TryParse(afterSupportedGroups, out var transportParametersExtension, out var afterTransportParametersExtension); //PskKeyExchangeModesExtension.TryParse(afterTransportParametersExtension, out var pskKeyExchangeModes, out var afterPsk); ////---------------------------------------------------------------- //var buffer = new byte[65000]; //var destination = buffer.AsSpan(); //var initialContext = InitialPacket.StartWriting(ref destination, initial.Version, initial.DestinationConnectionId, initial.SourceConnectionId, initial.Number, initial.Token); //var cryptoContext = CryptoFrame.StartWriting(ref destination, 0); //var clientHelloContext = ClientHello.StartWriting(ref destination, hello.Random, hello.CipherSuite, hello.SessionId); //keyShare.WriteBytes(ref destination); //unknownBytes.Span.CopyTo(destination); //destination = destination.Slice(unknownBytes.Length); //alpn.WriteBytes(ref destination); //supportedVersion.WriteBytes(ref destination); //signatureAlgorithms.WriteBytes(ref destination); //supportedGroups.WriteBytes(ref destination); //var transportParametersContext = TransportParametersExtension.StartWriting(ref destination); //transportParametersExtension.Data.Span.CopyTo(destination); //destination = destination.Slice(transportParametersExtension.Data.Length); //transportParametersContext.Complete(ref destination); //pskKeyExchangeModes.WriteBytes(ref destination); //clientHelloContext.Complete(ref destination); //cryptoContext.Complete(ref destination); //for (int i = 0; i < 1000; i++) //{ // PaddingFrame.WriteBytes(ref destination); //} //initialContext.Complete(ref destination); ////---------------------------------------------------------------- //InitialPacket.TryParse(buffer.ToArray(), out var initial1, out var remainings1); //CryptoFrame.TryParse(initial1.Payload, out var crypto1, out var afterCrypto1); //ClientHello.TryParse(crypto1.Data, out var hello1, out var afterHello1); //KeyShareExtension.TryParse(hello1.Payload, out var keyShare1, out var afterKeyShare1); //var unknownBytes1 = UnknownExtension.SliceBytes(afterKeyShare1, out var afterUnknown1); //AlpnExtension.TryParse(afterUnknown1, out var alpn1, out var afterAlpn1); //SupportedVersionExtension.TryParse(afterAlpn1, out var supportedVersion1, out var afterSupportedVersion1); //SignatureAlgorithmsExtension.TryParse(afterSupportedVersion1, out var signatureAlgorithms1, out var afterSignatureAlgorithms1); //SupportedGroupsExtension.TryParse(afterSignatureAlgorithms1, out var supportedGroups1, out var afterSupportedGroups1); //TransportParametersExtension.TryParse(afterSupportedGroups1, out var transportParametersExtension1, out var afterTransportParametersExtension1); //PskKeyExchangeModesExtension.TryParse(afterTransportParametersExtension1, out var pskKeyExchangeModes1, out var afterPsk1); //var client = DatagramChannel.Start(opt => //{ // opt.ListeningPoint = new IPEndPoint(IPAddress.Any, 50000); //}); //var addr = Dns.GetHostAddresses("litespeedtech.com"); //443 ////var addr = Dns.GetHostAddresses("test.privateoctopus.com"); //4433 ////var addr = Dns.GetHostAddresses("quant.eggert.org"); //4433 ////var addr = Dns.GetHostAddresses("f5quic.com"); //4433 //var dgram = new Datagram().WithAddress(addr[0]).WithPort(443).WithBuffer(buffer.ToArray()); //client.Writer.TryWrite(dgram); //var response = client.Reader.ReadAsync().AsTask().Result; }
public void Read_ResultsAreExpected() { //Arrange var messageBytes = Utils.ParseHexString(GetMessageHexString()); var record = new TlsRecord(); var message = new ClientHello(); var serverNames = new List <ServerNameEntry>(); var namedGroups = new List <NamedGroup>(); var signatureSchemes = new List <SignatureScheme>(); var keyShareEntries = new List <KeyShareEntry>(); var pskModes = new List <PskKeyExchangeMode>(); var supportedVersions = new List <ProtocolVersion>(); var ciphers = new List <Cipher>(); //Act var cursor = new MemoryCursor(messageBytes); var result = TlsRecord.TryParse(cursor, RecordType.Handshake, out record); using (record.Payload.SetCursor(cursor)) { result &= ClientHello.TryParse(cursor, out message); foreach (var cipher in message.CipherSuite) { ciphers.Add(cipher); } using (message.Payload.SetCursor(cursor)) { result &= cursor.TryParseServerNames(out var serverNamesBuffer); foreach (var entry in serverNamesBuffer.GetServerNameEntryReader(cursor)) { serverNames.Add(entry); } result &= cursor.TryParseSupportedGroups(out var supportedGroupsBuffer); foreach (var group in supportedGroupsBuffer.GetNamedGroupReader(cursor)) { namedGroups.Add(group); } result &= cursor.TryParseSignatureAlgorithms(out var signatureAlgorithmsBuffer); foreach (var scheme in signatureAlgorithmsBuffer.GetSignatureSchemeReader(cursor)) { signatureSchemes.Add(scheme); } result &= cursor.TryParseKeyShares(out var keySharesBuffer); foreach (var entry in keySharesBuffer.GetKeyShareEntryReader(cursor)) { keyShareEntries.Add(entry); } result &= cursor.TryParsePskKeyExchangeModes(out var pskModesBuffer); foreach (var mode in pskModesBuffer.GetPskKeyExchangeModeReader(cursor)) { pskModes.Add(mode); } result &= cursor.TryParseSupportedVersions(out var supportedVersionsBuffer); foreach (var version in supportedVersionsBuffer.GetProtocolVersionReader(cursor)) { supportedVersions.Add(version); } result &= cursor.IsEnd(); } result &= cursor.IsEnd(); } result &= cursor.IsEnd(); //Assert Assert.True(result); Assert.Equal(RecordType.Handshake, record.Type); Assert.Equal(ProtocolVersion.Tls10, record.ProtocolVersion); Assert.Equal(HandshakeRandom.Parse(GetBytesOfRandom()), message.Random); Assert.Equal(SessionId.Parse(GetBytesOfSessionId()), message.SessionId); Assert.Equal(new[] { Cipher.TLS_AES_128_GCM_SHA256, Cipher.TLS_AES_256_GCM_SHA384, Cipher.TLS_CHACHA20_POLY1305_SHA256 }, ciphers); var serverNameEntry = Assert.Single(serverNames); Assert.True(serverNameEntry.IsHostName()); Assert.Equal("example.ulfheim.net", serverNameEntry.ToString()); Assert.Equal(new[] { NamedGroup.X25519, NamedGroup.SECP256R1, NamedGroup.SECP384R1 }, namedGroups); Assert.Equal(new[] { SignatureScheme.ECDSA_SECP256R1_SHA256, SignatureScheme.RSA_PSS_RSAE_SHA256, SignatureScheme.RSA_PKCS1_SHA256, SignatureScheme.ECDSA_SECP384R1_SHA384, SignatureScheme.RSA_PSS_RSAE_SHA384, SignatureScheme.RSA_PKCS1_SHA384, SignatureScheme.RSA_PSS_RSAE_SHA512, SignatureScheme.RSA_PKCS1_SHA512, SignatureScheme.RSA_PKCS1_SHA1 }, signatureSchemes); var keyShareEntry = Assert.Single(keyShareEntries); Assert.Equal(NamedGroup.X25519, keyShareEntry.Group); Assert.True(GetBytesOfPublicKey().AsSpan().SequenceEqual(keyShareEntry.Key.Read(cursor).Span)); var pskMode = Assert.Single(pskModes); Assert.Equal(PskKeyExchangeMode.PskDheKe, pskMode); var supportedVersion = Assert.Single(supportedVersions); Assert.Equal(ProtocolVersion.Tls13, supportedVersion); }
public void Write_ResultBytesAreExpected() { //Arrange var expectedBytes = GetMessageHexString(); var buffer = new byte[TlsBuffer.MaxRecordSize]; var random = HandshakeRandom.Parse(GetBytesOfRandom()); var ciphers = new[] { Cipher.TLS_AES_128_GCM_SHA256, Cipher.TLS_AES_256_GCM_SHA384, Cipher.TLS_CHACHA20_POLY1305_SHA256 }; var sessionId = SessionId.Parse(GetBytesOfSessionId()); //Act var cursor = new MemoryCursor(buffer); using (TlsRecord.StartWriting(cursor, RecordType.Handshake, ProtocolVersion.Tls10)) using (ClientHello.StartWriting(cursor, random, ciphers, sessionId)) { using (cursor.StartServerNamesWriting()) { ServerNameEntry.WriteHostName(cursor, "example.ulfheim.net"); } using (cursor.StartSupportedGroupsWriting()) { NamedGroup.X25519.WriteBytes(cursor); NamedGroup.SECP256R1.WriteBytes(cursor); NamedGroup.SECP384R1.WriteBytes(cursor); } using (cursor.StartSignatureAlgorithmsWriting()) { SignatureScheme.ECDSA_SECP256R1_SHA256.WriteBytes(cursor); SignatureScheme.RSA_PSS_RSAE_SHA256.WriteBytes(cursor); SignatureScheme.RSA_PKCS1_SHA256.WriteBytes(cursor); SignatureScheme.ECDSA_SECP384R1_SHA384.WriteBytes(cursor); SignatureScheme.RSA_PSS_RSAE_SHA384.WriteBytes(cursor); SignatureScheme.RSA_PKCS1_SHA384.WriteBytes(cursor); SignatureScheme.RSA_PSS_RSAE_SHA512.WriteBytes(cursor); SignatureScheme.RSA_PKCS1_SHA512.WriteBytes(cursor); SignatureScheme.RSA_PKCS1_SHA1.WriteBytes(cursor); } using (cursor.StartKeySharesWriting()) { using (KeyShareEntry.StartWriting(cursor, NamedGroup.X25519)) { GetBytesOfPublicKey().CopyTo(cursor); } } using (cursor.StartPskKeyExchangeModesWriting()) { PskKeyExchangeMode.PskDheKe.WriteBytes(cursor); } using (cursor.StartSupportedVersionsWriting()) { ProtocolVersion.Tls13.WriteBytes(cursor); } } //Assert Assert.Equal(expectedBytes, Utils.ToHexString(cursor.PeekStart().ToArray()), true); }
/// <summary> /// Handles a ClientHello packet. /// </summary> /// <param name="session">The session that sent this packet.</param> /// <param name="hello">The ClientHello data that was sent.</param> private void HandleClientHello(ClientAgentSession sender, ClientHello hello) { // Logging Log?.Info("Handling ClientHello from session {0}.", sender.SessionId); // Let's see if this client is valid... ClientHelloResponse response = new ClientHelloResponse { Success = true, ErrorCode = 0, Message = "", HeartbeatTime = Configuration.HeartbeatTime, ForcedEncryption = Configuration.ForceEncryption }; // Get the correct wanted hash uint wantedHash = Configuration.Network.Hash != 0 ? Configuration.Network.Hash : NetworkFile.Hash; // Is the client the wrong application? if (hello.AppName != Configuration.Application.Name) { response.Success = false; response.ErrorCode = (byte)ToffeeErrorCodes.ClientHelloApplicationInvalid; Log?.Warning("Invalid ClientHello from session {0}. ({1})", sender.SessionId, ToffeeErrorCodes.ClientHelloApplicationInvalid); } // Is the client outdated? else if (hello.AppVersion != Configuration.Application.Version) { response.Success = false; response.ErrorCode = (byte)ToffeeErrorCodes.ClientHelloApplicationOutOfDate; Log?.Warning("Invalid ClientHello from session {0}. ({1})", sender.SessionId, ToffeeErrorCodes.ClientHelloApplicationOutOfDate); } // Is their encryption the same as ours? else if ((Configuration.EncryptionKey == 0x00) && (hello.HasEncryption)) { response.Success = false; response.ErrorCode = (byte)ToffeeErrorCodes.ClientHelloEncryptionInvalid; response.Message = "The server is not configured to have encryption."; Log?.Warning("Invalid ClientHello from session {0}. ({1}, {2})", sender.SessionId, ToffeeErrorCodes.ClientHelloEncryptionInvalid, response.Message); } // If we force encryption, do they have encryption? else if ((Configuration.ForceEncryption) && (!hello.HasEncryption)) { response.Success = false; response.ErrorCode = (byte)ToffeeErrorCodes.ClientHelloEncryptionInvalid; response.Message = "The server is configured to force encryption."; Log?.Warning("Invalid ClientHello from session {0}. ({1}, {2})", sender.SessionId, ToffeeErrorCodes.ClientHelloEncryptionInvalid, response.Message); } // Do they have the same network hash? else if (hello.NetworkHash != wantedHash) { response.Success = false; response.ErrorCode = (byte)ToffeeErrorCodes.ClientHelloHashInvalid; Log?.Warning("Invalid ClientHello from session {0}. ({1})", sender.SessionId, ToffeeErrorCodes.ClientHelloHashInvalid); } else { sender.Validated = true; Log?.Info("ClientHello was valid! Session {0} has been validated.", sender.SessionId); } // Send the response! sender.Send(ToffeeOpCode.ClientHelloResponse, response); // Debug information Log?.Debug("=== Response Info ==="); Log?.Debug("OpCode: 0x02 (ClientHelloResponse)"); Log?.Debug("Success: {0}", response.Success); Log?.Debug("ErrorCode: {0}", response.ErrorCode); Log?.Debug("Message: {0}", response.Message); Log?.Debug("HeartbeatTime: {0}", response.HeartbeatTime); Log?.Debug("ForcedEncryption: {0}", response.ForcedEncryption); Log?.Debug("====================="); Log?.Debug(""); }
private bool FullProtocolFromX509(ScpConfig.EncryptionMode encryptionMode, out byte[] symmetricKey, out MockedSecretarium secretarium) { // Client keys Assert.IsTrue(ScpConfigHelper.TryLoad("test.x509.json", out ScpConfig config)); Assert.IsTrue(config.TryGetECDsaKey(out ECDsaCng clientECDsaKeyCng, "SecretariumTestClient256")); var clientPub = clientECDsaKeyCng.ExportPublicKeyRaw(); // Client Hello var clientEph = ECDHHelper.CreateCngKey(); var clientEphCng = ECDHHelper.CreateECDiffieHellmanCngSha256(clientEph); var clientEphPub = clientEphCng.PublicKey(); var clientHello = clientEphPub; Assert.IsTrue(ClientHello.Parse(clientHello, out ClientHello clientHelloObj)); // Server Hello secretarium = new MockedSecretarium(encryptionMode); secretarium.GetServerHello(clientHello, out byte[] serverHello); Assert.IsTrue(ServerHello.Parse(serverHello, 18, out ServerHello serverHelloObj)); // Client ClientProofOfWork Assert.IsTrue(DiffieHellmanHelper.ComputeProofOfWork(serverHelloObj.proofOfWorkDetails, out byte[] proofOfWork)); var clientProofOfWork = ByteHelper.Combine(proofOfWork.ExtendTo(32), MockedSecretarium.GenesisPubKey); Assert.IsTrue(ClientProofOfWork.Parse(clientProofOfWork, out ClientProofOfWork clientProofOfWorkObj)); // Server Identity secretarium.GetServerIdentity(clientProofOfWork, out byte[] serverIdentity); Assert.IsTrue(ServerIdentity.Parse(serverIdentity, out ServerIdentity serverIdentityObj)); // Client computes symmetric key symmetricKey = DiffieHellmanHelper.GetSymmetricKey( clientEphCng, serverIdentityObj.ephDHKey, serverIdentityObj.preMasterSecret); // Client Proof Of Identity var nonce = ByteHelper.GetRandom(32); var nonceSigned = clientECDsaKeyCng.SignData(nonce); var clientProofOfIdentity = ByteHelper.Combine(nonce, clientEphPub, clientPub, nonceSigned); Assert.IsTrue(ClientProofOfIdentity.Parse(clientProofOfIdentity, out ClientProofOfIdentity clientProofOfIdentityObj)); // Client Encrypts Client Proof Of Identity var ivOffset = ByteHelper.GetRandom(16); var encryptedClientProofOfIdentity = encryptionMode == ScpConfig.EncryptionMode.AESCTR ? clientProofOfIdentity.AesCtrEncrypt(symmetricKey, ivOffset) : clientProofOfIdentity.AesGcmEncryptWithOffset(symmetricKey, ivOffset); var encryptedClientProofOfIdentityWithIvOffset = ByteHelper.Combine(ivOffset, encryptedClientProofOfIdentity); // Server Checks And Sends Proof Of Identity Assert.IsTrue(secretarium.GetServerProofOfIdentity( encryptedClientProofOfIdentityWithIvOffset, out byte[] encryptedServerProofOfIdentity)); // Client Decrypts Server Proof Of Identity ivOffset = encryptedServerProofOfIdentity.Extract(0, 16); var serverProofOfIdentity = encryptionMode == ScpConfig.EncryptionMode.AESCTR ? encryptedServerProofOfIdentity.Extract(16).AesCtrDecrypt(symmetricKey, ivOffset) : encryptedServerProofOfIdentity.Extract(16).AesGcmDecryptWithOffset(symmetricKey, ivOffset); Assert.IsTrue(ServerProofOfIdentity.Parse(serverProofOfIdentity, out ServerProofOfIdentity serverProofOfIdentityObj)); // Client Checks Server Proof Of Idendity var msg = "Hey you! Welcome to Secretarium!".ToBytes(); var secretariumECDsaCng = ECDsaHelper.ImportPublicKey(serverIdentityObj.publicKey); Assert.IsTrue(secretariumECDsaCng.VerifyData( ByteHelper.Combine(serverProofOfIdentityObj.nonce, msg), serverProofOfIdentityObj.welcomeSigned)); return(true); }
/// <summary> /// <exception cref="IOException"/> /// <exception cref="SpotifyAuthenticatedException"/> /// <exception cref="AccessViolationException"/> /// </summary> private void Connect() { #region ClientHello Setup ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; var clientHello = new ClientHello { BuildInfo = new BuildInfo { Platform = Platform.Win32X86, Product = Product.Client, ProductFlags = { ProductFlags.ProductFlagNone }, Version = 112800721 } }; clientHello.CryptosuitesSupported.Add(Cryptosuite.Shannon); clientHello.LoginCryptoHello = new LoginCryptoHelloUnion { DiffieHellman = new LoginCryptoDiffieHellmanHello { Gc = ByteString.CopyFrom(keys.PublicKeyArray()), ServerKeysKnown = 1 } }; var nonce = new byte[16]; (new Random()).NextBytes(nonce); clientHello.ClientNonce = ByteString.CopyFrom(nonce); clientHello.Padding = ByteString.CopyFrom(new byte[1] { (byte)30 }); var clientHelloBytes = clientHello.ToByteArray(); var a = conn.Result.NetworkStream; a.WriteByte(0x00); a.WriteByte(0x04); a.WriteByte(0x00); a.WriteByte(0x00); a.WriteByte(0x00); a.Flush(); var length = 2 + 4 + clientHelloBytes.Length; var bytes = BitConverter.GetBytes(length); a.WriteByte(bytes[0]); a.Write(clientHelloBytes, 0, clientHelloBytes.Length); a.Flush(); var buffer = new byte[1000]; var len = int.Parse(a.Read(buffer, 0, buffer.Length).ToString()); var tmp = new byte[len]; Array.Copy(buffer, tmp, len); tmp = tmp.Skip(4).ToArray(); var accumulator = new MemoryStream(); accumulator.WriteByte(0x00); accumulator.WriteByte(0x04); var lnarr = Utils.toByteArray(length); accumulator.Write(lnarr, 0, lnarr.Length); accumulator.Write((byte[])clientHelloBytes, 0, clientHelloBytes.Length); var lenArr = Utils.toByteArray(len); accumulator.Write(lenArr, 0, lenArr.Length); accumulator.Write((byte[])tmp, 0, tmp.Length); #endregion ClientHello Setup //Read APResponseMessage #region APResponse var binaryData = accumulator.ToArray(); var apResponseMessage = APResponseMessage.Parser.ParseFrom(tmp); var sharedKey = Utils.toByteArray(keys.ComputeSharedKey(apResponseMessage .Challenge.LoginCryptoChallenge.DiffieHellman.Gs.ToByteArray())); // Check gs_signature var rsa = new RSACryptoServiceProvider(); var rsaKeyInfo = new RSAParameters { Modulus = new BigInteger(1, serverKey).ToByteArrayUnsigned(), Exponent = BigInteger.ValueOf(65537).ToByteArrayUnsigned() }; //Set to the public key values. //Import key parameters into RSA. rsa.ImportParameters(rsaKeyInfo); var gs = apResponseMessage.Challenge.LoginCryptoChallenge.DiffieHellman.Gs.ToByteArray(); var sign = apResponseMessage.Challenge.LoginCryptoChallenge.DiffieHellman.GsSignature.ToByteArray(); if (!rsa.VerifyData(gs, sign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1)) { throw new AccessViolationException("Failed to verify APResponse"); } // Solve challenge binaryData = accumulator.ToArray(); using var data = new MemoryStream(); var mac = new HMACSHA1(sharedKey); mac.Initialize(); for (var i = 1; i < 6; i++) { mac.TransformBlock(binaryData, 0, binaryData.Length, null, 0); var temp = new[] { (byte)i }; mac.TransformBlock(temp, 0, temp.Length, null, 0); mac.TransformFinalBlock(new byte[0], 0, 0); var final = mac.Hash; data.Write(final, 0, final.Length); mac = new HMACSHA1(sharedKey); } var dataArray = data.ToArray(); mac = new HMACSHA1(Arrays.CopyOfRange(dataArray, 0, 0x14)); mac.TransformBlock(binaryData, 0, binaryData.Length, null, 0); mac.TransformFinalBlock(new byte[0], 0, 0); var challenge = mac.Hash; var clientResponsePlaintext = new ClientResponsePlaintext { LoginCryptoResponse = new LoginCryptoResponseUnion { DiffieHellman = new LoginCryptoDiffieHellmanResponse { Hmac = ByteString.CopyFrom(challenge) } }, PowResponse = new PoWResponseUnion(), CryptoResponse = new CryptoResponseUnion() }; var clientResponsePlaintextBytes = clientResponsePlaintext.ToByteArray(); len = 4 + clientResponsePlaintextBytes.Length; a.WriteByte(0x00); a.WriteByte(0x00); a.WriteByte(0x00); var bytesb = BitConverter.GetBytes(len); a.WriteByte(bytesb[0]); a.Write(clientResponsePlaintextBytes, 0, clientResponsePlaintextBytes.Length); a.Flush(); try { var scrap = new byte[4]; conn.Result.NetworkStream.ReadTimeout = 300; var read = conn.Result.NetworkStream.Read(scrap, 0, scrap.Length); if (read == scrap.Length) { length = (scrap[0] << 24) | (scrap[1] << 16) | (scrap[2] << 8) | (scrap[3] & 0xFF); var payload = new byte[length - 4]; conn.Result.NetworkStream.ReadComplete(payload, 0, payload.Length); var failed = APResponseMessage.Parser.ParseFrom(payload)?.LoginFailed; throw new SpotifyAuthenticatedException(failed); } else if (read > 0) { throw new Exception("Read unknown data!"); } } catch (Exception x) { // ignored } finally { conn.Result.NetworkStream.ReadTimeout = Timeout.Infinite; } using (authLock.Lock()) { sendCipher = new Shannon(); sendCipher.key(Arrays.CopyOfRange(data.ToArray(), 0x14, 0x34)); recvCipher = new Shannon(); recvCipher.key(Arrays.CopyOfRange(data.ToArray(), 0x34, 0x54)); authLockEventWaitHandle.Set(); } #endregion APResponse Debug.WriteLine("Connected successfully"); }
/// <summary> /// ClientHello を待ち受け、ALPN データを取得 /// </summary> /// <param name="stream"></param> /// <param name="protocolNames"></param> /// <returns></returns> public static bool TryGetClientAlpn(this ReadBufferedNetworkStream stream, out IReadOnlyList <string> protocolNames) { // ちゃんと Parse してから処理すれば良いんだけど、ALPN 取りたいだけなので雑…… protocolNames = Array.Empty <string>(); try { var recordIndex = 0; var recordData = new List <byte>(); ClientHello clientHello = null; while (recordData.Count < (clientHello != null ? clientHello.Length + 4 : int.MaxValue)) { stream.FillBuffer(recordIndex + 5); var record = new TlsRecord { ContentType = stream[recordIndex++] }; if (record.ContentType != 0x16) { return(false); // not Handshake Record } record.MajorVersion = stream[recordIndex++]; record.MinorVersion = stream[recordIndex++]; record.Length = stream.ReadBufferUInt16(recordIndex); recordIndex += 2; stream.FillBuffer(recordIndex + record.Length); recordData.AddRange(stream.ReadBufferBytes(recordIndex, record.Length)); if (clientHello == null && 3 <= recordData.Count) { if (recordData[0] != 0x01) { return(false); // not Client Hello } clientHello = new ClientHello { Length = recordData.ToUInt24(1) }; } } clientHello.MajorVersion = recordData[4]; clientHello.MinorVersion = recordData[5]; if (clientHello.MajorVersion != 3 || clientHello.MinorVersion < 1) { return(false); // less than TLS 1.0 (SSL 3.1) } clientHello.SessionIDLength = recordData[38]; clientHello.CipherSuitesLength = recordData.ToUInt16(39 + clientHello.SessionIDLength); clientHello.CompressionMethodsLength = recordData[41 + clientHello.SessionIDLength + clientHello.CipherSuitesLength]; var extensionsStartIndex = 43 + clientHello.SessionIDLength + clientHello.CipherSuitesLength; if (clientHello.Length + 4 <= extensionsStartIndex - 2) { return(false); // no Extensions } clientHello.ExtensionsLength = recordData.ToUInt16(extensionsStartIndex - 2); var extensionsIndex = extensionsStartIndex; while (extensionsIndex < extensionsStartIndex + clientHello.ExtensionsLength) { var type = recordData.ToUInt16(extensionsIndex); extensionsIndex += 2; var length = recordData.ToUInt16(extensionsIndex); extensionsIndex += 2; var data = recordData.Skip(extensionsIndex).Take(length).ToArray(); extensionsIndex += length; if (type != 16) { continue; } var names = new List <string>(); var alpnIndex = 2; // ALPN Extension Length 何のためにあるの…… while (alpnIndex < length) { var nameLength = data[alpnIndex++]; var nameBytes = new byte[nameLength]; Buffer.BlockCopy(data, alpnIndex, nameBytes, 0, nameLength); names.Add(Encoding.ASCII.GetString(nameBytes)); alpnIndex += nameLength; } protocolNames = names.ToArray(); return(true); } } catch { return(false); } return(false); }
private static void ParseClientHello(BytesSegment msg, ref ClientHello ch) { var cur = 0; if (msg[cur] != 1) { throw new Exception("Expected client hello (1), got " + msg[cur]); } cur++; var msgLength = msg[cur] << 16 | msg[cur + 1] << 8 | msg[cur + 2]; cur += 3; msg.SubSelf(4); cur = 0; ch.Version = (ushort)(msg[cur] << 8 | msg[cur + 1]); cur += 2; cur += 32; // skip random cur += 1 + msg[cur]; // skip session_id cur += 2 + (msg[cur] << 8 | msg[cur + 1]); // skip cipher_suites cur += 1 + msg[cur]; // skip compression_methods if (cur >= msgLength) { throw new Exception("extensionsBegin >= msgLength"); } var extensionsLength = msg[cur] << 8 | msg[cur + 1]; cur += 2; var extensionsEnd = cur + extensionsLength; if (extensionsEnd > msgLength) { throw new Exception("extensionsEnd > msgLength"); } while (cur < extensionsEnd) { var extType = (msg[cur] << 8 | msg[cur + 1]); cur += 2; var extLen = (msg[cur] << 8 | msg[cur + 1]); cur += 2; var extEnd = cur + extLen; if (extEnd > extensionsEnd) { throw new Exception("extEnd > extensionsEnd"); } if (extType == 0) // server_name { var nameListLen = (msg[cur] << 8 | msg[cur + 1]); cur += 2; var nameListEnd = cur + nameListLen; if (nameListEnd > extEnd) { throw new Exception("nameListEnd > extEnd"); } var nameList = new List <string>(); if (cur < nameListEnd) // read the first item only { if (msg[cur++] != 0) // name_type: host_name { throw new Exception("Not supported name type " + msg[cur]); } var nameLen = (msg[cur] << 8 | msg[cur + 1]); cur += 2; if (cur + nameLen > nameListEnd) { throw new Exception("nameEnd > nameListEnd"); } var str = NaiveUtils.UTF8Encoding.GetString(msg.Bytes, msg.Offset + cur, nameLen); // TODO: check encoding ch.Sni = str; } } else if (extType == 16) // ALPN { var listLen = (msg[cur] << 8 | msg[cur + 1]); cur += 2; var listEnd = cur + listLen; if (listEnd > extEnd) { throw new Exception("alpnListEnd > extEnd"); } if (cur < listEnd) // read the first item only { var strLen = msg[cur++]; if (cur + strLen > listEnd) { throw new Exception("alpnStrEnd > nameListEnd"); } ch.Alpn = Encoding.ASCII.GetString(msg.Bytes, msg.Offset + cur, strLen); } } else if (extType == 43) // supported_versions { var listLen = msg[cur++]; if (listLen < 2) { throw new Exception("listLen < 2"); } var listEnd = cur + listLen; if (listEnd > extEnd) { throw new Exception("supported_versions listEnd > extEnd"); } while (cur < listEnd) { var ver = (ushort)(msg[cur] << 8 | msg[cur + 1]); cur += 2; if (ver > ch.Version) { ch.Version = ver; } } } cur = extEnd; } return; }
public async Task <ServerHello> GetServerHello(ClientHello clientHello) { var result = await this.sessionService.CreateSession(clientHello); return(result); }
static void Main() { LibTLSClient cSSL; Common cf; Encryption e; Cipher c; ClientHello clientHello; ClientKeyExchange cke; int debug = 0; String request = ""; string[] args = Environment.GetCommandLineArgs(); try { debug = (int)UInt32.Parse(args[4]); if (debug == 1) { Console.WriteLine("Server: {0} Port: {1} Cipher: {2} Debug: {3}", args[1], args[2], args[3], args[4]); } request = args[5]; cf = new Common(debug); e = new Encryption(); cSSL = new LibTLSClient(cf, e); cSSL.cipher = UInt32.Parse(args[3], System.Globalization.NumberStyles.HexNumber); c = new Cipher((ushort)cSSL.cipher); cSSL.cipherObj = c; cSSL.serverIP = args[1]; } catch (Exception ex) { Console.WriteLine("<prog> <ip/fqdn> <port> <cipher hex> <debug [0/1/2]> <a GET request>"); Console.WriteLine("Example: TLSClient.exe 10.209.113.104 443 002f 2 \"GET / HTTP/1.1\""); return; } if (c.Supported() == false) { Console.WriteLine("Cipher Suite not supported currently"); Console.WriteLine("Please try 002f/0035/003c/003d/009c/009d"); return; } cSSL.CreateTCPConn(args[1], Convert.ToInt32(args[2])); cf.HandleResult(cSSL.errorCode, "TCP Connection"); cf.ExitOnError(cSSL.errorCode); cSSL.InitBufs(); List <UInt32> cipher_suites = new List <UInt32>(); cipher_suites.Add(cSSL.cipher); String clientIP = cSSL.GetIPAddress(); String serverIP = cSSL.serverIP; clientHello = new ClientHello(clientIP, serverIP, 3, 3, false, cipher_suites); List <byte> chello_hs = clientHello.Get(); List <byte> crandom = clientHello.GetRandom(); cSSL.StoreClientHelloParams(crandom); cSSL.SendHandshakeMessage(chello_hs, 0x1); cf.ExitOnError(cSSL.errorCode); cSSL.ReceiveHandshakeMessage(); cf.ExitOnError(cSSL.errorCode); cSSL.ParseServerHandshakeMessages(); cf.ExitOnError(cSSL.errorCode); if (cSSL.HasServerKeyExchange()) { cke = new ClientKeyExchange(cf, cSSL.sCert_hs, 3, 3, cSSL.sKeyExch_hs, (String)"ECDHE"); } else { cke = new ClientKeyExchange(cf, cSSL.sCert_hs, 3, 3, null, (String)"RSA"); } List <byte> cke_hs = cke.CreateCKE(); cSSL.StoreCKEParams(cke_hs, cke.GetPremasterSecret(), cke.ecdhCngClient, cke.server_pub_key, cke.client_pub_key); cSSL.SendHandshakeMessage(cke_hs, 0x10); cf.ExitOnError(cSSL.errorCode); cSSL.PrintHandshakeMessages(); cSSL.SendChangeCipherSpec(); cSSL.ComputeMasterSecret(); cSSL.ComputeVerifyData(); cSSL.ComputeKeys(); cSSL.SendClientFinished(); cSSL.ReadServerFinished(); cf.debugPrint(cSSL.ErrorCodeToString(cSSL.errorCode)); if (cSSL.errorCode != 0) { return; } cSSL.SendHTTPSData(request); cSSL.ReadHTTPSData(); cf.debugPrint(cSSL.ErrorCodeToString(cSSL.errorCode)); cSSL.ParseHTTPSData(); byte[] dec = cSSL.DecryptResp(); String dec_s = Encoding.ASCII.GetString(dec, 0, dec.Length); if ((dec_s.IndexOf("HTTP") == 0) && (debug == 0)) { Console.WriteLine("{0} Successful", cSSL.cipherObj.cipher_name); } if ((debug == 2) || (debug == 1)) { Console.WriteLine(dec_s); } }
void ProcessHandshake() { ClientHello clientHello = _recordLayer.Read() as ClientHello; if (clientHello == null) { throw new Exception(); } Console.WriteLine("[TLSServer] Receive ClientHello Version: {0}", clientHello.Version); Console.WriteLine("[TLSServer] CipherSuites"); for (int i = 0; i < clientHello.CipherSuites.Length; i++) { Console.WriteLine(" {0}", clientHello.CipherSuites[i]); } CipherSuite selected = _selector.Select(clientHello.CipherSuites); Console.WriteLine("[TLSServer] CipherSuite Selected. {0}", selected); if (selected == CipherSuite.NONE) { // Alertを送るべき? throw new Exception(); } CipherSuiteInfo selectedInfo = SupportedCipherSuites.GetSuiteInfo(selected); _sparams.SetVersion(clientHello.Version); _sparams.SetCipherSuite(selected, _signAlgo); _sparams.ClientRandom = clientHello.Random; _recordLayer.ProtocolVersion = clientHello.Version; byte[] serverRandom = new byte[RandomData.Size]; Extension[] serverExtensions = null; if (selectedInfo.IsECC) { serverExtensions = new Extension[] { new Extension(ExtensionType.EcPointFormats, new byte[] { 1, 0 }) } } ; RandomData.CreateRandomData(serverRandom, 0); _sparams.ServerRandom = serverRandom; ServerHello serverHello = new ServerHello(clientHello.Version, serverRandom, Utility.EmptyByteArray, selected, CompressionMethod.Null, serverExtensions); _recordLayer.Write(serverHello); Certificate serverCert = new Certificate(_certs); _recordLayer.Write(serverCert); if (Utility.IsNeedServerKeyExchangeMessage(_states.SecurityParameters.KeyExchangeAlgorithm)) { ServerKeyExchange serverExchange = new ServerKeyExchange(_sparams); _recordLayer.Write(serverExchange); } _recordLayer.Write(new ServerHelloDone()); TLSMessage msg = _recordLayer.Read(); ClientKeyExchange clientExchange = (ClientKeyExchange)msg; clientExchange.ComputeServerMasterSecret(_sparams); Console.WriteLine("MasterSecret"); Utility.Dump(_sparams.MasterSecret); _sparams.ComputeKeyBlock(); ChangeCipherSpec changeCipherSpec = (ChangeCipherSpec)_recordLayer.Read(); _recordLayer.EnableReceiveCipher(_sparams.CreateServerDecryptor(), _sparams.CreateClientWriteHMAC()); Finished finished = (Finished)_recordLayer.Read(); Console.WriteLine("VerifyData"); Utility.Dump(finished.VerifyData); Console.WriteLine("Computed VerifyData"); byte[] verifyData = _sparams.ComputeFinishedVerifyData(false); Utility.Dump(verifyData); if (!Utility.Equals(finished.VerifyData, 0, verifyData, 0, verifyData.Length)) { throw new Exception(); } _recordLayer.Write(ChangeCipherSpec.Instance); _recordLayer.EnableSendCipher(_sparams.CreateServerEncryptor(), _sparams.CreateServerWriteHMAC()); _recordLayer.ComputeHandshakeHash(true); verifyData = _sparams.ComputeFinishedVerifyData(true); Console.WriteLine("Finished VerifyData"); Utility.Dump(verifyData); finished = new Finished(_recordLayer.ProtocolVersion, verifyData); _recordLayer.Write(finished); }