private void HandleMessageReceive(ChannelMessage message) { SimpleMessage simpleMessage = new SimpleMessage(message); if (ShowTransportPackets) { CConsole.Gray("{0}", JsonConvert.SerializeObject(simpleMessage, Formatting.Indented)); } if (message.CipherText == null) { // It's not a message packet if (message.AnnouncedKey != null && message.AcknowledgeKey == null) { // BOB // Initial announce from other side if (PlaintextMode != message.PlaintextMode) { CConsole.Red("!!! Invalid Far-side configuration! Near-Side PlaintextMode = {0}, Far-Side PlaintextMode = {1}", PlaintextMode, message.PlaintextMode); IsOpen = false; MessageEvent.Set(); return; //throw new Exception("PlaintextMode Mismatch"); } Parameters = new DHParameters( new BigInteger(message.Param_P, 16), new BigInteger(message.Param_G, 16), new BigInteger(message.Param_Q, 16), message.Param_L); RachetKeyPair = DHKeyPair.Generate(Parameters); if (Verbose) { CConsole.Yellow("RootChainKey = {0}", H(RachetKeyPair.ComputeSharedSecret(message.AnnouncedKey))); } LastParterAnnouncedKey = message.AnnouncedKey; IsOpen = true; MessageEvent.Set(); } else if (message.AnnouncedKey != null && message.AcknowledgeKey != null) { // ALICE // Initial acknowledge from other side if (Verbose) { CConsole.DarkMagenta("Acknowledging = {0}", message.AnnouncedKey); } LastParterAnnouncedKey = message.AnnouncedKey; if (message.AcknowledgeKey != RachetKeyPair.PublicKey) { CConsole.Red("!!! Invalid AcknowledgedKey !!!"); throw new Exception("Invalid AcknowledgedKey"); } else { string secretA = RachetKeyPair.ComputeSharedSecret(message.AnnouncedKey); //FIRST RootChainKey if (PrefilledRootKey != null) { RootChainKey = PrefilledRootKey; string outputA; string outputB; KDF(RootChainKey, RootChainKey, out outputA, out outputB); RootChainKey = outputA; } else { RootChainKey = secretA; } if (Verbose) { CConsole.Yellow("RootChainKey = {0}", H(RootChainKey)); } string outputA1; string outputB1; KDF(RootChainKey, RootChainKey, out outputA1, out outputB1); RootChainKey = outputA1; ReceivingChainKey = outputB1; if (Verbose) { CConsole.DarkYellow("RootChainKey = {0}", H(RootChainKey)); } if (Verbose) { CConsole.Magenta("ReceivingChainKey = {0}", H(ReceivingChainKey)); } string outputA2; string outputB2; RachetKeyPair = DHKeyPair.Generate(Parameters); if (Verbose) { if (RootChainCount % 2 == 1) { CConsole.DarkMagenta("Announcing = {0}", H(RachetKeyPair.PublicKey)); } else { CConsole.DarkCyan("Announcing = {0}", H(RachetKeyPair.PublicKey)); } } string secret = RachetKeyPair.ComputeSharedSecret(message.AnnouncedKey); KDF(secret, RootChainKey, out outputA2, out outputB2); RootChainKey = outputA2; SendingChainKey = outputB2; if (Verbose) { CConsole.Yellow("RootChainKey = {0}", H(RootChainKey)); } } IsOpen = true; MessageEvent.Set(); } } else { // It's a message packet! Do the decrypt string text; if (!Decrypt(message, out text)) { throw new Exception("Failed to Decrypt packet!"); } OnMessage(text); MessageListener?.Invoke(text); } }
private bool Decrypt(ChannelMessage message, out string text) { if (PlaintextMode && message.PlaintextMode) { text = message.CipherText; return(true); } if (DHRachetNeeded(message.AnnouncedKey, message.AcknowledgeKey)) { string secretA = RachetKeyPair.ComputeSharedSecret(message.AnnouncedKey); string outputA1; string outputB1; KDF(secretA, RootChainKey, out outputA1, out outputB1); RootChainKey = outputA1; ReceivingChainKey = outputB1; if (Verbose) { if (RootChainCount % 2 == 1) { CConsole.Yellow("RootChainKey = {0}", H(RootChainKey)); } else { CConsole.DarkYellow("RootChainKey = {0}", H(RootChainKey)); } } if (Verbose) { if (RootChainCount % 2 == 1) { CConsole.Blue("ReceivingChainKey = {0}", H(ReceivingChainKey)); } else { CConsole.Magenta("ReceivingChainKey = {0}", H(ReceivingChainKey)); } } string messageKey; string outputA; string outputB; KDF(ReceivingChainKey, ReceivingChainKey, out outputA, out outputB); messageKey = outputA; ReceivingChainKey = outputB; if (Verbose) { if (RootChainCount % 2 == 1) { CConsole.Magenta("ReceivingChainKey = {0}", H(ReceivingChainKey)); } else { CConsole.Blue("ReceivingChainKey = {0}", H(ReceivingChainKey)); } } if (Verbose) { CConsole.DarkGreen("MessageKey = {0}", H(messageKey)); } text = DES.DecryptB64(message.CipherText, messageKey); RachetKeyPair = DHKeyPair.Generate(RachetKeyPair.Parameters); if (Verbose) { if (RootChainCount % 2 == 1) { CConsole.DarkMagenta("Announcing = {0}", H(RachetKeyPair.PublicKey)); } else { CConsole.DarkCyan("Announcing = {0}", H(RachetKeyPair.PublicKey)); } } string secretB = RachetKeyPair.ComputeSharedSecret(message.AnnouncedKey); string outputA2; string outputB2; KDF(secretB, RootChainKey, out outputA2, out outputB2); RootChainKey = outputA2; SendingChainKey = outputB2; if (Verbose) { if (RootChainCount % 2 == 1) { CConsole.Yellow("RootChainKey = {0}", H(RootChainKey)); } else { CConsole.DarkYellow("RootChainKey = {0}", H(RootChainKey)); } } ReceivingMessageId++; return(true); } else { if (Verbose) { CConsole.Red("ReceivingChainKey = {0}", H(ReceivingChainKey)); } string messageKey; string outputA; string outputB; KDF(ReceivingChainKey, ReceivingChainKey, out outputA, out outputB); messageKey = outputA; ReceivingChainKey = outputB; if (Verbose) { CConsole.DarkGreen("MessageKey = {0}", H(messageKey)); } text = DES.DecryptB64(message.CipherText, messageKey); ReceivingMessageId++; return(true); } }
public bool Open(bool sender) { if (!sender) { // BOB MessageEvent.WaitOne(30 * 1000); // Wait until fully opened or timeout in 30s if (IsOpen == false) { return(false); } // Send acknowledge if (Verbose) { CConsole.DarkCyan("Acknowledging = {0}", LastParterAnnouncedKey); } if (Verbose) { CConsole.DarkMagenta("Announcing = {0}", RachetKeyPair.PublicKey); } string secret = RachetKeyPair.ComputeSharedSecret(LastParterAnnouncedKey); if (PrefilledRootKey != null) { RootChainKey = PrefilledRootKey; string outputA1; string outputB1; KDF(RootChainKey, RootChainKey, out outputA1, out outputB1); RootChainKey = outputA1; } else { RootChainKey = secret; } string outputA; string outputB; KDF(RootChainKey, RootChainKey, out outputA, out outputB); RootChainKey = outputA; SendingChainKey = outputB; if (Verbose) { CConsole.DarkYellow("RootChainKey = {0}", H(RootChainKey)); } if (Verbose) { CConsole.Magenta("SendingChainKey = {0}", H(SendingChainKey)); } ChannelMessage msg = new ChannelMessage() { AcknowledgeKey = LastParterAnnouncedKey, AnnouncedKey = RachetKeyPair.PublicKey, CipherText = null }; if (!SerializeAndSend(msg)) { CConsole.Red("!!! Error sending initial announce !!!"); } } else { // ALICE // Send announce RachetKeyPair = DHKeyPair.Generate(); Parameters = RachetKeyPair.Parameters; ChannelMessage msg = new ChannelMessage() { AcknowledgeKey = null, AnnouncedKey = RachetKeyPair.PublicKey, Param_P = RachetKeyPair.Parameters.P.ToString(16), Param_G = RachetKeyPair.Parameters.G.ToString(16), Param_Q = RachetKeyPair.Parameters.Q.ToString(16), Param_L = RachetKeyPair.Parameters.L, CipherText = null, PlaintextMode = PlaintextMode }; if (Verbose) { CConsole.DarkCyan("Announcing = {0}", RachetKeyPair.PublicKey); } if (!SerializeAndSend(msg)) { CConsole.Red("!!! Error sending initial announce !!!"); } MessageEvent.WaitOne(30 * 1000); // wait till fully opened or timeout in 30s if (IsOpen == false) { return(false); } } return(true); }