Example #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);
        }
Example #2
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);
        }