/* In response, the server sends a "server-first-message" containing the
         * user's iteration count i and the user's salt, and appends its own
         * nonce to the client-specified one. */
        private static string CreateSaslStartReply(
            string clientSaslStart,
            string serverNonce,
            string serverSalt,
            int iterationCount)
        {
            // strip expected GS2 header of "n,," before parsing map
            var clientNonce = SaslMapParser.Parse(clientSaslStart.Substring(3))['r'];

            return($"r={clientNonce}{serverNonce},s={serverSalt},i={iterationCount}");
        }
            public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer)
            {
                var encoding        = Utf8Encodings.Strict;
                var map             = SaslMapParser.Parse(encoding.GetString(bytesReceivedFromServer));
                var serverSignature = Convert.FromBase64String(map['v']);

                if (!ConstantTimeEquals(_serverSignature64, serverSignature))
                {
                    throw new MongoAuthenticationException(conversation.ConnectionId, message: "Server signature was invalid.");
                }

                return(new CompletedStep());
            }
Beispiel #3
0
            public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer)
            {
                var encoding           = Utf8Encodings.Strict;
                var serverFirstMessage = encoding.GetString(bytesReceivedFromServer);
                var map = SaslMapParser.Parse(serverFirstMessage);

                var r = map['r'];

                if (!r.StartsWith(_rPrefix, StringComparison.Ordinal))
                {
                    throw new MongoAuthenticationException(conversation.ConnectionId, message: "Server sent an invalid nonce.");
                }
                var s = map['s'];
                var i = map['i'];

                const string gs2Header      = "n,,";
                var          channelBinding = "c=" + Convert.ToBase64String(encoding.GetBytes(gs2Header));
                var          nonce          = "r=" + r;
                var          clientFinalMessageWithoutProof = channelBinding + "," + nonce;

                var salt       = Convert.FromBase64String(map['s']);
                var iterations = int.Parse(map['i']);

                byte[] clientKey;
                byte[] serverKey;

                var cacheKey = new ScramCacheKey(_credential.SaslPreppedPassword, salt, iterations);

                if (_cache.TryGet(cacheKey, out var cacheEntry))
                {
                    clientKey = cacheEntry.ClientKey;
                    serverKey = cacheEntry.ServerKey;
                }
                else
                {
                    var saltedPassword = _hi(_credential, salt, iterations);
                    clientKey = _hmac(encoding, saltedPassword, "Client Key");
                    serverKey = _hmac(encoding, saltedPassword, "Server Key");
                    _cache.Add(cacheKey, new ScramCacheEntry(clientKey, serverKey));
                }

                var storedKey          = _h(clientKey);
                var authMessage        = _clientFirstMessageBare + "," + serverFirstMessage + "," + clientFinalMessageWithoutProof;
                var clientSignature    = _hmac(encoding, storedKey, authMessage);
                var clientProof        = XOR(clientKey, clientSignature);
                var serverSignature    = _hmac(encoding, serverKey, authMessage);
                var proof              = "p=" + Convert.ToBase64String(clientProof);
                var clientFinalMessage = clientFinalMessageWithoutProof + "," + proof;

                return(new ClientLast(encoding.GetBytes(clientFinalMessage), serverSignature));
            }
            public ISaslStep Transition(SaslConversation conversation, byte[] bytesReceivedFromServer)
            {
                var encoding           = Utf8Encodings.Strict;
                var serverFirstMessage = encoding.GetString(bytesReceivedFromServer);
                var map = SaslMapParser.Parse(serverFirstMessage);

                var r = map['r'];

                if (!r.StartsWith(_rPrefix))
                {
                    throw new MongoAuthenticationException(conversation.ConnectionId, message: "Server sent an invalid nonce.");
                }
                var s = map['s'];
                var i = map['i'];

                const string gs2Header      = "n,,";
                var          channelBinding = "c=" + Convert.ToBase64String(encoding.GetBytes(gs2Header));
                var          nonce          = "r=" + r;
                var          clientFinalMessageWithoutProof = channelBinding + "," + nonce;

                var saltedPassword = _hi(
                    _credential,
                    Convert.FromBase64String(s),
                    int.Parse(i));

                var clientKey       = _hmac(encoding, saltedPassword, "Client Key");
                var storedKey       = _h(clientKey);
                var authMessage     = _clientFirstMessageBare + "," + serverFirstMessage + "," + clientFinalMessageWithoutProof;
                var clientSignature = _hmac(encoding, storedKey, authMessage);
                var clientProof     = XOR(clientKey, clientSignature);
                var serverKey       = _hmac(encoding, saltedPassword, "Server Key");
                var serverSignature = _hmac(encoding, serverKey, authMessage);

                var proof = "p=" + Convert.ToBase64String(clientProof);
                var clientFinalMessage = clientFinalMessageWithoutProof + "," + proof;

                return(new ClientLast(encoding.GetBytes(clientFinalMessage), serverSignature));
            }