Beispiel #1
0
        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));
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
            }
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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))