Exemple #1
0
 def testUnit():
     clientFinalMessageBare = "c=biws,r=" + "fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j"
     saltedPassword = pbkdf2_hmac("sha1", saslprep(unicode("pencil")), b64decode("QSXCR+Q6sek8bf92"), 4096)
     print saltedPassword.encode("hex")
  
     clientKey = hmac.new(saltedPassword, "Client Key", sha1)
     print clientKey.hexdigest()
  
     storedKey = sha1(clientKey.digest())
     print storedKey.hexdigest()
  
     authMessage = "n=user,r=fyko+d2lbbFgONRv9qkxdawL,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096,c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j"
     clientSignature = hmac.new(storedKey.digest(), authMessage, sha1)
     print clientSignature.hexdigest()
  
     clientProof = _strxor(clientKey.digest(), clientSignature.digest())
     print clientProof.encode("hex")
  
     serverKey = hmac.new(saltedPassword, "Server Key", sha1)
     print serverKey.hexdigest()
  
     serverSignature = hmac.new(serverKey.digest(), authMessage, sha1)
     print serverSignature.hexdigest()
  
     clientFinalMessage = clientFinalMessageBare + ",p=" + b64encode(clientProof)
     print clientFinalMessage
  
     serverFinalMessage = "v=" + b64encode(serverSignature.digest())
     print serverFinalMessage
Exemple #2
0
    def derive_digest(cls, password, salt, rounds, alg):
        """helper to create SaltedPassword digest for SCRAM.

        This performs the step in the SCRAM protocol described as::

            SaltedPassword  := Hi(Normalize(password), salt, i)

        :type password: unicode or utf-8 bytes
        :arg password: password to run through digest

        :type salt: bytes
        :arg salt: raw salt data

        :type rounds: int
        :arg rounds: number of iterations.

        :type alg: str
        :arg alg: name of digest to use (e.g. ``"sha-1"``).

        :returns:
            raw bytes of ``SaltedPassword``
        """
        if isinstance(password, bytes):
            password = password.decode("utf-8")
        # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8,
        #       and handle normalizing alg name.
        return pbkdf2_hmac(alg, saslprep(password), salt, rounds)
Exemple #3
0
    def derive_digest(cls, password, salt, rounds, alg):
        """helper to create SaltedPassword digest for SCRAM.

        This performs the step in the SCRAM protocol described as::

            SaltedPassword  := Hi(Normalize(password), salt, i)

        :type password: unicode or utf-8 bytes
        :arg password: password to run through digest

        :type salt: bytes
        :arg salt: raw salt data

        :type rounds: int
        :arg rounds: number of iterations.

        :type alg: str
        :arg alg: name of digest to use (e.g. ``"sha-1"``).

        :returns:
            raw bytes of ``SaltedPassword``
        """
        if isinstance(password, bytes):
            password = password.decode("utf-8")
        password = saslprep(password).encode("utf-8")
        if not isinstance(salt, bytes):
            raise TypeError("salt must be bytes")
        if rounds < 1:
            raise ValueError("rounds must be >= 1")
        alg = norm_hash_name(alg, "hashlib")
        return pbkdf2(password, salt, rounds, None, "hmac-" + alg)
Exemple #4
0
    def derive_digest(cls, password, salt, rounds, alg):
        """helper to create SaltedPassword digest for SCRAM.

        This performs the step in the SCRAM protocol described as::

            SaltedPassword  := Hi(Normalize(password), salt, i)

        :type password: unicode or utf-8 bytes
        :arg password: password to run through digest

        :type salt: bytes
        :arg salt: raw salt data

        :type rounds: int
        :arg rounds: number of iterations.

        :type alg: str
        :arg alg: name of digest to use (e.g. ``"sha-1"``).

        :returns:
            raw bytes of ``SaltedPassword``
        """
        if isinstance(password, bytes):
            password = password.decode("utf-8")
        password = saslprep(password).encode("utf-8")
        if not isinstance(salt, bytes):
            raise TypeError("salt must be bytes")
        if rounds < 1:
            raise ValueError("rounds must be >= 1")
        alg = norm_hash_name(alg, "hashlib")
        return pbkdf2(password, salt, rounds, None, "hmac-" + alg)
Exemple #5
0
    def _create_admin(self):
        admin_data = {
            "username": "******",
            "password": pbkdf2_sha256.encrypt(saslprep("admin")),
            "admin": True,
            "preferred_channel": "email",
            "channels": {
                "email": {
                    "address": "*****@*****.**"
                },
                "facebook": {
                    "user_id": "user"
                },
                "telegram": {
                    "user_id": "user"
                },
                "irc": {
                    "nickname": "user",
                    "network": "user"
                },
                "slack": {
                    "channel": "user",
                    "username": "******"
                }
            }
        }

        cursor = self.user_collection.find({'username': '******'})
        if cursor.count() == 0:
            self.user_collection.insert_one(admin_data)
            return
        else:
            return
Exemple #6
0
    def post(self):
        """ Post a new user to the database. Make a dictionary to pass to the db_handler."""

        try:
            validate(request.json, user_schema)
        except Exception as e:
            error_msg = str(e).split("\n")
            return {"msg": "error with input data:" + str(error_msg[0])}, 400

        user_data = {}
        data = request.get_json()
        user_data["username"] = data.get("username")
        user_data["password"] = pbkdf2_sha256.encrypt(saslprep(
            data.get("password")),
                                                      rounds=200000,
                                                      salt_size=16)
        user_data["preferred_channel"] = data.get("preferred_channel")
        user_data["channels"] = data.get("channels")
        user_data["admin"] = False

        response = self.db_handler.create_user(user_data)

        if response == "used":
            return {'msg': "Username already in use"}, 400
        elif response is None:
            return {"msg": "Error during data handling"}
        else:
            return {"msg": "User created", "user_id": response}, 200
Exemple #7
0
    def create_authentication(password, salt):
        hash_data = argon2.low_level.hash_secret(
            secret=saslprep(password).encode('ascii'),
            salt=salt,
            time_cost=4096,
            memory_cost=512,
            parallelism=1,
            hash_len=32,
            type=argon2.low_level.Type.ID,
            version=0x13,
        )

        _, tag, v, params, _, salted_password = hash_data.decode('ascii').split('$')
        assert tag == 'argon2id'
        assert v == 'v=19'  # argon's version 1.3 is represented as 0x13, which is 19 decimal...
        params = {
            k: v
            for k, v in
            [x.split('=') for x in params.split(',')]
        }

        salted_password = salted_password.encode('ascii')
        client_key = hmac.new(salted_password, b"Client Key", hashlib.sha256).digest()
        stored_key = hashlib.new('sha256', client_key).digest()
        server_key = hmac.new(salted_password, b"Server Key", hashlib.sha256).digest()

        return {
            'memory': int(params['m']),
            'kdf': 'argon2id-13',
            'iterations': int(params['t']),
            'salt': binascii.b2a_hex(salt).decode('ascii'),
            'storedKey': binascii.b2a_hex(stored_key).decode('ascii'),
            'serverKey': binascii.b2a_hex(server_key).decode('ascii')
        }
Exemple #8
0
    def derive_digest(cls, password, salt, rounds, alg):
        """helper to create SaltedPassword digest for SCRAM.

        This performs the step in the SCRAM protocol described as::

            SaltedPassword  := Hi(Normalize(password), salt, i)

        :type password: unicode or utf-8 bytes
        :arg password: password to run through digest

        :type salt: bytes
        :arg salt: raw salt data

        :type rounds: int
        :arg rounds: number of iterations.

        :type alg: str
        :arg alg: name of digest to use (e.g. ``"sha-1"``).

        :returns:
            raw bytes of ``SaltedPassword``
        """
        if isinstance(password, bytes):
            password = password.decode("utf-8")
        # NOTE: pbkdf2_hmac() will encode secret & salt using utf-8,
        #       and handle normalizing alg name.
        return pbkdf2_hmac(alg, saslprep(password), salt, rounds)
Exemple #9
0
    def on_challenge(self, session, challenge):
        assert challenge.method == u"scram"
        assert self._client_nonce is not None
        required_args = ['nonce', 'kdf', 'salt', 'iterations']
        optional_args = ['memory', 'channel_binding']
        for k in required_args:
            if k not in challenge.extra:
                raise RuntimeError("WAMP-SCRAM challenge option '{}' is "
                                   " required but not specified".format(k))
        for k in challenge.extra:
            if k not in optional_args + required_args:
                raise RuntimeError(
                    "WAMP-SCRAM challenge has unknown attribute '{}'".format(
                        k))

        channel_binding = challenge.extra.get(u'channel_binding', u'')
        server_nonce = challenge.extra[u'nonce'].encode('ascii')  # base64
        salt = challenge.extra[u'salt']  # base64
        iterations = int(challenge.extra[u'iterations'])
        memory = int(challenge.extra.get(u'memory', -1))
        password = self._args['password'].encode('utf8')  # supplied by user
        authid = saslprep(self._args['authid'])
        algorithm = challenge.extra[u'kdf']
        client_nonce = self._client_nonce

        self._auth_message = (
            u"{client_first_bare},{server_first},{client_final_no_proof}".
            format(
                client_first_bare=u"n={},r={}".format(authid, client_nonce),
                server_first=u"r={},s={},i={}".format(
                    server_nonce.decode('ascii'), salt.decode('ascii'),
                    iterations),
                client_final_no_proof=u"c={},r={}".format(
                    channel_binding, server_nonce.decode('ascii')),
            ).encode('ascii'))

        if algorithm == u'argon2id-13':
            if memory == -1:
                raise ValueError(
                    "WAMP-SCRAM 'argon2id-13' challenge requires 'memory' parameter"
                )
            self._salted_password = _hash_argon2id13_secret(
                password, salt, iterations, memory)
        elif algorithm == u'pbkdf2':
            self._salted_password = _hash_pbkdf2_secret(
                password, salt, iterations)
        else:
            raise RuntimeError(
                "WAMP-SCRAM specified unknown KDF '{}'".format(algorithm))

        client_key = hmac.new(self._salted_password, b"Client Key",
                              hashlib.sha256).digest()
        stored_key = hashlib.new('sha256', client_key).digest()

        client_signature = hmac.new(stored_key, self._auth_message,
                                    hashlib.sha256).digest()
        client_proof = xor_array(client_key, client_signature)

        return base64.b64encode(client_proof)
    def on_challenge(self, session, challenge):
        assert challenge.method == u"scram"
        assert self._client_nonce is not None
        required_args = ['nonce', 'kdf', 'salt', 'iterations']
        optional_args = ['memory', 'channel_binding']
        for k in required_args:
            if k not in challenge.extra:
                raise RuntimeError(
                    "WAMP-SCRAM challenge option '{}' is "
                    " required but not specified".format(k)
                )
        for k in challenge.extra:
            if k not in optional_args + required_args:
                raise RuntimeError(
                    "WAMP-SCRAM challenge has unknown attribute '{}'".format(k)
                )

        channel_binding = challenge.extra.get(u'channel_binding', u'')
        server_nonce = challenge.extra[u'nonce'].encode('ascii')  # base64
        salt = challenge.extra[u'salt']  # base64
        iterations = int(challenge.extra[u'iterations'])
        memory = int(challenge.extra.get(u'memory', -1))
        password = self._args['password'].encode('utf8')  # supplied by user
        authid = saslprep(self._args['authid'])
        algorithm = challenge.extra[u'kdf']
        client_nonce = self._client_nonce

        self._auth_message = (
            u"{client_first_bare},{server_first},{client_final_no_proof}".format(
                client_first_bare=u"n={},r={}".format(authid, client_nonce),
                server_first=u"r={},s={},i={}".format(server_nonce.decode('ascii'), salt.decode('ascii'), iterations),
                client_final_no_proof=u"c={},r={}".format(channel_binding, server_nonce.decode('ascii')),
            ).encode('ascii')
        )

        if algorithm == u'argon2id-13':
            if memory == -1:
                raise ValueError(
                    "WAMP-SCRAM 'argon2id-13' challenge requires 'memory' parameter"
                )
            self._salted_password = _hash_argon2id13_secret(password, salt, iterations, memory)
        elif algorithm == u'pbkdf2':
            self._salted_password = _hash_pbkdf2_secret(password, salt, iterations)
        else:
            raise RuntimeError(
                "WAMP-SCRAM specified unknown KDF '{}'".format(algorithm)
            )

        client_key = hmac.new(self._salted_password, b"Client Key", hashlib.sha256).digest()
        stored_key = hashlib.new('sha256', client_key).digest()

        client_signature = hmac.new(stored_key, self._auth_message, hashlib.sha256).digest()
        client_proof = xor_array(client_key, client_signature)

        return base64.b64encode(client_proof)
Exemple #11
0
def mysaslprep(pwd):
    try:
        if type(pwd) is not str:
            pwd = pwd.decode('utf8')
        pwd = saslprep(pwd)
    except (UnicodeDecodeError, ValueError):
        pass
    if type(pwd) is str:
        return pwd.encode('utf8')
    else:
        return pwd
Exemple #12
0
    def on_connect(self):
        auth_methods = [u'scram']
        auth_role = u'user'
        authid = u'{}'.format(self.component_config.session.username)
        password = u'{}'.format(self.component_config.session.password)
        self.authenticator = create_authenticator(AuthScram.name,
                                                  authid=authid,
                                                  password=saslprep(password))

        self.join(self.config.realm,
                  authmethods=auth_methods,
                  authid=authid,
                  authrole=auth_role,
                  authextra=self.authenticator.authextra)
Exemple #13
0
    def authenticate(self, signed_message):
        """
        Verify the signed message sent by the client.

        :param signed_message: the base64-encoded result "ClientProof"
            from the SCRAM protocol
        """

        channel_binding = ""
        client_nonce = base64.b64encode(self._client_nonce).decode('ascii')
        server_nonce = base64.b64encode(self._server_nonce).decode('ascii')
        salt = base64.b64encode(self._salt).decode('ascii')
        auth_message = (
            "{client_first_bare},{server_first},{client_final_no_proof}".
            format(
                client_first_bare="n={},r={}".format(saslprep(self._authid),
                                                     client_nonce),
                server_first="r={},s={},i={}".format(server_nonce, salt,
                                                     self._iterations),
                client_final_no_proof="c={},r={}".format(
                    channel_binding, server_nonce),
            ))

        received_client_proof = base64.b64decode(signed_message)

        client_signature = hmac.new(self._stored_key,
                                    auth_message.encode('ascii'),
                                    hashlib.sha256).digest()
        recovered_client_key = util.xor(client_signature,
                                        received_client_proof)
        recovered_stored_key = hashlib.new('sha256',
                                           recovered_client_key).digest()

        # if we adjust self._authextra before _accept() it gets sent
        # back to the client
        server_signature = hmac.new(self._server_key,
                                    auth_message.encode('ascii'),
                                    hashlib.sha256).digest()
        if self._authextra is None:
            self._authextra = {}
        self._authextra['scram_server_signature'] = base64.b64encode(
            server_signature).decode('ascii')

        if hmac.compare_digest(recovered_stored_key, self._stored_key):
            return self._accept()

        self.log.error("SCRAM authentication failed for '{authid}'",
                       authid=self._authid)
        return types.Deny(message='SCRAM authentication failed')
Exemple #14
0
    def generate(cls,
                 owner: User,
                 username: str,
                 password: str,
                 alg: SCRAMAlgorithm,
                 salt: Optional[bytes] = None,
                 iterations: int = 4096):
        """ Generate SCRAM credentials, hashing the given password using the given algorithm.

        If salt is unset, a random one is used.

        If iterations is unset, 4096 (the Kafka default) is used.
        """
        # Set number of rounds:
        scram_hasher = scram.using(rounds=iterations)
        # Set salt:
        if salt is not None:
            scram_hasher = scram_hasher.using(salt=salt)
        # Set algorithm (sha-1 must always be in the algorithm list):
        scram_hasher = scram_hasher.using(f"sha-1,{alg.iana_name()}")
        # Run the hash, taking care to normalize the password
        scram_hash = scram_hasher.hash(saslprep(password))
        salt, _, hashed_pw = scram.extract_digest_info(scram_hash,
                                                       alg.iana_name())

        hash_func = alg.hash_function()
        server_key = hmac.new(hashed_pw, b"Server Key", hash_func).digest()
        client_key = hmac.new(hashed_pw, b"Client Key", hash_func).digest()
        stored_key = hash_func(client_key).digest()

        val = cls(
            owner=owner,
            username=username,
            algorithm=alg,
            salt=salt,
            server_key=server_key,
            stored_key=stored_key,
            iterations=iterations,
            string_encoding=cls.string_encode(salt, stored_key, server_key,
                                              iterations),
        )
        return val
Exemple #15
0
    def patch(self, user_id):

        try:
            validate(request.json, user_patch_schema)
        except Exception as e:
            error_msg = str(e).split("\n")
            return {"msg": "error with input data:" + str(error_msg[0])}, 400

        if self.check_authorization(user_id) is True:
            data = request.get_json()
            user_data = {}
            for key in data:
                if key == "admin" and self.check_admin(
                ) != True and data[key] not in [True, False]:
                    return {
                        "Error":
                        "Admin field should be True or False. Olnly admin can modify this value."
                    }, 400
                elif key == "username":
                    return {
                        "Error": "Not modified. Cannot modify username"
                    }, 400
                elif key == "preferred_channel":
                    if data[key] not in [
                            "email", "slack", "irc", "facebook", "telegram"
                    ]:
                        return {"Error": "Not modified. Channel unknown"}, 400
                if key == "password":
                    user_data[str(key)] = pbkdf2_sha256.encrypt(saslprep(
                        data["password"]),
                                                                rounds=200000,
                                                                salt_size=16)
                else:
                    user_data[str(key)] = data.get(key)
            response = self.db_handler.update_user(user_data, user_id)

            if response == 200:
                return {"msg": "modified"}, response
            else:
                return {"msg": "Not modified"}, response
        else:
            return {"msg": "Unauthorized"}, 401
Exemple #16
0
    def post(self):

        try:
            validate(request.json, login_schema)
        except Exception as e:
            error_msg = str(e).split("\n")
            return {"msg": "error with input data:" + str(error_msg[0])}, 400

        parser = reqparse.RequestParser()
        parser.add_argument("username", location="json")
        parser.add_argument("password", location="json")
        args = parser.parse_args()

        user = self.db_handler.get_user_name(args['username'])
        if user is None:
            return {"msg": "Authentication error"}, 401
        else:
            if pbkdf2_sha256.verify(saslprep(args["password"]),
                                    user["password"]):
                try:
                    access_token = create_access_token(
                        identity={
                            "username": user["username"],
                            "admin": user["admin"],
                            "_id": user["_id"]
                        })
                    refresh_token = create_refresh_token(
                        identity={
                            "username": user["username"],
                            "admin": user["admin"],
                            "_id": user["_id"]
                        })
                    resp = jsonify({'msg': 'logged in'})
                    set_access_cookies(resp, access_token)
                    set_refresh_cookies(resp, refresh_token)
                    return resp
                except Exception as e:
                    return {"msg": "Authentication error"}, 401
            else:
                return {"msg": "Authentication error"}, 401
Exemple #17
0
    def authenticate(self, signed_message):
        """
        Verify the signed message sent by the client.

        :param signed_message: the base64-encoded result "ClientProof"
            from the SCRAM protocol
        """

        channel_binding = ""
        client_nonce = base64.b64encode(self._client_nonce).decode('ascii')
        server_nonce = base64.b64encode(self._server_nonce).decode('ascii')
        salt = base64.b64encode(self._salt).decode('ascii')
        auth_message = (
            "{client_first_bare},{server_first},{client_final_no_proof}".format(
                client_first_bare="n={},r={}".format(saslprep(self._authid), client_nonce),
                server_first="r={},s={},i={}".format(server_nonce, salt, self._iterations),
                client_final_no_proof="c={},r={}".format(channel_binding, server_nonce),
            )
        )

        received_client_proof = base64.b64decode(signed_message)

        client_signature = hmac.new(self._stored_key, auth_message.encode('ascii'), hashlib.sha256).digest()
        recovered_client_key = util.xor(client_signature, received_client_proof)
        recovered_stored_key = hashlib.new('sha256', recovered_client_key).digest()

        # if we adjust self._authextra before _accept() it gets sent
        # back to the client
        server_signature = hmac.new(self._server_key, auth_message.encode('ascii'), hashlib.sha256).digest()
        if self._authextra is None:
            self._authextra = {}
        self._authextra['scram_server_signature'] = base64.b64encode(server_signature).decode('ascii')

        if hmac.compare_digest(recovered_stored_key, self._stored_key):
            return self._accept()

        self.log.error("SCRAM authentication failed for '{authid}'", authid=self._authid)
        return types.Deny(message=u'SCRAM authentication failed')
Exemple #18
0
 def checkPassword(passwd):
     clientFinalMessageBare = "c=biws,r=xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
     saltedPassword = pbkdf2_hmac("sha1", saslprep(unicode(passwd)), b64decode("yyyyyyyyyyyyyyyyy"), 4096)
     #print saltedPassword.encode("hex")
     clientKey = hmac.new(saltedPassword, "Client Key", sha1)
     #print clientKey.hexdigest()
     storedKey = sha1(clientKey.digest())
     #print storedKey.hexdigest()
     authMessage = "n=username,r=hydra,r=xxxxxxxxxxxxxxxxxxxxxxxxxxxx,s=yyyyyyyyyyyyyyyyy,i=4096,c=biws,r=xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
     clientSignature = hmac.new(storedKey.digest(), authMessage, sha1)
     #print clientSignature.hexdigest()
     clientProof = _strxor(clientKey.digest(), clientSignature.digest())
     #print clientProof.encode("hex")
     serverKey = hmac.new(saltedPassword, "Server Key", sha1)
     #print serverKey.hexdigest()
     serverSignature = hmac.new(serverKey.digest(), authMessage, sha1)
     #print serverSignature.hexdigest()
     clientFinalMessage = clientFinalMessageBare + ",p=" + b64encode(clientProof)
     #print clientFinalMessage
     serverFinalMessage = "v=" + b64encode(serverSignature.digest())
     if (serverFinalMessage == "v=base64_encoded_string"):
         return True
     else:
         return False
Exemple #19
0
    def on_challenge(self, session, challenge):
        assert challenge.method == u"scram"
        assert self._client_nonce is not None
        required_args = ['nonce', 'salt', 'cost']
        optional_args = ['memory', 'parallel', 'channel_binding']
        # probably want "algorithm" too, with either "argon2id-19" or
        # "pbkdf2" as values
        for k in required_args:
            if k not in challenge.extra:
                raise RuntimeError(
                    "WAMP-SCRAM challenge option '{}' is "
                    " required but not specified".format(k)
                )
        for k in challenge.extra:
            if k not in optional_args + required_args:
                raise RuntimeError(
                    "WAMP-SCRAM challenge has unknown attribute '{}'".format(k)
                )

        channel_binding = challenge.extra.get(u'channel_binding', u'')
        server_nonce = challenge.extra[u'nonce']  # base64
        salt = challenge.extra[u'salt']  # base64
        cost = int(challenge.extra[u'cost'])
        memory = int(challenge.extra.get(u'memory', 512))
        parallel = int(challenge.extra.get(u'parallel', 2))
        password = self._args['password'].encode('utf8')  # supplied by user
        authid = saslprep(self._args['authid'])
        client_nonce = self._client_nonce

        auth_message = (
            "{client_first_bare},{server_first},{client_final_no_proof}".format(
                client_first_bare="n={},r={}".format(authid, client_nonce),
                server_first="r={},s={},i={}".format(server_nonce, salt, cost),
                client_final_no_proof="c={},r={}".format(channel_binding, server_nonce),
            )
        )

        rawhash = hash_secret(
            secret=password,
            salt=base64.b64decode(salt),
            time_cost=cost,
            memory_cost=memory,
            parallelism=parallel,
            hash_len=16,  # another knob?
            type=Type.ID,
            version=19,
        )
        # spits out stuff like:
        # '$argon2i$v=19$m=512,t=2,p=2$5VtWOO3cGWYQHEMaYGbsfQ$AcmqasQgW/wI6wAHAMk4aQ'

        _, tag, ver, options, salt_data, hash_data = rawhash.split(b'$')
        salted_password = hash_data
        client_key = hmac.new(salted_password, b"Client Key", hashlib.sha256).digest()
        stored_key = hashlib.new('sha256', client_key).digest()

        client_signature = hmac.new(stored_key, auth_message.encode('ascii'), hashlib.sha256).digest()
        client_proof = xor_array(client_key, client_signature)

        def confirm_server_signature(session, details):
            """
            When the server is satisfied, it sends a 'WELCOME' message.
            This will cause the session to be set up and 'join' gets
            notified. Here, we check the server-signature thus
            authorizing the server -- if it fails we drop the
            connection.
            """
            alleged_server_sig = base64.b64decode(details.authextra['scram_server_signature'])
            server_key = hmac.new(salted_password, b"Server Key", hashlib.sha256).digest()
            server_signature = hmac.new(server_key, auth_message.encode('ascii'), hashlib.sha256).digest()
            if not hmac.compare_digest(server_signature, alleged_server_sig):
                session.log.error("Verification of server SCRAM signature failed")
                session.leave(
                    u"wamp.error.cannot_authenticate",
                    u"Verification of server signature failed",
                )
            else:
                session.log.info(
                    "Verification of server SCRAM signature successful"
                )
        session.on('join', confirm_server_signature)

        return base64.b64encode(client_proof)
Exemple #20
0
 def set_password(self, password):
     """throws ValueError if password violates RFC 4013"""
     global PWD_CONTEXT
     self.pwd_hash = PWD_CONTEXT.hash(saslprep(password))
Exemple #21
0
def generate_hash(user_password: str) -> str:
    """Generate a hashed version of the password."""
    return pbkdf2_sha256.hash(saslprep(user_password))
Exemple #22
0
print "password: "******"client Nonce: " + sys.argv[3]
print "server Nonce: " + sys.argv[4]
print "server salt: " + sys.argv[5]
print "iteration: " + sys.argv[6]
print "clientProof to test with: " + sys.argv[7]

username = sys.argv[1]
password = sys.argv[2]
clientNonce = sys.argv[3]
serverNonce = sys.argv[4]
serverSalt = sys.argv[5]
iteration = sys.argv[6]
clientProofToFound = sys.argv[7]

normalizedPassword = utils.saslprep(unicode(password))

clientInitMessage = "n=" + username + ",r=" + clientNonce

serverInitReply = "r=" + clientNonce + serverNonce + ",s=" + serverSalt + ",i=" + iteration

clientFinal = "c=biws,r=" + clientNonce + serverNonce

saltedPassword = pbkdf2_sha1.using(
    rounds=iteration,
    salt=serverSalt.decode("base64")).hash(normalizedPassword).split('$')[-1]

clientKey = hmac.new(utils.ab64_decode(saltedPassword), "Client Key",
                     hashlib.sha1)

storedKey = hashlib.sha1(clientKey.digest())
Exemple #23
0
def _client_first_message_bare(username, c_nonce):
    return ','.join(('n=' + saslprep(username), 'r=' + c_nonce))