Пример #1
0
def generate_hash_and_salt(password: bytes) -> (bytes, bytes):
    """ Generates a hash and salt that will match for a given input string.
        Input is anticipated to be any arbitrary string."""
    salt = encode_base64(urandom(16))
    password_hashed = encode_base64(
        pbkdf2('sha1', password, salt, iterations=ITERATIONS, dklen=32))
    return password_hashed, salt
Пример #2
0
def generate_user_hash_and_salt(password: bytes) -> (bytes, bytes):
    """ Generates a hash and salt that will match a given input string, and also
        matches the hashing that is done on a user's device. 
        Input is anticipated to be any arbitrary string."""
    salt = encode_base64(urandom(16))
    password = device_hash(password)
    password_hashed = encode_base64(
        pbkdf2('sha1', password, salt, iterations=ITERATIONS, dklen=32))
    return password_hashed, salt
Пример #3
0
def compare_password(proposed_password, salt, real_password_hash):
    """ Compares a proposed password with a salt and a real password, returns
        True if the hash results are identical.
        Expects the proposed password to be a base64 encoded string.
        Expects the real password to be a base64 encoded string. """
    proposed_hash = encode_base64(
        pbkdf2('sha1',
               proposed_password,
               salt,
               iterations=ITERATIONS,
               dklen=32))
    return proposed_hash == real_password_hash
Пример #4
0
    def authenticate(self, sm, token):
        mechanism, hashfun_name, = token
        logger.info("attempting %s mechanism (using %s hashfun)", mechanism,
                    hashfun_name)
        # this is pretty much a verbatim implementation of RFC 5802.

        hashfun_factory = functools.partial(hashlib.new, hashfun_name)
        digest_size = hashfun_factory().digest_size

        # we don’t support channel binding
        gs2_header = b"n,,"
        username, password = yield from self._credential_provider()
        username = saslprep(username).encode("utf8")
        password = saslprep(password).encode("utf8")

        our_nonce = base64.b64encode(
            _system_random.getrandbits(self.nonce_length * 8).to_bytes(
                self.nonce_length, "little"))

        auth_message = b"n=" + username + b",r=" + our_nonce
        _, payload = yield from sm.initiate(mechanism,
                                            gs2_header + auth_message)

        auth_message += b"," + payload

        payload = dict(self.parse_message(payload))

        try:
            iteration_count = int(payload[b"i"])
            nonce = payload[b"r"]
            salt = base64.b64decode(payload[b"s"])
        except (ValueError, KeyError):
            yield from sm.abort()
            raise SASLFailure(
                None, text="malformed server message: {!r}".format(payload))

        if not nonce.startswith(our_nonce):
            yield from sm.abort()
            raise SASLFailure(None, text="server nonce doesn't fit our nonce")

        t0 = time.time()

        salted_password = pbkdf2(hashfun_name, password, salt, iteration_count)

        logger.debug("pbkdf2 timing: %f seconds", time.time() - t0)

        client_key = hmac.new(salted_password, b"Client Key",
                              hashfun_factory).digest()

        stored_key = hashfun_factory(client_key).digest()

        reply = b"c=" + base64.b64encode(b"n,,") + b",r=" + nonce

        auth_message += b"," + reply

        client_proof = (int.from_bytes(
            hmac.new(stored_key, auth_message, hashfun_factory).digest(),
            "big") ^ int.from_bytes(client_key, "big")).to_bytes(
                digest_size, "big")

        logger.debug("response generation time: %f seconds", time.time() - t0)
        try:
            state, payload = yield from sm.response(
                reply + b",p=" + base64.b64encode(client_proof))
        except SASLFailure as err:
            raise err.promote_to_authentication_failure() from None

        if state != "success":
            raise SASLFailure("malformed-request",
                              text="SCRAM protocol violation")

        server_signature = hmac.new(
            hmac.new(salted_password, b"Server Key", hashfun_factory).digest(),
            auth_message, hashfun_factory).digest()

        payload = dict(self.parse_message(payload))

        if base64.b64decode(payload[b"v"]) != server_signature:
            raise SASLFailure(
                None,
                "authentication successful, but server signature invalid")

        return True
Пример #5
0
 def compute(self, val):
     return pbkdf2(hash_name=self.func,
                   password=val,
                   salt=self.salt,
                   iterations=self.iterations,
                   dklen=self.dklen)
Пример #6
0
def generate_user_hash_and_salt(password):
    salt = encode_base64(urandom(16))
    password = device_hash(password)
    password_hashed = encode_base64(pbkdf2('sha1', password, salt, iterations=1000, dklen=32))
    return password_hashed, salt
Пример #7
0
    def authenticate(self, sm, token):
        mechanism, hashfun_name, = token
        logger.info("attempting %s mechanism (using %s hashfun)",
                    mechanism,
                    hashfun_name)
        # this is pretty much a verbatim implementation of RFC 5802.

        hashfun_factory = functools.partial(hashlib.new, hashfun_name)
        digest_size = hashfun_factory().digest_size

        # we don’t support channel binding
        gs2_header = b"n,,"
        username, password = yield from self._credential_provider()
        username = saslprep(username).encode("utf8")
        password = saslprep(password).encode("utf8")

        our_nonce = base64.b64encode(_system_random.getrandbits(
            self.nonce_length * 8
        ).to_bytes(
            self.nonce_length, "little"
        ))

        auth_message = b"n=" + username + b",r=" + our_nonce
        _, payload = yield from sm.initiate(
            mechanism,
            gs2_header + auth_message)

        auth_message += b"," + payload

        payload = dict(self.parse_message(payload))

        try:
            iteration_count = int(payload[b"i"])
            nonce = payload[b"r"]
            salt = base64.b64decode(payload[b"s"])
        except (ValueError, KeyError):
            yield from sm.abort()
            raise SASLFailure(
                None,
                text="malformed server message: {!r}".format(payload))

        if not nonce.startswith(our_nonce):
            yield from sm.abort()
            raise SASLFailure(
                None,
                text="server nonce doesn't fit our nonce")

        t0 = time.time()

        salted_password = pbkdf2(
            hashfun_name,
            password,
            salt,
            iteration_count)

        logger.debug("pbkdf2 timing: %f seconds", time.time() - t0)

        client_key = hmac.new(
            salted_password,
            b"Client Key",
            hashfun_factory).digest()

        stored_key = hashfun_factory(client_key).digest()

        reply = b"c=" + base64.b64encode(b"n,,") + b",r=" + nonce

        auth_message += b"," + reply

        client_proof = (
            int.from_bytes(
                hmac.new(
                    stored_key,
                    auth_message,
                    hashfun_factory).digest(),
                "big") ^
            int.from_bytes(client_key, "big")).to_bytes(digest_size, "big")

        logger.debug("response generation time: %f seconds", time.time() - t0)
        try:
            state, payload = yield from sm.response(
                reply + b",p=" + base64.b64encode(client_proof)
            )
        except SASLFailure as err:
            raise err.promote_to_authentication_failure() from None

        if state != "success":
            raise SASLFailure(
                "malformed-request",
                text="SCRAM protocol violation")

        server_signature = hmac.new(
            hmac.new(
                salted_password,
                b"Server Key",
                hashfun_factory).digest(),
            auth_message,
            hashfun_factory).digest()

        payload = dict(self.parse_message(payload))

        if base64.b64decode(payload[b"v"]) != server_signature:
            raise SASLFailure(
                None,
                "authentication successful, but server signature invalid")

        return True
Пример #8
0
    def authenticate(self, sm, token):
        mechanism, info, = token
        logger.info("attempting %s mechanism (using %s hashfun)",
                    mechanism,
                    info)
        # this is pretty much a verbatim implementation of RFC 5802.

        hashfun_factory = functools.partial(hashlib.new, info.hashfun_name)

        gs2_header = self._get_gs2_header()
        username, password = yield from self._credential_provider()
        username = saslprep(username).encode("utf8")
        password = saslprep(password).encode("utf8")

        our_nonce = base64.b64encode(_system_random.getrandbits(
            self.nonce_length * 8
        ).to_bytes(
            self.nonce_length, "little"
        ))

        auth_message = b"n=" + username + b",r=" + our_nonce
        state, payload = yield from sm.initiate(
            mechanism,
            gs2_header + auth_message)

        if state != SASLState.CHALLENGE or payload is None:
            yield from sm.abort()
            raise SASLFailure(
                None,
                text="protocol violation: expected challenge with payload")

        auth_message += b"," + payload

        payload = dict(self.parse_message(payload))

        try:
            iteration_count = int(payload[b"i"])
            nonce = payload[b"r"]
            salt = base64.b64decode(payload[b"s"])
        except (ValueError, KeyError):
            yield from sm.abort()
            raise SASLFailure(
                None,
                text="malformed server message: {!r}".format(payload))

        if not nonce.startswith(our_nonce):
            yield from sm.abort()
            raise SASLFailure(
                None,
                text="server nonce doesn't fit our nonce")

        if (self.enforce_minimum_iteration_count and
                iteration_count < info.minimum_iteration_count):
            raise SASLFailure(
                None,
                text="minimum iteration count for {} violated "
                "({} is less than {})".format(
                    mechanism,
                    iteration_count,
                    info.minimum_iteration_count,
                )
            )

        t0 = time.time()

        salted_password = pbkdf2(
            info.hashfun_name,
            password,
            salt,
            iteration_count)

        logger.debug("pbkdf2 timing: %f seconds", time.time() - t0)

        client_key = hmac.new(
            salted_password,
            b"Client Key",
            hashfun_factory).digest()

        stored_key = hashfun_factory(client_key).digest()

        reply = b"c=" + base64.b64encode(self._get_cb_data()) + b",r=" + nonce

        auth_message += b"," + reply

        client_proof = xor_bytes(
            hmac.new(
                stored_key,
                auth_message,
                hashfun_factory).digest(),
            client_key)

        logger.debug("response generation time: %f seconds", time.time() - t0)
        try:
            state, payload = yield from sm.response(
                reply + b",p=" + base64.b64encode(client_proof)
            )
        except SASLFailure as err:
            raise err.promote_to_authentication_failure() from None

        # this is the pseudo-challenge for the server signature
        # we have to reply with the empty string!
        if state != SASLState.CHALLENGE:
            raise SASLFailure(
                "malformed-request",
                text="SCRAM protocol violation")

        state, dummy_payload = yield from sm.response(b"")
        if state != SASLState.SUCCESS or dummy_payload is not None:
            raise SASLFailure(
                None,
                "SASL protocol violation")

        server_signature = hmac.new(
            hmac.new(
                salted_password,
                b"Server Key",
                hashfun_factory).digest(),
            auth_message,
            hashfun_factory).digest()

        payload = dict(self.parse_message(payload))

        if base64.b64decode(payload[b"v"]) != server_signature:
            raise SASLFailure(
                None,
                "authentication successful, but server signature invalid")

        return True
Пример #9
0
def derive_key_from_password(salt, password=None, hash_name="sha512", iterations=50000,
                             prompt="Please supply the password for the key: ",
                             dklen=None):
    return hashlib.pbkdf2(hash_name, getpass.getpass(prompt) if password is None else password, 
                          salt, iterations, dklen)