Exemple #1
0
        PullMsgResult ProduceWelcome(ref Msg msg)
        {
            Span <byte> cookieNonce      = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> cookiePlaintext  = stackalloc byte[64];
            Span <byte> cookieCiphertext = stackalloc byte[64 + XSalsa20Poly1305.TagLength];

            //  Create full nonce for encryption
            //  8-byte prefix plus 16-byte random nonce
            CookieNoncePrefix.CopyTo(cookieNonce);
            using var rng = RandomNumberGenerator.Create();
#if NETSTANDARD2_1
            rng.GetBytes(cookieNonce.Slice(8));
#else
            byte[] temp = new byte[16];
            rng.GetBytes(temp);
            temp.CopyTo(cookieNonce.Slice(8));
#endif

            // Generate cookie = Box [C' + s'](t)
            m_cnClientKey.CopyTo(cookiePlaintext);
            m_cnSecretKey.CopyTo(cookiePlaintext.Slice(32));

            // Generate fresh cookie key
            rng.GetBytes(m_cookieKey);

            // Encrypt using symmetric cookie key
            using var secretBox = new XSalsa20Poly1305(m_cookieKey);
            secretBox.Encrypt(cookieCiphertext, cookiePlaintext, cookieNonce);
            cookiePlaintext.Clear();

            Span <byte> welcomeNonce      = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> welcomePlaintext  = stackalloc byte[128];
            Span <byte> welcomeCiphertext = stackalloc byte[128 + Curve25519XSalsa20Poly1305.TagLength];

            //  Create full nonce for encryption
            //  8-byte prefix plus 16-byte random nonce
            WelcomeNoncePrefix.CopyTo(welcomeNonce);
#if NETSTANDARD2_1
            rng.GetBytes(welcomeNonce.Slice(8));
#else
            rng.GetBytes(temp);
            temp.CopyTo(welcomeNonce.Slice(8));
#endif

            // Create 144-byte Box [S' + cookie](S->C')
            m_cnPublicKey.CopyTo(welcomePlaintext);
            cookieNonce.Slice(8).CopyTo(welcomePlaintext.Slice(32));
            cookieCiphertext.CopyTo(welcomePlaintext.Slice(48));
            using var box = new Curve25519XSalsa20Poly1305(m_secretKey, m_cnClientKey);
            box.Encrypt(welcomeCiphertext, welcomePlaintext, welcomeNonce);
            welcomePlaintext.Clear();

            msg.InitPool(168); // TODO: we can save some allocation here by allocating this earlier
            Span <byte> welcome = msg;
            WelcomeLiteral.CopyTo(welcome);
            welcomeNonce.Slice(8, 16).CopyTo(welcome.Slice(8));
            welcomeCiphertext.CopyTo(welcome.Slice(24));

            return(PullMsgResult.Ok);
        }
Exemple #2
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 #3
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 #4
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);

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