public void PolyReferenceTests(byte[] key, byte[] iv, byte[] data, byte[] expected) { Poly pmac = new Poly(Common.AesFactory); pmac.Init(key, iv, 16); pmac.Process(new ArraySegment <byte>(data)); byte[] mac = pmac.Compute(); var bcpoly = new Poly1305(new AesEngine()); bcpoly.Init(new ParametersWithIV(new KeyParameter(key), iv)); bcpoly.BlockUpdate(data, 0, data.Length); byte[] bcmac = new byte[bcpoly.GetMacSize()]; bcpoly.DoFinal(bcmac, 0); var _key = string.Join(", ", key.Select(b => $"0x{b:x2}")); var _iv = string.Join(", ", iv.Select(b => $"0x{b:x2}")); var _data = string.Join(", ", data.Select(b => $"0x{b:x2}")); var _expected = string.Join(", ", bcmac.Select(b => $"0x{b:x2}")); Log.Verbose($"[InlineData(new byte[] {{{_key}}}, new byte[] {{{_iv}}}, new byte[] {{{_data}}}, new byte[] {{{_expected}}})]"); Assert.Equal(expected, mac); Assert.Equal(expected, bcmac); }
public void PolyMultiTest() { RandomNumberGenerator rng = new RandomNumberGenerator(); byte[] iv = rng.Generate(16); byte[] key = rng.Generate(32); byte[] data = rng.Generate(100); Poly pmac = new Poly(Common.AesFactory); pmac.Init(key, iv, 16); pmac.Process(new ArraySegment <byte>(data)); byte[] mac1 = pmac.Compute(); pmac = new Poly(Common.AesFactory); pmac.Init(key, iv, 16); pmac.Process(new ArraySegment <byte>(data, 0, 50)); pmac.Process(new ArraySegment <byte>(data, 50, 50)); byte[] mac2 = pmac.Compute(); pmac = new Poly(Common.AesFactory); pmac.Init(key, iv, 16); pmac.Process(new ArraySegment <byte>(data, 0, 33)); pmac.Process(new ArraySegment <byte>(data, 33, 33)); pmac.Process(new ArraySegment <byte>(data, 66, 34)); byte[] mac3 = pmac.Compute(); Assert.Equal(mac1, mac2); Assert.Equal(mac1, mac3); }
public void PolyReuseKeyTest(int ivBytes, int dataBytes, int macSize) { RandomNumberGenerator rng = new RandomNumberGenerator(); byte[] iv = rng.Generate(ivBytes); byte[] key = rng.Generate(32); byte[] data1 = rng.Generate(dataBytes); byte[] data2 = rng.Generate(dataBytes); var pmac = new Poly(Common.AesFactory); pmac.Init(key, iv, macSize); pmac.Process(new ArraySegment <byte>(data1)); byte[] mac1 = pmac.Compute(); pmac.Init(key, iv, macSize); pmac.Process(new ArraySegment <byte>(data2)); byte[] mac2 = pmac.Compute(); var bcpoly1 = new Poly1305(new AesEngine()); bcpoly1.Init(new ParametersWithIV(new KeyParameter(key), iv)); bcpoly1.BlockUpdate(data1, 0, data1.Length); byte[] bcmac1 = new byte[bcpoly1.GetMacSize()]; bcpoly1.DoFinal(bcmac1, 0); bcmac1 = bcmac1.Take(macSize).ToArray(); var bcpoly2 = new Poly1305(new AesEngine()); bcpoly2.Init(new ParametersWithIV(new KeyParameter(key), iv)); bcpoly2.BlockUpdate(data2, 0, data2.Length); byte[] bcmac2 = new byte[bcpoly2.GetMacSize()]; bcpoly2.DoFinal(bcmac2, 0); bcmac2 = bcmac2.Take(macSize).ToArray(); Assert.Equal(bcmac1, mac1); Assert.Equal(bcmac2, mac2); }
public void BasicPolyTests(int ivBytes, int dataBytes, int macSize) { RandomNumberGenerator rng = new RandomNumberGenerator(); byte[] iv = rng.Generate(ivBytes); byte[] key = rng.Generate(32); byte[] data = rng.Generate(dataBytes); Poly pmac = new Poly(Common.AesFactory); var bcpoly = new Poly1305(new AesEngine()); pmac.Init(key, iv, macSize); bcpoly.Init(new ParametersWithIV(new KeyParameter(key), iv)); pmac.Process(new ArraySegment <byte>(data)); byte[] mac = pmac.Compute(); bcpoly.BlockUpdate(data, 0, data.Length); byte[] bcmac = new byte[bcpoly.GetMacSize()]; bcpoly.DoFinal(bcmac, 0); bcmac = bcmac.Take(macSize).ToArray(); Assert.Equal(bcmac, mac); }
static void Main(string[] args) { int messageCount = 1000000; double clientDropChance = 0.0; double serverDropChance = 0.0; var defaultServices = new BouncyCastleServices(KeyGeneration.GeneratePrivateKey()); Random r = new Random(); RandomNumberGenerator rng = new RandomNumberGenerator(); Stopwatch sw = new Stopwatch(); Console.WriteLine("Generating data..."); byte[] keys = new byte[16 * 1000000]; byte[] blocks = new byte[16 * 1000000]; byte[] output = new byte[32 * 1000000]; rng.Generate(keys); rng.Generate(blocks); Thread.Sleep(1000); { var poly = new Poly(defaultServices.AesFactory); poly.Init(new ArraySegment <byte>(keys, 0, 32), new ArraySegment <byte>(blocks, 0, 16), 16); poly.Init(new ArraySegment <byte>(keys, 1000, 32), new ArraySegment <byte>(blocks, 1000, 16), 16); Console.WriteLine("Doing Pol1305 MACs"); sw.Reset(); sw.Start(); for (int i = 0; i < keys.Length; i += 32) { poly.Process(blocks, i, 16); poly.Process(blocks, i, 16); poly.Process(blocks, i, 16); poly.Process(blocks, i, 16); poly.Compute(new ArraySegment <byte>(output, i, 16)); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({(keys.Length / 32) / sw.Elapsed.TotalSeconds:F0}/s)"); } Thread.Sleep(1000); { var sha = System.Security.Cryptography.SHA256.Create(); sha.ComputeHash(blocks, 10000, 16); Console.WriteLine("Doing SHA256 hashes (dotnet)"); sw.Reset(); sw.Start(); for (int i = 0; i < blocks.Length; i += 16) { sha.ComputeHash(blocks, i, 16); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({(keys.Length / 16) / sw.Elapsed.TotalSeconds:F0}/s)"); } Thread.Sleep(1000); { var sha = new Org.BouncyCastle.Crypto.Digests.Sha256Digest(); sha.BlockUpdate(blocks, 10000, 16); sha.DoFinal(output, 10000); Console.WriteLine("Doing SHA256 hashes (bc)"); sw.Reset(); sw.Start(); for (int i = 0; i < blocks.Length; i += 16) { sha.BlockUpdate(blocks, i, 16); sha.DoFinal(output, i * 2); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({(keys.Length / 16) / sw.Elapsed.TotalSeconds:F0}/s)"); } Thread.Sleep(1000); { var aes = System.Security.Cryptography.Aes.Create(); aes.Mode = System.Security.Cryptography.CipherMode.ECB; var key = new byte[16]; Array.Copy(keys, 10000, key, 0, 16); aes.CreateEncryptor(key, null); Console.WriteLine("Calculating AES keys (dotnet)"); sw.Reset(); sw.Start(); for (int i = 0; i < keys.Length; i += 16) { Array.Copy(keys, i, key, 0, 16); aes.CreateEncryptor(key, null); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({(keys.Length / 16) / sw.Elapsed.TotalSeconds:F0}/s)"); } Thread.Sleep(1000); { var aes = System.Security.Cryptography.Aes.Create(); aes.Mode = System.Security.Cryptography.CipherMode.ECB; var key = new byte[16]; Array.Copy(keys, key, 16); var enc = aes.CreateEncryptor(key, null); enc.TransformBlock(blocks, 10000, 16, output, 10000); Console.WriteLine("Processing AES blocks (dotnet"); sw.Reset(); sw.Start(); for (int i = 0; i < blocks.Length; i += 16) { enc.TransformBlock(blocks, i, 16, output, i); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({(keys.Length / 16) / sw.Elapsed.TotalSeconds:F0}/s)"); } Thread.Sleep(1000); { Org.BouncyCastle.Crypto.Engines.AesEngine aes = new Org.BouncyCastle.Crypto.Engines.AesEngine(); aes.Init(true, new KeyParameter(keys, 10000, 16)); aes.Init(true, new KeyParameter(keys, 20000, 16)); Console.WriteLine("Calculating AES keys (bc)"); sw.Reset(); sw.Start(); for (int i = 0; i < keys.Length; i += 16) { aes.Init(true, new KeyParameter(keys, i, 16)); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({(keys.Length / 16) / sw.Elapsed.TotalSeconds:F0}/s)"); } Thread.Sleep(1000); { Org.BouncyCastle.Crypto.Engines.AesEngine aes = new Org.BouncyCastle.Crypto.Engines.AesEngine(); aes.Init(true, new KeyParameter(keys, 12300, 16)); aes.ProcessBlock(blocks, 10000, output, 10000); Console.WriteLine("Processing AES blocks (bc)"); sw.Reset(); sw.Start(); for (int i = 0; i < blocks.Length; i += 16) { aes.ProcessBlock(blocks, i, output, i); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({(keys.Length / 16) / sw.Elapsed.TotalSeconds:F0}/s)"); } Thread.Sleep(1000); { var aes = new Org.BouncyCastle.Crypto.Engines.AesLightEngine(); aes.Init(true, new KeyParameter(keys, 10000, 16)); aes.Init(true, new KeyParameter(keys, 20000, 16)); Console.WriteLine("Calculating AES keys (bc light)"); sw.Reset(); sw.Start(); for (int i = 0; i < keys.Length; i += 16) { aes.Init(true, new KeyParameter(keys, i, 16)); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({(keys.Length / 16) / sw.Elapsed.TotalSeconds:F0}/s)"); } Thread.Sleep(1000); { var aes = new Org.BouncyCastle.Crypto.Engines.AesLightEngine(); aes.Init(true, new KeyParameter(keys, 12340, 16)); aes.ProcessBlock(blocks, 10000, output, 10000); Console.WriteLine("Processing AES blocks (bc light)"); sw.Reset(); sw.Start(); for (int i = 0; i < blocks.Length; i += 16) { aes.ProcessBlock(blocks, i, output, i); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({(keys.Length / 16) / sw.Elapsed.TotalSeconds:F0}/s)"); } Thread.Sleep(1000); { SymmetricRacthet sr = new SymmetricRacthet(); var(client, server) = CreateAndInitialize(); var kdf = new AesKdf(client.Services.AesFactory); sr.Initialize(rng.Generate(32)); Console.WriteLine("Testing Symmetric Ratchet Speed"); sr.RatchetForSending(kdf); sr.RatchetForSending(kdf); sr.RatchetForSending(kdf); sr.RatchetForSending(kdf); sw.Reset(); sw.Start(); int cnt = 1000000; for (int i = 0; i < cnt; i++) { sr.RatchetForSending(kdf); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({cnt / sw.Elapsed.TotalSeconds:F0}/s)"); Console.WriteLine($"It would take { (double)int.MaxValue / 2 / (cnt / sw.Elapsed.TotalSeconds) / 60:F0} minutes to do 2^32 ratchets"); } Thread.Sleep(1000); { Console.WriteLine("Testing one way message send speed (small: 16 bytes)..."); var(client, server) = CreateAndInitialize(); var messagesToSend = Enumerable.Range(0, messageCount).Select(_ => rng.Generate(16)).ToArray(); var messagesSent = new List <byte[]>(messageCount); var m1 = client.Send(new byte[16]); var m2 = client.Send(new byte[16]); var m3 = client.Send(new byte[16]); sw.Reset(); sw.Start(); for (int i = 0; i < messageCount; i++) { messagesSent.Add(client.Send(messagesToSend[i])); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({messageCount / sw.Elapsed.TotalSeconds:F0}/s)"); Console.WriteLine($"Bandwidth: { messagesToSend.Sum(x => x.Length * 8) / sw.Elapsed.TotalSeconds / (1024 * 1024):F0} Mbps"); Thread.Sleep(1000); Console.WriteLine("Testing one way message receive speed (small: 16 bytes)..."); server.Receive(m1); server.Receive(m2); server.Receive(m3); sw.Reset(); sw.Start(); for (int i = 0; i < messageCount; i++) { server.Receive(messagesSent[i]); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({messageCount / sw.Elapsed.TotalSeconds:F0}/s)"); Console.WriteLine($"Bandwidth: { messagesToSend.Sum(x => x.Length * 8) / sw.Elapsed.TotalSeconds / (1024 * 1024):F0} Mbps"); } Thread.Sleep(2000); { Console.WriteLine("Testing one way message send speed (large: 64 bytes)..."); var(client, server) = CreateAndInitialize(); var messagesToSend = Enumerable.Range(0, messageCount).Select(_ => rng.Generate(64)).ToArray(); var messagesSent = new List <byte[]>(messageCount); var m1 = client.Send(new byte[16]); var m2 = client.Send(new byte[16]); var m3 = client.Send(new byte[16]); sw.Reset(); sw.Start(); for (int i = 0; i < messageCount; i++) { messagesSent.Add(client.Send(messagesToSend[i])); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({messageCount / sw.Elapsed.TotalSeconds:F0}/s)"); Console.WriteLine($"Bandwidth: { messagesToSend.Sum(x => x.Length * 8) / sw.Elapsed.TotalSeconds / (1024 * 1024):F0} Mbps"); Thread.Sleep(1000); Console.WriteLine("Testing one way message receive speed (large: 64 bytes)..."); server.Receive(m1); server.Receive(m2); server.Receive(m3); sw.Reset(); sw.Start(); for (int i = 0; i < messageCount; i++) { server.Receive(messagesSent[i]); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({messageCount / sw.Elapsed.TotalSeconds:F0}/s)"); Console.WriteLine($"Bandwidth: { messagesToSend.Sum(x => x.Length * 8) / sw.Elapsed.TotalSeconds / (1024 * 1024):F0} Mbps"); } messageCount /= 10; Thread.Sleep(2000); { Console.WriteLine("Testing one way message send speed (IP: 1350 bytes)..."); var(client, server) = CreateAndInitialize(1350); var messagesToSend = Enumerable.Range(0, messageCount).Select(_ => rng.Generate(1300)).ToArray(); var messagesSent = new List <byte[]>(messageCount); var m1 = client.Send(new byte[16]); var m2 = client.Send(new byte[16]); var m3 = client.Send(new byte[16]); sw.Reset(); sw.Start(); for (int i = 0; i < messageCount; i++) { messagesSent.Add(client.Send(messagesToSend[i])); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({messageCount / sw.Elapsed.TotalSeconds:F0}/s)"); Console.WriteLine($"Bandwidth: { messagesToSend.Sum(x => x.Length * 8) / sw.Elapsed.TotalSeconds / (1024 * 1024):F0} Mbps"); Thread.Sleep(1000); Console.WriteLine("Testing one way message receive speed (IP: 1350 bytes)..."); server.Receive(m1); server.Receive(m2); server.Receive(m3); sw.Reset(); sw.Start(); for (int i = 0; i < messageCount; i++) { server.Receive(messagesSent[i]); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({messageCount / sw.Elapsed.TotalSeconds:F0}/s)"); Console.WriteLine($"Bandwidth: { messagesToSend.Sum(x => x.Length * 8) / sw.Elapsed.TotalSeconds / (1024 * 1024):F0} Mbps"); } Thread.Sleep(1000); { Console.WriteLine("Testing ECDHratchet speed..."); var(client, server) = CreateAndInitialize(1350); var messagesToSend = Enumerable.Range(0, messageCount / 4000).Select(_ => rng.Generate(32)).ToArray(); server.Receive(client.Send(new byte[32])); client.Receive(server.Send(new byte[32])); sw.Reset(); sw.Start(); for (int i = 0; i < messageCount / 4000; i++) { var m1 = client.Send(messagesToSend[i]); server.Receive(m1); var m2 = server.Send(messagesToSend[i]); client.Receive(m2); } sw.Stop(); Console.WriteLine($"Took {sw.Elapsed.TotalSeconds:F2}s ({(messageCount / 2000) / sw.Elapsed.TotalSeconds:F0}/s)"); } messageCount *= 10; Thread.Sleep(1000); { var(client, server) = CreateAndInitialize(); var clientMessages = new HashSet <byte[]>(Enumerable.Range(0, messageCount).Select(_ => rng.Generate(32))); var serverMessages = new HashSet <byte[]>(Enumerable.Range(0, messageCount).Select(_ => rng.Generate(32))); Queue <byte[]> clientMessagesToSend = new Queue <byte[]>(clientMessages); Queue <byte[]> serverMessagesToSend = new Queue <byte[]>(serverMessages); var messagesSentFromClient = new Queue <byte[]>(); var messagesSentFromServer = new Queue <byte[]>(); HashSet <byte[]> messagesReceivedByClient = new HashSet <byte[]>(); HashSet <byte[]> messagesReceivedByServer = new HashSet <byte[]>(); byte[] DoubleInSize(byte[] payload) => payload.Concat(payload).ToArray(); int clientSent = 0, serverSent = 0, clientReceived = 0, serverReceived = 0, clientDropped = 0, serverDropped = 0; Console.WriteLine($"Sending {messageCount}/{clientDropChance:P0} and {messageCount}/{serverDropChance:P0}"); sw.Reset(); sw.Start(); double oldTime = 0; int oldCnt = 0; for (int i = 0; ; i++) { bool anyMessagesToReceive = messagesSentFromClient.TryPeek(out var _) || messagesSentFromServer.TryPeek(out var _); bool anyMessagesToSend = clientMessagesToSend.TryPeek(out var _) || serverMessagesToSend.TryPeek(out var _); if (!anyMessagesToReceive && !anyMessagesToSend) { break; } if (i % 1000 == 0) { var totalReceived = clientReceived + serverReceived + clientDropped + serverDropped; var totalAll = messageCount + messageCount; var percentage = (double)totalReceived / totalAll; var newTime = sw.Elapsed.TotalSeconds; var deltaTime = newTime - oldTime; var deltaCnt = totalReceived - oldCnt; double perSecond = 0; if (oldTime != 0) { perSecond = deltaCnt / deltaTime; } Console.Write($"\r{percentage:P0} - c: {clientSent}/{clientDropped} -> {serverReceived} s: {serverSent}/{serverDropped} -> {clientReceived} ({perSecond:F0}/s) "); oldCnt = totalReceived; oldTime = newTime; } var clientOrServer = r.Next(2); var sendOrReceive = r.Next(2); double ratio = (double)messageCount / messageCount; int maxClient = 100; int maxServer = (int)(100 / ratio); var maxMessages = r.Next(clientOrServer == 0 ? maxClient : maxServer) + 1; if (anyMessagesToSend && (sendOrReceive == 0 || !anyMessagesToReceive)) { if (clientOrServer == 0) // send from client { while (maxMessages-- > 0) { clientMessagesToSend.TryDequeue(out var payload); if (payload != null) { payload = r.Next(10) > 7 ? DoubleInSize(payload) : payload; var message = client.Send(payload); if (r.NextDouble() > clientDropChance) { clientSent++; messagesSentFromClient.Enqueue(message); } else { clientDropped++; } } } } else { while (maxMessages-- > 0) { serverMessagesToSend.TryDequeue(out var payload); if (payload != null) { payload = r.Next(10) > 7 ? DoubleInSize(payload) : payload; var message = server.Send(payload); if (r.NextDouble() > serverDropChance) { serverSent++; messagesSentFromServer.Enqueue(message); } else { serverDropped++; } } } } } else { if (clientOrServer != 0) // receive by client { while (maxMessages-- > 0) { messagesSentFromServer.TryDequeue(out var message); if (message != null) { var payload = client.Receive(message).Payload; messagesReceivedByClient.Add(payload); clientReceived++; } } } else // receive by server { while (maxMessages-- > 0) { messagesSentFromClient.TryDequeue(out var message); if (message != null) { var payload = server.Receive(message).Payload; messagesReceivedByServer.Add(payload); serverReceived++; } } } } } Console.WriteLine("Done"); } }