/// <summary> /// Generate a handshake packet for the current keys /// </summary> public Packet Handshake(byte csid, bool isReply = false) { Packet inner = new Packet (); Packet keyPacket = new Packet (); foreach (var csItem in Local.CipherSets) { if (csItem.Value.CSID == csid) { keyPacket.Body = csItem.Value.Keys.PublicKey; } else { keyPacket.Head.Add (csItem.Value.CSID.ToString (), Base32Encoder.Encode (csItem.Value.Keys.PublicKey)); } } if (isReply) { inner.Head.Add ("at", OutAt); } else { inner.Head.Add ("at", NextAt()); } inner.Head.Add ("csid", csid.ToString ("x2")); keyPacket.Encode (); inner.Body = keyPacket.FullPacket; inner.Encode (); Packet outer = Local.CipherSets[csid].MessageEncrypt(remoteInfo, inner); outer.HeadBytes = new byte[1]; outer.HeadLength = 1; outer.HeadBytes [0] = csid; outer.Encode (); return outer; }
public static Packet DecodePacket(byte[] packetData) { Packet pkt = new Packet(); if (!pkt.Decode(packetData)) { return null; } return pkt; }
/// <summary> /// Attempt to Decrypt a packet sent to us. /// </summary> /// <param name="outer">A packet to attempt to decrypt</param> public Packet Decrypt(Packet outer) { ICipherSet cs; if (CipherSets.TryGetValue (outer.HeadBytes [0], out cs)) { return cs.MessageDecrypt (outer); } return null; }
public Packet MessageEncrypt(ICipherSetRemoteInfo remoteInfo, Packet inner) { CS1ARemoteInfo ri = (CS1ARemoteInfo)remoteInfo; var agreedValue = ECDHAgree (ri.RemotePublicKey, ri.EphemeralKeys.PrivateKey); // Hash the agreed key var hashedValue = Helpers.SHA256Hash (Helpers.ToByteArray(agreedValue, 20)); // Fold to get the actual key for AES byte[] aesKey = Helpers.Fold (hashedValue); Random rnd = new Random (); // Setup and encrypt the actual data byte[] aesIV = new byte[16]; rnd.NextBytes (aesIV); Array.Clear (aesIV, 4, 12); var cipher = new SicBlockCipher (new AesFastEngine ()); var parameters = new ParametersWithIV (new KeyParameter (aesKey), aesIV); cipher.Init (true, parameters); var encryptedInner = new byte[inner.FullPacket.Length]; BufferedBlockCipher bufferCipher = new BufferedBlockCipher (cipher); var offset = bufferCipher.ProcessBytes (inner.FullPacket, encryptedInner, 0); bufferCipher.DoFinal (encryptedInner, offset); // Construct the packet minus the hmac Packet outPacket = new Packet (); outPacket.Body = new byte[29 + encryptedInner.Length]; Buffer.BlockCopy (ri.EphemeralKeys.PublicKey, 0, outPacket.Body, 0, ri.EphemeralKeys.PublicKey.Length); Buffer.BlockCopy (aesIV, 0, outPacket.Body, 21, 4); Buffer.BlockCopy (encryptedInner, 0, outPacket.Body, 25, encryptedInner.Length); // ECDH for the hmac key using var idAgreedValue = ECDHAgree (ri.RemotePublicKey, Key.PrivateKey); // Mash on the IV for the compound key byte[] macKey = new byte[24]; byte[] idAgreedValueArray = Helpers.ToByteArray(idAgreedValue, 20); Buffer.BlockCopy(idAgreedValueArray, 0, macKey, 0, idAgreedValueArray.Length); Buffer.BlockCopy(aesIV, 0, macKey, idAgreedValueArray.Length, 4); // Actually hmac all the data now var hmac = new HMac (new Sha256Digest ()); hmac.Init(new KeyParameter (macKey, 0, 24)); hmac.BlockUpdate(outPacket.Body, 0, 25 + encryptedInner.Length); byte[] mac = new byte[hmac.GetMacSize()]; hmac.DoFinal(mac, 0); // Fold it up, shove it in and we're done var foldedMac = Helpers.Fold(mac, 3); Buffer.BlockCopy(foldedMac, 0, outPacket.Body, 25 + encryptedInner.Length, foldedMac.Length); return outPacket; }
public bool Handshake(Packet outer) { var linkData = Packet.DecodePacket (outer.Body); if (Exchange == null) { Exchange = new Exchange (Mesh.Self, 0x1a, linkData.Body); Exchange.OutAt = (uint)outer.Head ["at"]; var tokenData = outer.Parent.Body.Take (16).ToArray (); var tokenHash = Helpers.SHA256Hash (tokenData).Take (16).ToArray (); Token = Helpers.ToHexSring (tokenHash); } if (!Exchange.Verify (outer.Parent)) { return false; } Exchange.Sync (outer); return true; }
public void Packet() { // Basic packet decoding byte[] packetData = StringToByteArray ("001d7b2274797065223a2274657374222c22666f6f223a5b22626172225d7d616e792062696e61727921"); Telehash.E3X.Packet p = new Telehash.E3X.Packet (packetData); Assert.AreEqual (p.HeadLength, 29); Assert.AreEqual (p.Body.Length, 11); Assert.AreEqual ((string)p.Head ["type"], "test"); Assert.AreEqual ((string)p.Head ["foo"] [0], "bar"); Telehash.E3X.Packet encodeTestPacket = new Telehash.E3X.Packet (); encodeTestPacket.Body = p.Body; encodeTestPacket.Head.Add ("type", "test"); var fooArray = new JArray (); fooArray.Add ("bar"); encodeTestPacket.Head.Add ("foo", fooArray); encodeTestPacket.Encode (); Assert.AreEqual (packetData, encodeTestPacket.FullPacket); }
public void Packet() { // Basic packet decoding byte[] packetData = StringToByteArray("001d7b2274797065223a2274657374222c22666f6f223a5b22626172225d7d616e792062696e61727921"); Telehash.E3X.Packet p = new Telehash.E3X.Packet(packetData); Assert.AreEqual(p.HeadLength, 29); Assert.AreEqual(p.Body.Length, 11); Assert.AreEqual((string)p.Head ["type"], "test"); Assert.AreEqual((string)p.Head ["foo"] [0], "bar"); Telehash.E3X.Packet encodeTestPacket = new Telehash.E3X.Packet(); encodeTestPacket.Body = p.Body; encodeTestPacket.Head.Add("type", "test"); var fooArray = new JArray(); fooArray.Add("bar"); encodeTestPacket.Head.Add("foo", fooArray); encodeTestPacket.Encode(); Assert.AreEqual(packetData, encodeTestPacket.FullPacket); }
public void Prepare(ICipherSetRemoteInfo info, Packet outer) { var ri = (CS1ARemoteInfo)info; ri.RemoteEphemeralKey = new byte[21]; Buffer.BlockCopy (outer.Parent.Body, 0, ri.RemoteEphemeralKey, 0, 21); var secret = Helpers.ToByteArray(ECDHAgree (ri.RemoteEphemeralKey, ri.EphemeralKeys.PrivateKey), 20); var shaBuffer = new byte[secret.Length + ri.RemoteEphemeralKey.Length + ri.EphemeralKeys.PublicKey.Length]; Buffer.BlockCopy (secret, 0, shaBuffer, 0, secret.Length); Buffer.BlockCopy (ri.RemoteEphemeralKey, 0, shaBuffer, secret.Length, ri.RemoteEphemeralKey.Length); Buffer.BlockCopy (ri.EphemeralKeys.PublicKey, 0, shaBuffer, secret.Length + ri.RemoteEphemeralKey.Length, ri.EphemeralKeys.PublicKey.Length); ri.DecryptionKey = Helpers.FoldOnce (Helpers.SHA256Hash (shaBuffer)); Buffer.BlockCopy (ri.EphemeralKeys.PublicKey, 0, shaBuffer, secret.Length, ri.EphemeralKeys.PublicKey.Length); Buffer.BlockCopy (ri.RemoteEphemeralKey, 0, shaBuffer, secret.Length + ri.EphemeralKeys.PublicKey.Length, ri.RemoteEphemeralKey.Length); ri.EncryptionKey = Helpers.FoldOnce (Helpers.SHA256Hash (shaBuffer)); var rnd = new SecureRandom (); ri.IV = (uint)rnd.NextInt (); }
public Packet ChannelDecrypt(ICipherSetRemoteInfo channelInfo, Packet outer) { // We gotta have the primary components and something to decrypt if (outer.Body.Length < 25) { return null; } var ci = (CS1ARemoteInfo)channelInfo; // Rip apart our packet byte[] token = outer.Body.Take (16).ToArray (); byte[] iv = outer.Body.Skip (16).Take (4).ToArray (); byte[] encryptedData = outer.Body.Skip (20).Take (outer.Body.Length - 24).ToArray (); byte[] dataMac = outer.Body.Skip (outer.Body.Length - 4).Take (4).ToArray (); // Make sure we're on the right channel if (!token.SequenceEqual (ci.Token)) { return null; } // Validate us some hmac byte[] hmacKey = new byte[20]; Buffer.BlockCopy (ci.DecryptionKey, 0, hmacKey, 0, 16); Buffer.BlockCopy (iv, 0, hmacKey, 16, 4); var hmac = new HMac (new Sha256Digest ()); hmac.Init(new KeyParameter (hmacKey)); hmac.BlockUpdate(encryptedData, 0, encryptedData.Length); byte[] mac = new byte[hmac.GetMacSize()]; hmac.DoFinal(mac, 0); var foldedMac = Helpers.Fold (mac, 3); if (!foldedMac.SequenceEqual (dataMac)) { // Get out of here with your bad data return null; } // Everything seems ok. Get it decrypted byte[] aesIV = new byte[16]; Buffer.BlockCopy (iv, 0, aesIV, 0, 4); Array.Clear (aesIV, 4, 12); var cipher = new SicBlockCipher (new AesFastEngine ()); var parameters = new ParametersWithIV (new KeyParameter (ci.DecryptionKey), aesIV); cipher.Init (false, parameters); var decryptedData = new byte[encryptedData.Length]; BufferedBlockCipher bufferCipher = new BufferedBlockCipher (cipher); var offset = bufferCipher.ProcessBytes (encryptedData, decryptedData, 0); bufferCipher.DoFinal (decryptedData, offset); // Build a packet and ship it off return Packet.DecodePacket (decryptedData); }
public Packet ChannelEncrypt(ICipherSetRemoteInfo channelInfo, Packet inner) { var ci = (CS1ARemoteInfo)channelInfo; // TODO: Validate we don't care about endianess of IV here // Setup and encrypt the actual data byte[] aesIV = new byte[16]; Buffer.BlockCopy (BitConverter.GetBytes(ci.IV), 0, aesIV, 0, 4); Array.Clear (aesIV, 4, 12); var cipher = new SicBlockCipher (new AesFastEngine ()); var parameters = new ParametersWithIV (new KeyParameter (ci.EncryptionKey), aesIV); cipher.Init (true, parameters); var encryptedInner = new byte[inner.FullPacket.Length]; BufferedBlockCipher bufferCipher = new BufferedBlockCipher (cipher); var offset = bufferCipher.ProcessBytes (inner.FullPacket, encryptedInner, 0); bufferCipher.DoFinal (encryptedInner, offset); // Hmac the output byte[] hmacKey = new byte[20]; Buffer.BlockCopy (ci.EncryptionKey, 0, hmacKey, 0, 16); Buffer.BlockCopy (BitConverter.GetBytes(ci.IV), 0, hmacKey, 16, 4); var hmac = new HMac (new Sha256Digest ()); hmac.Init(new KeyParameter (hmacKey)); hmac.BlockUpdate(encryptedInner, 0, encryptedInner.Length); byte[] mac = new byte[hmac.GetMacSize()]; hmac.DoFinal(mac, 0); var foldedMac = Helpers.Fold (mac, 3); // Create the outgoing packet Packet outPacket = new Packet(); outPacket.Body = new byte[encryptedInner.Length + 24]; Buffer.BlockCopy(ci.Token, 0, outPacket.Body, 0, 16); Buffer.BlockCopy(BitConverter.GetBytes(ci.IV), 0, outPacket.Body, 16, 4); Buffer.BlockCopy(encryptedInner, 0, outPacket.Body, 20, encryptedInner.Length); Buffer.BlockCopy(foldedMac, 0, outPacket.Body, outPacket.Body.Length - 4, 4); // Next IV next packet ++ci.IV; return outPacket; }
public bool MessageVerify (ICipherSetRemoteInfo remoteInfo, Packet outer) { CS1ARemoteInfo ri = (CS1ARemoteInfo)remoteInfo; byte[] ivData = outer.Body.Skip(21).Take(4).ToArray(); byte[] hmacData = outer.Body.Skip(outer.Body.Length - 4).Take(4).ToArray(); // Check the hmac to validate the packet var agreedHMacKeyData = Helpers.ToByteArray (ECDHAgree (ri.RemotePublicKey, Key.PrivateKey), 20); byte[] hmacKey = new byte[24]; if (agreedHMacKeyData.Length != 20) { // It's not a correct agreed value, expected 20 bytes return false; } Buffer.BlockCopy (agreedHMacKeyData, 0, hmacKey, 0, 20); Buffer.BlockCopy (ivData, 0, hmacKey, 20, 4); var hmac = new HMac (new Sha256Digest ()); byte[] fullIv = new byte[16]; Array.Clear (fullIv, 0, 16); Buffer.BlockCopy (ivData, 0, fullIv, 0, 4); hmac.Init(new KeyParameter (hmacKey, 0, 24)); hmac.BlockUpdate(outer.Body, 0, outer.Body.Length - 4); byte[] mac = new byte[hmac.GetMacSize()]; hmac.DoFinal(mac, 0); var macValue = Helpers.Fold (mac, 3); if (!macValue.SequenceEqual (hmacData)) { // The hmacs did not match, blow up the world return false; } return true; }
public void Encrypt(Packet msg) { }
public void Receive(Pipe pipe, Packet packet) { if (pipe == null || packet == null || packet.FullPacket.Length == 0) { DebugLog ("Invalid data sent to Receive"); return; } DebugLog ("Received a packet: " + packet.ToDebugString()); DebugLog ("Head length: " + packet.HeadLength + "\n"); // Process handshakes if (packet.HeadLength == 1) { DebugLog ("Processing a handshake"); var inner = self.Decrypt (packet); if (inner == null) { DebugLog ("There was no inner packet\n"); return; } inner.Parent = packet; DebugLog ("Decrypted"); DebugLog (inner.ToDebugString ()); DebugLog ("HERE"); JToken msgType; bool gotValue = inner.Head.TryGetValue ("type", out msgType); // TODO: Handle other types correctly if (gotValue && msgType.ToString () != "link") { DebugLog ("We can only handle key type messages right now\n"); return; } DebugLog ("Building hashname"); // Get the hashname from the inner packet var keyPacket = Packet.DecodePacket (inner.Body); if (keyPacket == null) { DebugLog ("No key packet was in the handshake"); return; } var hashKeys = new Dictionary<string, string> (); foreach (var entry in keyPacket.Head) { // TODO: Move to the new inner packet syntax hashKeys.Add (entry.Key, entry.Value.ToString ()); } var fromHashname = Telehash.Hashname.FromKey ("1a", keyPacket.Body, hashKeys); DebugLog ("Incoming hashname: " + fromHashname); Link curLink; if (Links.TryGetValue (fromHashname, out curLink)) { // TODO: Replace an existing link JToken atToken; if (!inner.Head.TryGetValue ("at", out atToken)) { DebugLog ("No at value was found on handshake"); return; } if (curLink.Exchange.At == atToken.Value<uint> ()) { if (!curLink.Handshake (inner)) { DebugLog ("Could not finish handshake"); return; } if (LinkUp != null) { LinkUp (curLink); } DebugLog ("Start using channels?"); } return; } else { // TODO: Method to approve or reject the hashname? Link newLink = new Link (fromHashname); newLink.Mesh = this; if (!newLink.Handshake (inner)) { DebugLog ("Invalid Handshake for Link"); return; } newLink.AddPipe (pipe); // We index both the hashname and the Token for different lookup cases Links.Add (fromHashname, newLink); DebugLog ("Token for new Link is " + Helpers.ToHexSring(newLink.Exchange.Token)); Links.Add (Helpers.ToHexSring(newLink.Exchange.Token), newLink); if (LinkUp != null) { LinkUp (newLink); } } } else if (packet.HeadLength == 0) { byte[] token = packet.Body.Take(16).ToArray(); Link link; if (Links.TryGetValue (Helpers.ToHexSring (token), out link)) { var outer = link.Exchange.Receive (packet); if (outer == null) { DebugLog ("Unable to decrypt a packet"); // TODO: Do we shutdown the link or exchange? Probably not, DoS } DebugLog ("We got a channel packet: " + outer.ToDebugString ()); link.Receive (outer, pipe); } else { DebugLog ("No known link for channel packet token: " + Helpers.ToHexSring (token)); return; } } DebugLog ("We're out\n"); }
public Packet Receive(Packet packet) { return cipherSet.ChannelDecrypt(remoteInfo, packet); }
public void Sync(Packet handshake) { cipherSet.Prepare (remoteInfo, handshake); }
public void Receive(Packet packet, Pipe pipe) { }
public void Send (Packet packet) { var sendData = packet.Cloak (); Client.Send (sendData, sendData.Length, remoteEndpoint); }
public Packet MessageDecrypt(Packet outer) { byte[] remoteKeyData = outer.Body.Take(21).ToArray(); byte[] ivData = outer.Body.Skip(21).Take(4).ToArray(); byte[] innerEncryptedData = outer.Body.Skip(25).Take(outer.Body.Length - 29).ToArray(); // Decode the body ECKeyPair remoteEphemeralKeys = ECKeyPair.LoadKeys (SecNamedCurves.GetByName ("secp160r1"), remoteKeyData, null); var idAgreement = ECDHAgree (remoteEphemeralKeys.PublicKey, Key.PrivateKey); var agreedHash = Helpers.SHA256Hash (Helpers.ToByteArray (idAgreement, 20)); var aesKey = Helpers.FoldOnce(agreedHash); // Pad out the IV byte[] aesIV = new byte[16]; Array.Clear (aesIV, 0, 16); Buffer.BlockCopy (ivData, 0, aesIV, 0, 4); // Decrypt it var cipher = new BufferedBlockCipher (new SicBlockCipher (new AesFastEngine ())); var parameters = new ParametersWithIV (new KeyParameter (aesKey), aesIV); cipher.Init (false, parameters); byte[] decryptedBody = new byte[innerEncryptedData.Length]; var offset = cipher.ProcessBytes (innerEncryptedData, decryptedBody, 0); cipher.DoFinal (decryptedBody, offset); Packet outPacket = Packet.DecodePacket (decryptedBody); return outPacket; }
public bool Verify(Packet msg) { return cipherSet.MessageVerify (remoteInfo, msg); }