private static async Task Client() { // Connect to the server using the named pipe. using (var client = new NamedPipeClientStream(ServerName, PipeName, PipeDirection.InOut)) { await client.ConnectAsync(); // Select the initial Noise protocol and configuration. var initial = Protocol.Parse("Noise_NN_25519_ChaChaPoly_SHA256".AsSpan()); var config = new ProtocolConfig(initiator: true); using (var noise = new NoiseSocket(initial, config, client)) { // Send the initial handshake message to the server. In the real world the // negotiation data would contain the initial protocol, supported protocols // for the switch and retry cases, and maybe some other negotiation options. await noise.WriteHandshakeMessageAsync(negotiationData : null); // Receive the negotiation data from the server. In this example we will // assume that the server decided to retry with Noise_XX_25519_AESGCM_BLAKE2b. await noise.ReadNegotiationDataAsync(); // New protocol requires static key, so it's generated here. using (var keyPair = KeyPair.Generate()) { // The client again plays the role of the initiator. config = new ProtocolConfig(initiator: true, s: keyPair.PrivateKey); // Retry with a protocol different from the initial one. noise.Retry(protocol, config); // Ignore the empty handshake message. await noise.IgnoreHandshakeMessageAsync(); // Finish the handshake using the new protocol. await noise.WriteHandshakeMessageAsync(); await noise.ReadNegotiationDataAsync(); await noise.ReadHandshakeMessageAsync(); await noise.WriteHandshakeMessageAsync(); // Send the transport message to the server. var request = Encoding.UTF8.GetBytes("I'm cooking MC's like a pound of bacon"); await noise.WriteMessageAsync(request); // Receive the transport message from the // server and print it to the standard output. var response = await noise.ReadMessageAsync(); Console.WriteLine(Encoding.UTF8.GetString(response)); } } } }
private static async Task Server() { // Create the named pipe and wait for the client to connect to it. using (var server = new NamedPipeServerStream(PipeName, PipeDirection.InOut)) { await server.WaitForConnectionAsync(); // Initialize the NoiseSocket. using (var noise = new NoiseSocket(server)) { // Receive the negotiation data from the client. In the real world the // negotiation data would contain the initial protocol, supported protocols // for the switch and retry cases, and maybe some other negotiation options. await noise.ReadNegotiationDataAsync(); // Read the handshake message from the client, but without decrypting it. await noise.IgnoreHandshakeMessageAsync(); // New protocol requires static key, so we generate it here. using (var keyPair = KeyPair.Generate()) { // The server decides to retry with a new protocol. // It again plays the role of the responder. var config = new ProtocolConfig(initiator: false, s: keyPair.PrivateKey); noise.Retry(protocol, config); // Request a retry from the client. In the real world the negotiation data // would encode the details about the server's desicion to make a retry request. await noise.WriteEmptyHandshakeMessageAsync(negotiationData : null); // Receive the negotiation data from the client. The client will // usually just confirm the server's choice of the retry protocol. await noise.ReadNegotiationDataAsync(); // Finish the handshake using the new protocol. await noise.ReadHandshakeMessageAsync(); await noise.WriteHandshakeMessageAsync(); await noise.ReadNegotiationDataAsync(); await noise.ReadHandshakeMessageAsync(); // Receive the transport message from the client. var request = await noise.ReadMessageAsync(); // Echo the message back to the client. await noise.WriteMessageAsync(request); } } } }
public async Task TestVectors() { var s = File.ReadAllText("Vectors/noisesocket.json"); var json = JObject.Parse(s); using (var stream = new MemoryStream()) { foreach (var vector in json["vectors"]) { var initialConfig = vector["initial"]; var switchConfig = vector["switch"]; var retryConfig = vector["retry"]; var alicePrologue = GetBytes(vector, "alice_prologue"); var alicePsks = GetPsks(vector, "alice_psks"); var bobPrologue = GetBytes(vector, "bob_prologue"); var bobPsks = GetPsks(vector, "bob_psks"); var handshakeHash = GetBytes(vector, "handshake_hash"); var config = vector["initial"].ToObject <Config>(); var aliceConfig = new ProtocolConfig(true, alicePrologue, config.AliceStatic, config.AliceRemoteStatic, alicePsks); var bobConfig = new ProtocolConfig(false, bobPrologue, config.BobStatic, config.BobRemoteStatic, bobPsks); var protocol = Protocol.Parse(config.ProtocolName.AsSpan()); var queue = ReadMessages(vector["messages"]); var alice = new NoiseSocket(protocol, aliceConfig, stream, true); var bob = new NoiseSocket(protocol, bobConfig, stream, true); var aliceEphemeral = config.AliceEphemeral; var bobEphemeral = config.BobEphemeral; alice.SetInitializer(handshakeState => Utilities.SetDh(handshakeState, aliceEphemeral)); bob.SetInitializer(handshakeState => Utilities.SetDh(handshakeState, bobEphemeral)); var writer = alice; var reader = bob; if (switchConfig == null && retryConfig == null) { var message = queue.Dequeue(); stream.Position = 0; await alice.WriteHandshakeMessageAsync(message.NegotiationData, message.MessageBody, message.PaddedLength); Assert.Equal(message.Value, Utilities.ReadMessage(stream)); stream.Position = 0; Assert.Equal(message.NegotiationData, await bob.ReadNegotiationDataAsync()); bob.Accept(protocol, bobConfig); Assert.Equal(message.MessageBody, await bob.ReadHandshakeMessageAsync()); Utilities.Swap(ref writer, ref reader); } else if (switchConfig != null) { config = switchConfig.ToObject <Config>(); protocol = Protocol.Parse(config.ProtocolName.AsSpan()); aliceConfig = new ProtocolConfig(false, alicePrologue, config.AliceStatic, config.AliceRemoteStatic, alicePsks); bobConfig = new ProtocolConfig(true, bobPrologue, config.BobStatic, config.BobRemoteStatic, bobPsks); var message = queue.Dequeue(); stream.Position = 0; await alice.WriteHandshakeMessageAsync(message.NegotiationData, message.MessageBody, message.PaddedLength); Assert.Equal(message.Value, Utilities.ReadMessage(stream)); stream.Position = 0; Assert.Equal(message.NegotiationData, await bob.ReadNegotiationDataAsync()); if ((protocol.Modifiers & PatternModifiers.Fallback) != 0) { await bob.ReadHandshakeMessageAsync(); bob.Switch(protocol, bobConfig); message = queue.Dequeue(); stream.Position = 0; await bob.WriteHandshakeMessageAsync(message.NegotiationData, message.MessageBody, message.PaddedLength); Assert.Equal(message.Value, Utilities.ReadMessage(stream)); stream.Position = 0; Assert.Equal(message.NegotiationData, await alice.ReadNegotiationDataAsync()); alice.Switch(protocol, aliceConfig); Assert.Equal(message.MessageBody, await alice.ReadHandshakeMessageAsync()); } else { bob.Switch(protocol, bobConfig); bob.SetInitializer(handshakeState => Utilities.SetDh(handshakeState, config.BobEphemeral)); await bob.IgnoreHandshakeMessageAsync(); message = queue.Dequeue(); stream.Position = 0; await bob.WriteHandshakeMessageAsync(message.NegotiationData, message.MessageBody, message.PaddedLength); Assert.Equal(message.Value, Utilities.ReadMessage(stream)); stream.Position = 0; Assert.Equal(message.NegotiationData, await alice.ReadNegotiationDataAsync()); alice.Switch(protocol, aliceConfig); alice.SetInitializer(handshakeState => Utilities.SetDh(handshakeState, config.AliceEphemeral)); Assert.Equal(message.MessageBody, await alice.ReadHandshakeMessageAsync()); } } else if (retryConfig != null) { config = retryConfig.ToObject <Config>(); protocol = Protocol.Parse(config.ProtocolName.AsSpan()); aliceConfig = new ProtocolConfig(true, alicePrologue, config.AliceStatic, config.AliceRemoteStatic, alicePsks); bobConfig = new ProtocolConfig(false, bobPrologue, config.BobStatic, config.BobRemoteStatic, bobPsks); var message = queue.Dequeue(); stream.Position = 0; await alice.WriteHandshakeMessageAsync(message.NegotiationData, message.MessageBody, message.PaddedLength); Assert.Equal(message.Value, Utilities.ReadMessage(stream)); stream.Position = 0; Assert.Equal(message.NegotiationData, await bob.ReadNegotiationDataAsync()); bob.Retry(protocol, bobConfig); bob.SetInitializer(handshakeState => Utilities.SetDh(handshakeState, config.BobEphemeral)); await bob.IgnoreHandshakeMessageAsync(); message = queue.Dequeue(); stream.Position = 0; await bob.WriteEmptyHandshakeMessageAsync(message.NegotiationData); Assert.Equal(message.Value, Utilities.ReadMessage(stream)); stream.Position = 0; Assert.Equal(message.NegotiationData, await alice.ReadNegotiationDataAsync()); alice.Retry(protocol, aliceConfig); alice.SetInitializer(handshakeState => Utilities.SetDh(handshakeState, config.AliceEphemeral)); await alice.IgnoreHandshakeMessageAsync(); } while (queue.Count > 0) { var message = queue.Dequeue(); if (writer.HandshakeHash.IsEmpty) { stream.Position = 0; await writer.WriteHandshakeMessageAsync(message.NegotiationData, message.MessageBody, message.PaddedLength); Assert.Equal(message.Value, Utilities.ReadMessage(stream)); stream.Position = 0; Assert.Empty(await reader.ReadNegotiationDataAsync()); Assert.Equal(message.MessageBody, await reader.ReadHandshakeMessageAsync()); } else { stream.Position = 0; await writer.WriteMessageAsync(message.MessageBody, message.PaddedLength); Assert.Equal(message.Value, Utilities.ReadMessage(stream)); stream.Position = 0; Assert.Equal(message.MessageBody, await reader.ReadMessageAsync()); } Utilities.Swap(ref writer, ref reader); } Assert.Equal(handshakeHash, writer.HandshakeHash.ToArray()); Assert.Equal(handshakeHash, reader.HandshakeHash.ToArray()); alice.Dispose(); bob.Dispose(); } } }
public static async Task <IEnumerable <Vector> > Generate() { var vectors = new List <Vector>(); using (var stream = new MemoryStream()) { foreach (var test in GetTests()) { var aliceConfig = new ProtocolConfig( initiator: true, prologue: PrologueRaw, s: test.InitStaticRequired ? AliceStaticRaw : null, rs: test.InitRemoteStaticRequired ? BobStaticPublicRaw : null, psks: test.PsksRequired ? psksRaw : null ); var bobConfig = new ProtocolConfig( initiator: false, prologue: PrologueRaw, s: test.RespStaticRequired ? BobStaticRaw : null, rs: test.RespRemoteStaticRequired ? AliceStaticPublicRaw : null, psks: test.PsksRequired ? psksRaw : null ); var alice = new NoiseSocket(test.Protocol, aliceConfig, stream, true); var bob = new NoiseSocket(test.Protocol, bobConfig, stream, true); alice.SetInitializer(handshakeState => Utilities.SetDh(handshakeState, AliceEphemeralRaw.ToArray())); bob.SetInitializer(handshakeState => Utilities.SetDh(handshakeState, BobEphemeralRaw.ToArray())); var proxy = new SocketProxy(stream, (ushort)test.PaddedLength); var queue = new Queue <byte[]>(payloads); var writer = alice; var reader = bob; if (test.Response == Response.Accept) { await proxy.WriteHandshakeMessageAsync(alice, InitialNegotiationData, queue.Dequeue()); await bob.ReadNegotiationDataAsync(); bob.Accept(test.Protocol, bobConfig); await bob.ReadHandshakeMessageAsync(); stream.Position = 0; Utilities.Swap(ref writer, ref reader); } else if (test.Response == Response.Switch) { await proxy.WriteHandshakeMessageAsync(alice, InitialNegotiationData, queue.Dequeue()); await bob.ReadNegotiationDataAsync(); if (test.Fallback != null) { await bob.ReadHandshakeMessageAsync(); stream.Position = 0; bob.Switch(test.Fallback, new ProtocolConfig(true, PrologueRaw, BobStaticRaw)); await proxy.WriteHandshakeMessageAsync(bob, SwitchNegotiationData, queue.Dequeue()); await alice.ReadNegotiationDataAsync(); alice.Switch(test.Fallback, new ProtocolConfig(false, PrologueRaw, AliceStaticRaw)); await alice.ReadHandshakeMessageAsync(); stream.Position = 0; } else { bob.Switch(test.Protocol, aliceConfig); bob.SetInitializer(handshakeState => Utilities.SetDh(handshakeState, AliceEphemeralRaw.ToArray())); await bob.IgnoreHandshakeMessageAsync(); stream.Position = 0; await proxy.WriteHandshakeMessageAsync(bob, SwitchNegotiationData, queue.Dequeue()); await alice.ReadNegotiationDataAsync(); alice.Switch(test.Protocol, bobConfig); alice.SetInitializer(handshakeState => Utilities.SetDh(handshakeState, BobEphemeralRaw.ToArray())); await alice.ReadHandshakeMessageAsync(); stream.Position = 0; } } else if (test.Response == Response.Retry) { await proxy.WriteHandshakeMessageAsync(alice, InitialNegotiationData, queue.Dequeue()); await bob.ReadNegotiationDataAsync(); bob.Retry(test.Protocol, bobConfig); await bob.IgnoreHandshakeMessageAsync(); stream.Position = 0; await proxy.WriteEmptyHandshakeMessageAsync(bob, RetryNegotiationData); await alice.ReadNegotiationDataAsync(); alice.Retry(test.Protocol, aliceConfig); await alice.IgnoreHandshakeMessageAsync(); stream.Position = 0; } while (queue.Count > 0) { if (writer.HandshakeHash.IsEmpty) { await proxy.WriteHandshakeMessageAsync(writer, null, queue.Dequeue()); await reader.ReadNegotiationDataAsync(); await reader.ReadHandshakeMessageAsync(); stream.Position = 0; } else { await proxy.WriteMessageAsync(writer, queue.Dequeue()); } Utilities.Swap(ref writer, ref reader); } var initialConfig = new Config { ProtocolName = Encoding.ASCII.GetString(test.Protocol.Name), AliceStatic = aliceConfig.LocalStatic, AliceEphemeral = AliceEphemeralRaw, AliceRemoteStatic = aliceConfig.RemoteStatic, BobStatic = bobConfig.LocalStatic, BobEphemeral = BobEphemeralRaw, BobRemoteStatic = bobConfig.RemoteStatic }; var switchConfig = new Config { ProtocolName = Encoding.ASCII.GetString(test.Protocol.Name), AliceStatic = bobConfig.LocalStatic, AliceEphemeral = BobEphemeralRaw, AliceRemoteStatic = bobConfig.RemoteStatic, BobStatic = aliceConfig.LocalStatic, BobEphemeral = AliceEphemeralRaw, BobRemoteStatic = aliceConfig.RemoteStatic }; if (test.Fallback != null) { switchConfig = new Config { ProtocolName = Encoding.ASCII.GetString(test.Fallback.Name), AliceStatic = AliceStaticRaw, AliceEphemeral = AliceEphemeralRaw, BobStatic = BobStaticRaw, BobEphemeral = BobEphemeralRaw }; } var vector = new Vector { Initial = initialConfig, Switch = test.Response == Response.Switch ? switchConfig : null, Retry = test.Response == Response.Retry ? initialConfig : null, AlicePrologue = PrologueHex, AlicePsks = test.PsksRequired ? psksHex : null, BobPrologue = PrologueHex, BobPsks = test.PsksRequired ? psksHex : null, HandshakeHash = Hex.Encode(writer.HandshakeHash.ToArray()), Messages = proxy.Messages }; alice.Dispose(); bob.Dispose(); vectors.Add(vector); } } return(vectors); }