public void TestKeyExchange(ScpConfig.EncryptionMode encryptionMode) { // Client side var clientEph = ECDHHelper.CreateCngKey(); var clientEphCng = ECDHHelper.CreateECDiffieHellmanCngSha256(clientEph); var clientEphPubKey = clientEphCng.PublicKey(); // Server side var secretarium = new MockedSecretarium(encryptionMode); Assert.IsTrue(secretarium.GetServerHello(clientEphPubKey, out byte[] serverHello)); Assert.IsTrue(ServerHello.Parse(serverHello, 18, out ServerHello serverHelloObj)); // Client side Assert.IsTrue(DiffieHellmanHelper.ComputeProofOfWork(serverHelloObj.proofOfWorkDetails, out byte[] proofOfWork)); var clientProofOfWork = ByteHelper.Combine(proofOfWork.ExtendTo(32), MockedSecretarium.GenesisPubKey); // Server side Assert.IsTrue(secretarium.GetServerIdentity(clientProofOfWork, out byte[] serverIdentity)); Assert.IsTrue(ServerIdentity.Parse(serverIdentity, out ServerIdentity serverIdentityObj)); // Client side var symmetricKey = DiffieHellmanHelper.GetSymmetricKey( clientEphCng, serverIdentityObj.ephDHKey, serverIdentityObj.preMasterSecret); // Check keys are the same both sides Assert.IsTrue(symmetricKey.SequenceEqual(secretarium.Session.SymmetricKey)); }
public void TestComputeProofOfWork() { var d = new ProofOfWorkDetails { difficulty = 15, challenge = ByteHelper.GetRandom(31) }; var res = DiffieHellmanHelper.ComputeProofOfWork(d, out byte[] proof); Assert.IsTrue(res); VerifyPow(d, proof); }
public void TestPerformances() { var difficulties = new int[] { 15, 16, 17, 18, 19, 20, 21, 22 }; var results = new long[difficulties.Length * 2]; var loops = 50L; for (var k = 0; k < loops; k++) { var d = new ProofOfWorkDetails { challenge = ByteHelper.GetRandom(31) }; for (var i = 0; i < difficulties.Length; i++) { var sw1 = Stopwatch.StartNew(); d.difficulty = (byte)difficulties[i]; var res = DiffieHellmanHelper.ComputeProofOfWork(d, out byte[] proof); Assert.IsTrue(res); sw1.Stop(); var sw2 = Stopwatch.StartNew(); VerifyPow(d, proof); sw2.Stop(); results[i * 2] += sw1.ElapsedMilliseconds; results[i * 2 + 1] += sw2.ElapsedMilliseconds; } } for (var i = 0; i < difficulties.Length; i++) { var msg = string.Format("Difficulty {0}, proof {1}ms, verification {2}ms", difficulties[i], results[i * 2] / loops, results[i * 2 + 1] / loops); TestContext.WriteLine(msg); } }
private bool FullProtocolFromX509(ScpConfig.EncryptionMode encryptionMode, out byte[] symmetricKey, out MockedSecretarium secretarium) { // Client keys Assert.IsTrue(ScpConfigHelper.TryLoad("test.x509.json", out ScpConfig config)); Assert.IsTrue(config.TryGetECDsaKey(out ECDsaCng clientECDsaKeyCng, "SecretariumTestClient256")); var clientPub = clientECDsaKeyCng.ExportPublicKeyRaw(); // Client Hello var clientEph = ECDHHelper.CreateCngKey(); var clientEphCng = ECDHHelper.CreateECDiffieHellmanCngSha256(clientEph); var clientEphPub = clientEphCng.PublicKey(); var clientHello = clientEphPub; Assert.IsTrue(ClientHello.Parse(clientHello, out ClientHello clientHelloObj)); // Server Hello secretarium = new MockedSecretarium(encryptionMode); secretarium.GetServerHello(clientHello, out byte[] serverHello); Assert.IsTrue(ServerHello.Parse(serverHello, 18, out ServerHello serverHelloObj)); // Client ClientProofOfWork Assert.IsTrue(DiffieHellmanHelper.ComputeProofOfWork(serverHelloObj.proofOfWorkDetails, out byte[] proofOfWork)); var clientProofOfWork = ByteHelper.Combine(proofOfWork.ExtendTo(32), MockedSecretarium.GenesisPubKey); Assert.IsTrue(ClientProofOfWork.Parse(clientProofOfWork, out ClientProofOfWork clientProofOfWorkObj)); // Server Identity secretarium.GetServerIdentity(clientProofOfWork, out byte[] serverIdentity); Assert.IsTrue(ServerIdentity.Parse(serverIdentity, out ServerIdentity serverIdentityObj)); // Client computes symmetric key symmetricKey = DiffieHellmanHelper.GetSymmetricKey( clientEphCng, serverIdentityObj.ephDHKey, serverIdentityObj.preMasterSecret); // Client Proof Of Identity var nonce = ByteHelper.GetRandom(32); var nonceSigned = clientECDsaKeyCng.SignData(nonce); var clientProofOfIdentity = ByteHelper.Combine(nonce, clientEphPub, clientPub, nonceSigned); Assert.IsTrue(ClientProofOfIdentity.Parse(clientProofOfIdentity, out ClientProofOfIdentity clientProofOfIdentityObj)); // Client Encrypts Client Proof Of Identity var ivOffset = ByteHelper.GetRandom(16); var encryptedClientProofOfIdentity = encryptionMode == ScpConfig.EncryptionMode.AESCTR ? clientProofOfIdentity.AesCtrEncrypt(symmetricKey, ivOffset) : clientProofOfIdentity.AesGcmEncryptWithOffset(symmetricKey, ivOffset); var encryptedClientProofOfIdentityWithIvOffset = ByteHelper.Combine(ivOffset, encryptedClientProofOfIdentity); // Server Checks And Sends Proof Of Identity Assert.IsTrue(secretarium.GetServerProofOfIdentity( encryptedClientProofOfIdentityWithIvOffset, out byte[] encryptedServerProofOfIdentity)); // Client Decrypts Server Proof Of Identity ivOffset = encryptedServerProofOfIdentity.Extract(0, 16); var serverProofOfIdentity = encryptionMode == ScpConfig.EncryptionMode.AESCTR ? encryptedServerProofOfIdentity.Extract(16).AesCtrDecrypt(symmetricKey, ivOffset) : encryptedServerProofOfIdentity.Extract(16).AesGcmDecryptWithOffset(symmetricKey, ivOffset); Assert.IsTrue(ServerProofOfIdentity.Parse(serverProofOfIdentity, out ServerProofOfIdentity serverProofOfIdentityObj)); // Client Checks Server Proof Of Idendity var msg = "Hey you! Welcome to Secretarium!".ToBytes(); var secretariumECDsaCng = ECDsaHelper.ImportPublicKey(serverIdentityObj.publicKey); Assert.IsTrue(secretariumECDsaCng.VerifyData( ByteHelper.Combine(serverProofOfIdentityObj.nonce, msg), serverProofOfIdentityObj.welcomeSigned)); return(true); }
public bool Connect(int timeout = 3000) { if (_webSocket != null) { _webSocket.Close(); } // -1- Open Websocket UpdateState(ConnectionState.Connecting); var signal = new AutoResetEvent(false); var canContinue = true; void onOpenHandler(object sender, EventArgs e) { UpdateState(ConnectionState.Open); signal.Set(); } void onCloseHandler(object sender, CloseEventArgs e) { UpdateState(ConnectionState.Closed); canContinue = false; //signal.Set(); Force wait until timeout to avoid quick reconnection loops } void onErrorHandler(object sender, ErrorEventArgs e) { UpdateState(ConnectionState.Closed); canContinue = false; //signal.Set(); Force wait until timeout to avoid quick reconnection loops } EventHandler <MessageEventArgs> onMessageHandler; _webSocket = new WebSocket(_config.secretarium.endPoint, "pair1.sp.nanomsg.org"); _webSocket.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls12; _webSocket.Compression = CompressionMethod.None; _webSocket.OnOpen += onOpenHandler; _webSocket.OnClose += onCloseHandler; _webSocket.OnError += onErrorHandler; _webSocket.Connect(); if (!signal.WaitOne(timeout) || !canContinue) { _webSocket.Close(); return(false); } _webSocket.OnOpen -= onOpenHandler; // -2- Send Client Hello UpdateState(ConnectionState.SecureConnectionInProgress); var clientEphCngKey = ECDHHelper.CreateCngKey(); var clientEphCng = ECDHHelper.CreateECDiffieHellmanCngSha256(clientEphCngKey); var clientEphPub = clientEphCngKey.ExportPublicKeyRaw(); var clientHello = ByteHelper.Combine(_hop, clientEphPub); ServerHello serverHello = null; onMessageHandler = (sender, e) => { if (!ServerHello.Parse(e.RawData.Extract(4), MaxAllowedPoWDifficilty, out serverHello)) { canContinue = false; } signal.Set(); }; _webSocket.OnMessage += onMessageHandler; _webSocket.Send(clientHello); if (!signal.WaitOne(timeout) || !canContinue) { _webSocket.Close(); return(false); } _webSocket.OnMessage -= onMessageHandler; // -3- Send Client Proof Of Work if (!DiffieHellmanHelper.ComputeProofOfWork(serverHello.proofOfWorkDetails, out byte[] proofOfWork))