Exemple #1
0
        PushMsgResult ProcessReady(ref Msg msg)
        {
            if (msg.Size < 30)
            {
                return(PushMsgResult.Error);
            }

            Span <byte> readyNonce     = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            var         readyPlaintext = new byte[msg.Size - 14 - Curve25519XSalsa20Poly1305.TagLength];
            Span <byte> readyBox       = msg.Slice(14);

            ReadyNoncePrefix.CopyTo(readyNonce);
            msg.Slice(6, 8).CopyTo(readyNonce.Slice(16));
            m_peerNonce = NetworkOrderBitsConverter.ToUInt64(msg, 6);

            bool isDecrypted = m_box.TryDecrypt(readyPlaintext, readyBox, readyNonce);

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

            if (!ParseMetadata(readyPlaintext))
            {
                return(PushMsgResult.Error);
            }

            Array.Clear(readyPlaintext, 0, readyPlaintext.Length);

            m_state = State.Connected;
            return(PushMsgResult.Ok);
        }
Exemple #2
0
        PullMsgResult ProduceReady(ref Msg msg)
        {
            int         metadataLength = BasicPropertiesLength;
            Span <byte> readyNonce     = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];

            byte[] readyPlaintext = new byte[metadataLength];

            //  Create Box [metadata](S'->C')
            AddBasicProperties(readyPlaintext);

            ReadyNoncePrefix.CopyTo(readyNonce);
            NetworkOrderBitsConverter.PutUInt64(m_nonce, readyNonce.Slice(16));

            msg.InitPool(14 + Curve25519XSalsa20Poly1305.TagLength + metadataLength);
            var readyBox = msg.Slice(14);

            m_box.Encrypt(readyBox, readyPlaintext, readyNonce);
            Array.Clear(readyPlaintext, 0, readyPlaintext.Length);

            Span <byte> ready = msg;

            ReadyLiteral.CopyTo(ready);

            //  Short nonce, prefixed by "CurveZMQREADY---"
            readyNonce.Slice(16).CopyTo(ready.Slice(6));

            m_nonce++;

            return(0);
        }
Exemple #3
0
        PullMsgResult ProduceInitiate(ref Msg msg)
        {
            int metadataLength = BasicPropertiesLength;

            byte[] metadataPlaintext = new byte[metadataLength];
            AddBasicProperties(metadataPlaintext);
            msg.InitPool(113 + 128 + metadataLength + Curve25519XSalsa20Poly1305.TagLength);

            Span <byte> vouchNonce     = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> vouchPlaintext = stackalloc byte[64];
            Span <byte> vouchBox       = stackalloc byte[Curve25519XSalsa20Poly1305.TagLength + 64];

            //  Create vouch = Box [C',S](C->S')
            m_cnPublicKey.CopyTo(vouchPlaintext);
            m_serverKey.CopyTo(vouchPlaintext.Slice(32));

            VouchNoncePrefix.CopyTo(vouchNonce);
            using var rng = RandomNumberGenerator.Create();
#if NETSTANDARD2_1
            rng.GetBytes(vouchNonce.Slice(8));
#else
            byte[] temp = new byte[16];
            rng.GetBytes(temp);
            temp.CopyTo(vouchNonce.Slice(8));
#endif

            using var box = new Curve25519XSalsa20Poly1305(m_secretKey, m_cnServerKey);
            box.Encrypt(vouchBox, vouchPlaintext, vouchNonce);

            Span <byte> initiate          = msg;
            Span <byte> initiateNonce     = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> initiatePlaintext = new byte[128 + metadataLength];
            Span <byte> initiateBox       = initiate.Slice(113);

            //  Create Box [C + vouch + metadata](C'->S')
            m_publicKey.CopyTo(initiatePlaintext);
            vouchNonce.Slice(8).CopyTo(initiatePlaintext.Slice(32));
            vouchBox.CopyTo(initiatePlaintext.Slice(48));
            metadataPlaintext.CopyTo(initiatePlaintext.Slice(48 + 80));
            Array.Clear(metadataPlaintext, 0, metadataPlaintext.Length);

            InitiatieNoncePrefix.CopyTo(initiateNonce);
            NetworkOrderBitsConverter.PutUInt64(m_nonce, initiateNonce.Slice(16));

            using var box2 = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_cnServerKey);
            box2.Encrypt(initiateBox, initiatePlaintext, initiateNonce);

            InitiateLiteral.CopyTo(initiate);

            //  Cookie provided by the server in the WELCOME command
            m_cnCookie.CopyTo(initiate.Slice(9, 96));

            //  Short nonce, prefixed by "CurveZMQINITIATE"
            initiateNonce.Slice(16).CopyTo(initiate.Slice(105));

            m_nonce++;

            return(PullMsgResult.Ok);
        }
Exemple #4
0
        /// <summary>
        /// Parses a metadata.
        /// Metadata consists of a list of properties consisting of
        /// name and value as size-specified strings.
        /// </summary>
        /// <returns>Returns true on success and false on error.</returns>
        protected bool ParseMetadata(Span <byte> source)
        {
            while (source.Length > 1)
            {
                int nameLength = source[0];
                source = source.Slice(NameLengthSize);
                if (source.Length < nameLength)
                {
                    break;
                }

                string name = SpanUtility.ToAscii(source.Slice(0, nameLength));
                source = source.Slice(nameLength);
                if (source.Length < ValueLengthSize)
                {
                    break;
                }

                int valueLength = NetworkOrderBitsConverter.ToInt32(source);
                source = source.Slice(ValueLengthSize);
                if (source.Length < valueLength)
                {
                    break;
                }

                byte[] value = new byte[valueLength];
                source.Slice(0, valueLength).CopyTo(value);
                source = source.Slice(valueLength);

                if (name == ZmtpPropertyIdentity && Options.RecvIdentity)
                {
                    PeerIdentity = value;
                }
                else if (name == ZmtpPropertySocketType)
                {
                    if (!CheckSocketType(Encoding.ASCII.GetString(value)))
                    {
                        return(false);
                    }
                }
                else
                {
                    if (!GetProperty(name, value, valueLength))
                    {
                        return(false);
                    }
                }
            }

            if (source.Length > 0)
            {
                return(false);
            }

            return(true);
        }
Exemple #5
0
        /// <inheritdoc/>
        public override DateTimeOffset?GetBlockPerceivedTime(HashDigest <SHA256> blockHash)
        {
            byte[] key = BlockKey(blockHash);
            if (_blockPerceptionDb.Get(key) is { } bytes)
            {
                long unixTimeMs = NetworkOrderBitsConverter.ToInt64(bytes);
                return(DateTimeOffset.FromUnixTimeMilliseconds(unixTimeMs));
            }

            return(null);
        }
Exemple #6
0
 /// <inheritdoc/>
 public override void SetBlockPerceivedTime(
     HashDigest <SHA256> blockHash,
     DateTimeOffset perceivedTime
     )
 {
     byte[] key = BlockKey(blockHash);
     _blockPerceptionDb.Put(
         key,
         NetworkOrderBitsConverter.GetBytes(perceivedTime.ToUnixTimeMilliseconds())
         );
 }
Exemple #7
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);
        }
Exemple #8
0
        private static byte[] GetMessage(int version, IValue extra)
        {
            byte[] msg = NetworkOrderBitsConverter.GetBytes(version);
            if (!(extra is null))
            {
                byte[] extraBytes    = _codec.Encode(extra);
                int    versionLength = msg.Length;
                Array.Resize(ref msg, versionLength + extraBytes.Length);
                extraBytes.CopyTo(msg, versionLength);
            }

            return(msg);
        }
        private static void RoundTripInt32(int num, params byte[] bytes)
        {
            byte[] buffer = NetworkOrderBitsConverter.GetBytes(num);

            Assert.AreEqual(4, buffer.Length);
            CollectionAssert.AreEqual(bytes, buffer);

            Assert.AreEqual(num, NetworkOrderBitsConverter.ToInt32(buffer));

            NetworkOrderBitsConverter.PutInt32(num, buffer);

            CollectionAssert.AreEqual(bytes, buffer);

            Assert.AreEqual(num, NetworkOrderBitsConverter.ToInt32(buffer));
        }
        private static void RoundTripInt16(short num, params byte[] bytes)
        {
            byte[] buffer = NetworkOrderBitsConverter.GetBytes(num);

            Assert.Equal(2, buffer.Length);
            Assert.Equal(bytes, buffer);

            Assert.Equal(num, NetworkOrderBitsConverter.ToInt16(buffer));

            NetworkOrderBitsConverter.PutInt16(num, buffer);

            Assert.Equal(bytes, buffer);

            Assert.Equal(num, NetworkOrderBitsConverter.ToInt16(buffer));
        }
        public void TrySignalTest()
        {
            var socket = new MockOutgoingSocket((ref Msg msg, TimeSpan timeout, bool more) =>
            {
                Assert.Equal(TimeSpan.Zero, timeout);
                Assert.Equal(8, msg.Data.Length);

                var value = NetworkOrderBitsConverter.ToInt64(msg.Data);

                Assert.Equal(0x7766554433221100L, value);

                Assert.False(more);
                return(true);
            });

            Assert.True(socket.TrySignalOK());
        }
        public void SignalTest()
        {
            OutgoingSocketMock socket = new OutgoingSocketMock((ref Msg msg, TimeSpan timeout, bool more) =>
            {
                Assert.AreEqual(SendReceiveConstants.InfiniteTimeout, timeout);
                Assert.AreEqual(8, msg.Data.Length);

                long value = NetworkOrderBitsConverter.ToInt64(msg.Data);

                Assert.AreEqual(0x7766554433221100L, value);

                Assert.IsFalse(more);
                return(true);
            });

            socket.SignalOK();
        }
        public void TrySignalFailedTest()
        {
            OutgoingSocketMock socket = new OutgoingSocketMock((ref Msg msg, TimeSpan timeout, bool more) =>
            {
                Assert.AreEqual(TimeSpan.Zero, timeout);
                Assert.AreEqual(8, msg.Data.Length);

                long value = NetworkOrderBitsConverter.ToInt64(msg.Data);

                Assert.AreEqual(0x7766554433221100L, value);

                Assert.IsFalse(more);
                return(false);
            });

            Assert.IsFalse(socket.TrySignalOK());
        }
Exemple #14
0
 /// <inheritdoc cref="BaseStore.SetBlockPerceivedTime(BlockHash, DateTimeOffset)"/>
 public override void SetBlockPerceivedTime(
     BlockHash blockHash,
     DateTimeOffset perceivedTime
     )
 {
     try
     {
         byte[] key = BlockKey(blockHash);
         _blockPerceptionDb.Put(
             key,
             NetworkOrderBitsConverter.GetBytes(perceivedTime.ToUnixTimeMilliseconds())
             );
     }
     catch (Exception e)
     {
         LogUnexpectedException(nameof(SetBlockPerceivedTime), e);
     }
 }
Exemple #15
0
        /// <inheritdoc cref="BaseStore.GetBlockPerceivedTime(BlockHash)"/>
        public override DateTimeOffset?GetBlockPerceivedTime(BlockHash blockHash)
        {
            try
            {
                byte[] key = BlockKey(blockHash);
                if (_blockPerceptionDb.Get(key) is { } bytes)
                {
                    long unixTimeMs = NetworkOrderBitsConverter.ToInt64(bytes);
                    return(DateTimeOffset.FromUnixTimeMilliseconds(unixTimeMs));
                }
            }
            catch (Exception e)
            {
                LogUnexpectedException(nameof(GetBlockPerceivedTime), e);
            }

            return(null);
        }
        public void TestInt64()
        {
            byte[] buffer = NetworkOrderBitsConverter.GetBytes(1);

            Assert.AreEqual(1, buffer[3]);
            Assert.AreEqual(0, buffer[0]);

            long num = NetworkOrderBitsConverter.ToInt32(buffer);

            Assert.AreEqual(1, num);

            NetworkOrderBitsConverter.PutInt32(16777216, buffer, 0);

            Assert.AreEqual(1, buffer[0]);
            Assert.AreEqual(0, buffer[3]);

            num = NetworkOrderBitsConverter.ToInt32(buffer);

            Assert.AreEqual(16777216, num);
        }
        public void TestInt32()
        {
            byte[] buffer = NetworkOrderBitsConverter.GetBytes((long)1);

            Assert.AreEqual(buffer[7], 1);
            Assert.AreEqual(0, buffer[0]);

            long num = NetworkOrderBitsConverter.ToInt64(buffer);

            Assert.AreEqual(1, num);

            NetworkOrderBitsConverter.PutInt64(72057594037927936, buffer, 0);

            Assert.AreEqual(1, buffer[0]);
            Assert.AreEqual(0, buffer[7]);

            num = NetworkOrderBitsConverter.ToInt64(buffer);

            Assert.AreEqual(72057594037927936, num);
        }
        public void Constructor()
        {
            // Generate fixture block hashes looks like 0x000...1, 0x000...2, 0x000...3, and so on,
            // for the sake of easier debugging.
            ImmutableArray <HashDigest <SHA256> > blocks = Enumerable.Range(0, 0x10).Select(i =>
            {
                byte[] bytes = NetworkOrderBitsConverter.GetBytes(i);
                var buffer   = new byte[HashDigest <SHA256> .Size];
                bytes.CopyTo(buffer, buffer.Length - bytes.Length);
                return(new HashDigest <SHA256>(buffer));
            }).ToImmutableArray();

            var locator = new BlockLocator(
                indexBlockHash: idx => blocks[(int)(idx < 0 ? blocks.Length + idx : idx)],
                indexByBlockHash: hash => blocks.IndexOf(hash),
                sampleAfter: 5
                );

            foreach (HashDigest <SHA256> hash in locator)
            {
                _output.WriteLine(hash.ToString());
            }

            Assert.Equal(
                new[]
            {
                blocks[0xf],
                blocks[0xe],
                blocks[0xd],
                blocks[0xc],
                blocks[0xb],
                blocks[0xa],
                blocks[0x8],
                blocks[0x4],
                blocks[0x0],
            },
                locator
                );
        }
Exemple #19
0
        public override PullMsgResult Encode(ref Msg msg)
        {
            Span <byte> messageNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];

            m_encodeNoncePrefix.CopyTo(messageNonce);
            NetworkOrderBitsConverter.PutUInt64(m_nonce, messageNonce.Slice(16));

            byte flags = 0;

            if (msg.HasMore)
            {
                flags |= 0x01;
            }
            if (msg.HasCommand)
            {
                flags |= 0x02;
            }

            Msg plaintext = new Msg();

            plaintext.InitPool(msg.Size + 1);
            plaintext[0] = flags;
            msg.CopyTo(plaintext.Slice(1));

            msg.Close();
            msg.InitPool(16 + Curve25519XSalsa20Poly1305.TagLength + plaintext.Size);

            Assumes.NotNull(m_box);

            m_box.Encrypt(msg.Slice(16), plaintext, messageNonce);
            plaintext.Close();

            MessageLiteral.CopyTo(msg);
            NetworkOrderBitsConverter.PutUInt64(m_nonce, msg.Slice(8));

            m_nonce++;
            return(PullMsgResult.Ok);
        }
Exemple #20
0
        PullMsgResult ProduceHello(ref Msg msg)
        {
            msg.InitPool(200);

            Span <byte> helloNonce     = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> helloPlaintext = stackalloc byte[64];
            Span <byte> helloBox       = msg.Slice(120);

            // Prepare the full nonce
            HelloNoncePrefix.CopyTo(helloNonce);
            NetworkOrderBitsConverter.PutUInt64(m_nonce, helloNonce.Slice(16));

            // Create Box [64 * %x0](C'->S)
            using var box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_serverKey);
            box.Encrypt(helloBox, helloPlaintext, helloNonce);

            Span <byte> hello = msg;

            HelloLiteral.CopyTo(hello);

            //  CurveZMQ major and minor version numbers
            hello[6] = 1;
            hello[7] = 0;

            // 8-80 are left zeros for anti-amplification padding

            //  Client public connection key
            m_cnPublicKey.CopyTo(hello.Slice(80));

            //  Short nonce, prefixed by "CurveZMQHELLO---"
            helloNonce.Slice(16).CopyTo(hello.Slice(112));

            m_nonce++;

            return(PullMsgResult.Ok);
        }
Exemple #21
0
        protected int AddProperty(byte[] output, int outputOffset, string name, byte[] value)
        {
            if (name.Length > 255)
            {
                throw new ArgumentException("property name length exceed maximum size");
            }

            int totalLength = GetPropertyLength(name, value.Length);

            if (totalLength > (output.Length - outputOffset))
            {
                throw new Exception("totalLength of property exceed maximum size");
            }

            output[outputOffset] = (byte)name.Length;
            outputOffset        += NameLengthSize;
            System.Text.Encoding.ASCII.GetBytes(name, 0, name.Length, output, outputOffset);
            outputOffset += name.Length;
            NetworkOrderBitsConverter.PutInt32(value.Length, output, outputOffset);
            outputOffset += ValueLengthSize;
            Buffer.BlockCopy(value, 0, output, outputOffset, value.Length);

            return(totalLength);
        }
Exemple #22
0
        protected int AddProperty(Span <byte> output, string name, byte[] value)
        {
            if (name.Length > 255)
            {
                throw new ArgumentException("property name length exceed maximum size");
            }

            int totalLength = GetPropertyLength(name, value.Length);

            if (totalLength > output.Length)
            {
                throw new Exception("totalLength of property exceed maximum size");
            }

            output[0] = (byte)name.Length;
            output    = output.Slice(NameLengthSize);
            System.Text.Encoding.ASCII.GetBytes(name, output);
            output = output.Slice(name.Length);
            NetworkOrderBitsConverter.PutInt32(value.Length, output);
            output = output.Slice(ValueLengthSize);
            value.CopyTo(output);

            return(totalLength);
        }
Exemple #23
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);
        }
Exemple #24
0
        /// <summary>
        /// Parses a metadata.
        /// Metadata consists of a list of properties consisting of
        /// name and value as size-specified strings.
        /// </summary>
        /// <returns>Returns true on success and false on error.</returns>
        protected bool ParseMetadata(byte[] source, int offset, int length)
        {
            int bytesLeft = length;

            while (bytesLeft > 1)
            {
                int nameLength = source[offset];
                offset    += NameLengthSize;
                bytesLeft -= NameLengthSize;
                if (bytesLeft < nameLength)
                {
                    break;
                }

                string name = Encoding.ASCII.GetString(source, offset, nameLength);
                offset    += nameLength;
                bytesLeft -= nameLength;
                if (bytesLeft < ValueLengthSize)
                {
                    break;
                }

                int valueLength = NetworkOrderBitsConverter.ToInt32(source, offset);
                offset    += ValueLengthSize;
                bytesLeft -= ValueLengthSize;
                if (bytesLeft < valueLength)
                {
                    break;
                }

                byte[] value = new byte[valueLength];
                Buffer.BlockCopy(source, offset, value, 0, valueLength);
                offset    += valueLength;
                bytesLeft -= valueLength;

                if (name == ZmtpPropertyIdentity && Options.RecvIdentity)
                {
                    PeerIdentity = value;
                }
                else if (name == ZmtpPropertySocketType)
                {
                    if (!CheckSocketType(Encoding.ASCII.GetString(value)))
                    {
                        return(false);
                    }
                }
                else
                {
                    if (!GetProperty(name, value, valueLength))
                    {
                        return(false);
                    }
                }
            }

            if (bytesLeft > 0)
            {
                return(false);
            }

            return(true);
        }
Exemple #25
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);

            Assumes.NotNull(m_box);

            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);
        }