Exemplo n.º 1
0
        PushMsgResult ProcessWelcome(ref Msg msg)
        {
            if (msg.Size != 168)
            {
                return(PushMsgResult.Error);
            }

            Span <byte> welcomeNonce     = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> welcomePlaintext = stackalloc byte[128];
            Span <byte> welcomeBox       = msg.Slice(24, 144);

            WelcomeNoncePrefix.CopyTo(welcomeNonce);
            msg.Slice(8, 16).CopyTo(welcomeNonce.Slice(8));

            using var box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_serverKey);
            bool isDecrypted = box.TryDecrypt(welcomePlaintext, welcomeBox, welcomeNonce);

            if (!isDecrypted)
            {
                return(PushMsgResult.Error);
            }

            m_cnServerKey = welcomePlaintext.Slice(0, 32).ToArray();
            m_cnCookie    = welcomePlaintext.Slice(32, 16 + 80).ToArray();

            // Create the curve box
            m_box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_cnServerKey);

            m_state = State.SendInitiate;

            return(PushMsgResult.Ok);
        }
Exemplo n.º 2
0
        public bool DecodeEndVerify(EncryptedVote vote, out byte[] decoded)
        {
            Curve25519XSalsa20Poly1305 box = new Curve25519XSalsa20Poly1305(_privateKey, vote.PublicKey.ParseHexEncodedValue());
            var encryptedMessage           = vote.Message.ParseHexEncodedValue();
            var decryptedMessage           = new byte[encryptedMessage.Length - XSalsa20Poly1305.TagLength];
            var ret = box.TryDecrypt(decryptedMessage, encryptedMessage, vote.Nonce.ParseHexEncodedValue());

            decoded = decryptedMessage;
            return(ret);
        }
Exemplo n.º 3
0
        PushMsgResult ProcessHello(ref Msg msg)
        {
            if (!CheckBasicCommandStructure(ref msg))
            {
                return(PushMsgResult.Error);
            }

            Span <byte> hello = msg;

            if (!IsCommand("HELLO", ref msg))
            {
                return(PushMsgResult.Error);
            }

            if (hello.Length != 200)
            {
                return(PushMsgResult.Error);
            }

            byte major = hello[6];
            byte minor = hello[7];

            if (major != 1 || minor != 0)
            {
                // client HELLO has unknown version number
                return(PushMsgResult.Error);
            }

            // Save client's short-term public key (C')
            hello.Slice(80, 32).CopyTo(m_cnClientKey);

            Span <byte> helloNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];

            HelloNoncePrefix.CopyTo(helloNonce);
            hello.Slice(112, 8).CopyTo(helloNonce.Slice(16));
            m_peerNonce = NetworkOrderBitsConverter.ToUInt64(hello, 112);

            using var box = new Curve25519XSalsa20Poly1305(m_secretKey, m_cnClientKey);

            Span <byte> helloPlaintext = stackalloc byte[80];
            bool        isDecrypted    = box.TryDecrypt(helloPlaintext, hello.Slice(120, 80), helloNonce);

            if (!isDecrypted)
            {
                return(PushMsgResult.Error);
            }

            helloPlaintext.Clear();

            m_state = State.SendingWelcome;
            return(PushMsgResult.Ok);
        }
Exemplo n.º 4
0
        PushMsgResult ProcessInitiate(ref Msg msg)
        {
            if (!CheckBasicCommandStructure(ref msg))
            {
                return(PushMsgResult.Error);
            }

            Span <byte> initiate = msg;

            if (!IsCommand("INITIATE", ref msg))
            {
                return(PushMsgResult.Error);
            }

            if (initiate.Length < 257)
            {
                return(PushMsgResult.Error);
            }

            Span <byte> cookieNonce     = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> cookiePlaintext = stackalloc byte[64];
            Span <byte> cookieBox       = initiate.Slice(25, 80);

            CookieNoncePrefix.CopyTo(cookieNonce);
            initiate.Slice(9, 16).CopyTo(cookieNonce.Slice(8));

            using var secretBox = new XSalsa20Poly1305(m_cookieKey);
            bool decrypted = secretBox.TryDecrypt(cookiePlaintext, cookieBox, cookieNonce);

            if (!decrypted)
            {
                return(PushMsgResult.Error);
            }

            //  Check cookie plain text is as expected [C' + s']
            if (!SpanUtility.Equals(m_cnClientKey, cookiePlaintext.Slice(0, 32)) ||
                !SpanUtility.Equals(m_cnSecretKey, cookiePlaintext.Slice(32, 32)))
            {
                return(PushMsgResult.Error);
            }

            Span <byte> initiateNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];

            byte[] initiatePlaintext = new byte[msg.Size - 113];
            var    initiateBox       = initiate.Slice(113);

            InitiatieNoncePrefix.CopyTo(initiateNonce);
            initiate.Slice(105, 8).CopyTo(initiateNonce.Slice(16));
            m_peerNonce = NetworkOrderBitsConverter.ToUInt64(initiate, 105);

            using var box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_cnClientKey);
            bool decrypt = box.TryDecrypt(initiatePlaintext, initiateBox, initiateNonce);

            if (!decrypt)
            {
                return(PushMsgResult.Error);
            }

            Span <byte> vouchNonce     = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> vouchPlaintext = stackalloc byte[64];
            Span <byte> vouchBox       = new Span <byte>(initiatePlaintext, 48, 80);
            var         clientKey      = new Span <byte>(initiatePlaintext, 0, 32);

            VouchNoncePrefix.CopyTo(vouchNonce);
            new Span <byte>(initiatePlaintext, 32, 16).CopyTo(vouchNonce.Slice(8));

            using var box2 = new Curve25519XSalsa20Poly1305(m_cnSecretKey, clientKey);
            decrypt        = box2.TryDecrypt(vouchPlaintext, vouchBox, vouchNonce);
            if (!decrypt)
            {
                return(PushMsgResult.Error);
            }

            //  What we decrypted must be the client's short-term public key
            if (!SpanUtility.Equals(vouchPlaintext.Slice(0, 32), m_cnClientKey))
            {
                return(PushMsgResult.Error);
            }

            //  Create the session box
            m_box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_cnClientKey);

            //  This supports the Stonehouse pattern (encryption without authentication).
            m_state = State.SendingReady;

            if (!ParseMetadata(new Span <byte>(initiatePlaintext, 128, initiatePlaintext.Length - 128 - 16)))
            {
                return(PushMsgResult.Error);
            }

            vouchPlaintext.Clear();
            Array.Clear(initiatePlaintext, 0, initiatePlaintext.Length);

            return(PushMsgResult.Ok);
        }
Exemplo n.º 5
0
        public override PushMsgResult Decode(ref Msg msg)
        {
            if (!CheckBasicCommandStructure(ref msg))
            {
                return(PushMsgResult.Error);
            }

            int size = msg.Size;

            if (!IsCommand("MESSAGE", ref msg))
            {
                return(PushMsgResult.Error);
            }

            if (size < 33) // Size of 16 bytes of command + 16 bytes of MAC + 1 byte for flag
            {
                return(PushMsgResult.Error);
            }

            Span <byte> messageNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];

            m_decodeNoncePrefix.CopyTo(messageNonce);
            msg.Slice(8, 8).CopyTo(messageNonce.Slice(16));

            UInt64 nonce = NetworkOrderBitsConverter.ToUInt64(msg, 8);

            if (nonce <= m_peerNonce)
            {
                return(PushMsgResult.Error);
            }

            m_peerNonce = nonce;

            Msg plain = new Msg();

            plain.InitPool(msg.Size - 16 - Curve25519XSalsa20Poly1305.TagLength);

            var isAuthenticate = m_box.TryDecrypt(plain, msg.Slice(16), messageNonce);

            if (!isAuthenticate)
            {
                plain.Close();
                return(PushMsgResult.Error);
            }

            msg.Move(ref plain);

            byte flags = msg[0];

            if ((flags & 0x01) != 0)
            {
                msg.SetFlags(MsgFlags.More);
            }
            if ((flags & 0x02) != 0)
            {
                msg.SetFlags(MsgFlags.Command);
            }

            msg.TrimPrefix(1);

            return(PushMsgResult.Ok);
        }