public Exchange(Self localIdentity, byte csid, byte[] publicKey) { Local = localIdentity; cipherSet = localIdentity.CipherSets [csid]; var ri = new CS1ARemoteInfo(); ri.RemotePublicKey = publicKey; cipherSet.GenerateEphemeralKeys(ri); remoteInfo = ri; var idKey = localIdentity.CipherSets [csid].Keys.PublicKey; for (int i = 0; i < publicKey.Length; ++i) { if (publicKey [i] == idKey [i]) { continue; } if (publicKey [i] > idKey [i]) { Order = HashOrder.High; At = 1; break; } else { Order = HashOrder.Low; At = 2; break; } } }
public void GenerateEphemeralKeys(ICipherSetRemoteInfo remoteInfo) { CS1ARemoteInfo ri = (CS1ARemoteInfo)remoteInfo; ri.EphemeralKeys = ECKeyPair.Generate (SecNamedCurves.GetByName ("secp160r1")); var hashToken = Helpers.SHA256Hash (ri.EphemeralKeys.PublicKey.Take(16).ToArray()); ri.Token = hashToken.Take (16).ToArray (); }
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 Exchange (Self localIdentity, byte csid, byte[] publicKey) { Local = localIdentity; cipherSet = localIdentity.CipherSets [csid]; var ri = new CS1ARemoteInfo (); ri.RemotePublicKey = publicKey; cipherSet.GenerateEphemeralKeys (ri); remoteInfo = ri; var idKey = localIdentity.CipherSets [csid].Keys.PublicKey; for (int i = 0; i < publicKey.Length; ++i) { if (publicKey [i] == idKey [i]) { continue; } if (publicKey [i] > idKey [i]) { Order = HashOrder.High; At = 1; break; } else { Order = HashOrder.Low; At = 2; break; } } }
public void GenerateEphemeralKeys(ICipherSetRemoteInfo remoteInfo) { CS1ARemoteInfo ri = (CS1ARemoteInfo)remoteInfo; ri.EphemeralKeys = ECKeyPair.Generate(SecNamedCurves.GetByName("secp160r1")); var hashToken = Helpers.SHA256Hash(ri.EphemeralKeys.PublicKey.Take(16).ToArray()); ri.Token = hashToken.Take(16).ToArray(); }
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 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 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 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 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); }