Example #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));
        }
Example #2
0
        public void TestDiffieHellmanSha256FromBase64()
        {
            var serverEphPubKeyBase64BE = "5+K+/aahgA7QLksySOV43r+iwM0F/RPDfgCM344Mf+pqKlLMPKzGJhkhhKriE6UJ95JmfiGngIoKegQ+plHz2w==";
            var serverEphPriKeyBase64BE = "sxJNyEO7i6YfA1p9CTglH13Uy/yW9UU7Ew2JChzbrjI=";

            var clientEphEccPrivateBlobBase64 = "RUNLMiAAAADgzTD0gIgNIjSEoCVMZnIvGerxx6FTZHheMPzI44s1mBAjjtZw5R2YVC1zubdetTpRHnGXBoje56G97htrY7WGpUWP1xM8GhdWN31HjIgR68JNuW4XIlTgO0qOE0ezNjI=";
            var clientEphEccPrivateBlob       = clientEphEccPrivateBlobBase64.FromBase64String();
            var clientEphCng = ECDHHelper.ImportFromEccPrivateBlob(
                clientEphEccPrivateBlob, out byte[] clientEphPubKey, out byte[] clientEphPriKey);

            byte[] commonSecretClient;
            {
                var serverEphPub    = serverEphPubKeyBase64BE.FromBase64String().ReverseEndianness();
                var serverEphCngKey = serverEphPub.ToECDHCngKey();

                commonSecretClient = clientEphCng.DeriveKeyMaterial(serverEphCngKey);
            }

            byte[] commonSecretServer;
            {
                var serverEphPubKey = serverEphPubKeyBase64BE.FromBase64String().ReverseEndianness();
                var serverEphPriKey = serverEphPriKeyBase64BE.FromBase64String().ReverseEndianness();
                var serverEphCng    = ECDHHelper.Import(serverEphPubKey, serverEphPriKey);

                commonSecretServer = serverEphCng.DeriveKeyMaterial(clientEphCng.PublicKey);
            }

            Assert.IsTrue(commonSecretClient.SequenceEqual(commonSecretServer));
        }
Example #3
0
        public bool GetServerIdentity(byte[] clientProofOfWork, out byte[] serverIdentity)
        {
            serverIdentity = null;

            if (!ClientProofOfWork.Parse(clientProofOfWork, out ClientProofOfWork cpow))
            {
                return(false);
            }

            if (!cpow.knownSecretariumPubKey.SequenceEqual(GenesisPubKey))
            {
                return(false);
            }

            // Create ephemereal DH keys
            var eph       = ECDHHelper.CreateCngKey();
            var ephCng    = ECDHHelper.CreateECDiffieHellmanCngSha256(eph);
            var ephPubKey = ephCng.PublicKey();

            // Get CommonKey from DH
            var clientPublicCngKey = Session.ClientEphDHPubKey.ToECDHCngKey();
            var commonKey          = ephCng.DeriveKeyMaterial(clientPublicCngKey);

            // Generate a random SymmetricKey
            var symmetricKey = ByteHelper.GetRandom(commonKey.Length);

            // XOR CommonKey and SymmetricKey to produce a PreMasterSecret
            var preMasterSecret = commonKey.Xor(symmetricKey);

            serverIdentity = ByteHelper.Combine(preMasterSecret, ephPubKey, GenesisPubKey);

            Session.SymmetricKey = symmetricKey;

            return(true);
        }
Example #4
0
        public void TestDiffieHellmanSha256()
        {
            var client = ECDHHelper.CreateECDiffieHellmanCngSha256();
            var server = ECDHHelper.CreateECDiffieHellmanCngSha256();

            var commonSecretBytesClient = client.DeriveKeyMaterial(server.PublicKey);
            var commonSecretBytesServer = server.DeriveKeyMaterial(client.PublicKey);

            Assert.IsTrue(commonSecretBytesClient.SequenceEqual(commonSecretBytesServer));
        }
Example #5
0
        public void TestDiffieHellmanP256()
        {
            var clientKey = ECDHHelper.CreateCngKey();
            var serverKey = ECDHHelper.CreateCngKey();

            var clientECDHCng = ECDHHelper.CreateECDiffieHellmanCngSha256(clientKey);
            var serverECDHCng = ECDHHelper.CreateECDiffieHellmanCngSha256(serverKey);

            var commonSecretServer = serverECDHCng.DeriveKeyMaterial(clientECDHCng.PublicKey);
            var commonSecretClient = clientECDHCng.DeriveKeyMaterial(serverECDHCng.PublicKey);

            Assert.IsTrue(commonSecretClient.SequenceEqual(commonSecretServer));
        }
Example #6
0
        public void TestDiffieHellmanSha256IsReplayable()
        {
            var clientFullKey = ECDHHelper.CreateECDiffieHellmanCngSha256().Key;
            var serverFullKey = ECDHHelper.CreateECDiffieHellmanCngSha256().Key;

            var clientECDH1 = ECDHHelper.CreateECDiffieHellmanCngSha256(clientFullKey);
            var serverECDH1 = ECDHHelper.CreateECDiffieHellmanCngSha256(serverFullKey);
            var commonSecretBytesClient1 = clientECDH1.DeriveKeyMaterial(serverECDH1.PublicKey);
            var commonSecretBytesServer1 = serverECDH1.DeriveKeyMaterial(clientECDH1.PublicKey);

            Assert.IsTrue(commonSecretBytesClient1.SequenceEqual(commonSecretBytesServer1));

            var clientECDH2 = ECDHHelper.CreateECDiffieHellmanCngSha256(clientFullKey);
            var serverECDH2 = ECDHHelper.CreateECDiffieHellmanCngSha256(serverFullKey);
            var commonSecretBytesClient2 = clientECDH2.DeriveKeyMaterial(serverECDH2.PublicKey);
            var commonSecretBytesServer2 = serverECDH2.DeriveKeyMaterial(clientECDH2.PublicKey);

            Assert.IsTrue(commonSecretBytesClient2.SequenceEqual(commonSecretBytesServer2));

            Assert.IsTrue(commonSecretBytesClient1.SequenceEqual(commonSecretBytesClient2));
        }
Example #7
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);
        }
Example #8
0
        public void TestCngKeyOnP256()
        {
            CngKey key = ECDHHelper.CreateCngKey();

            EllipticCurveHelper.TestKeyBelongsToP256(key);
        }
Example #9
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))