예제 #1
0
    def test_90_bcrypt_padding(self):
        """test passlib correctly handles bcrypt padding bits"""
        self.require_TEST_MODE("full")
        #
        # prevents reccurrence of issue 25 (https://code.google.com/p/passlib/issues/detail?id=25)
        # were some unused bits were incorrectly set in bcrypt salt strings.
        # (fixed since 1.5.3)
        #
        bcrypt = self.handler
        corr_desc = ".*incorrectly set padding bits"

        #
        # test encrypt() / genconfig() don't generate invalid salts anymore
        #
        def check_padding(hash):
            assert hash.startswith("$2a$") and len(hash) >= 28
            self.assertTrue(
                hash[28] in '.Oeu',
                "unused bits incorrectly set in hash: %r" % (hash, ))

        for i in irange(6):
            check_padding(bcrypt.genconfig())
        for i in irange(3):
            check_padding(bcrypt.encrypt("bob", rounds=bcrypt.min_rounds))

        #
        # test genconfig() corrects invalid salts & issues warning.
        #
        with self.assertWarningList(["salt too large", corr_desc]):
            hash = bcrypt.genconfig(salt="." * 21 + "A.",
                                    rounds=5,
                                    relaxed=True)
        self.assertEqual(hash, "$2a$05$" + "." * 22)

        #
        # test public methods against good & bad hashes
        #
        samples = self.known_incorrect_padding
        for pwd, bad, good in samples:

            # make sure genhash() corrects bad configs, leaves good unchanged
            with self.assertWarningList([corr_desc]):
                self.assertEqual(bcrypt.genhash(pwd, bad), good)
            with self.assertWarningList([]):
                self.assertEqual(bcrypt.genhash(pwd, good), good)

            # make sure verify() works correctly with good & bad hashes
            with self.assertWarningList([corr_desc]):
                self.assertTrue(bcrypt.verify(pwd, bad))
            with self.assertWarningList([]):
                self.assertTrue(bcrypt.verify(pwd, good))

            # make sure normhash() corrects bad hashes, leaves good unchanged
            with self.assertWarningList([corr_desc]):
                self.assertEqual(bcrypt.normhash(bad), good)
            with self.assertWarningList([]):
                self.assertEqual(bcrypt.normhash(good), good)

        # make sure normhash() leaves non-bcrypt hashes alone
        self.assertEqual(bcrypt.normhash("$md5$abc"), "$md5$abc")
예제 #2
0
    def test_90_bcrypt_padding(self):
        """test passlib correctly handles bcrypt padding bits"""
        self.require_TEST_MODE("full")
        #
        # prevents reccurrence of issue 25 (https://code.google.com/p/passlib/issues/detail?id=25)
        # were some unused bits were incorrectly set in bcrypt salt strings.
        # (fixed since 1.5.3)
        #
        bcrypt = self.handler
        corr_desc = ".*incorrectly set padding bits"

        #
        # test encrypt() / genconfig() don't generate invalid salts anymore
        #
        def check_padding(hash):
            assert hash.startswith("$2a$") and len(hash) >= 28
            self.assertTrue(hash[28] in '.Oeu',
                            "unused bits incorrectly set in hash: %r" % (hash,))
        for i in irange(6):
            check_padding(bcrypt.genconfig())
        for i in irange(3):
            check_padding(bcrypt.encrypt("bob", rounds=bcrypt.min_rounds))

        #
        # test genconfig() corrects invalid salts & issues warning.
        #
        with self.assertWarningList(["salt too large", corr_desc]):
            hash = bcrypt.genconfig(salt="."*21 + "A.", rounds=5, relaxed=True)
        self.assertEqual(hash, "$2a$05$" + "." * 22)

        #
        # test public methods against good & bad hashes
        #
        samples = self.known_incorrect_padding
        for pwd, bad, good in samples:

            # make sure genhash() corrects bad configs, leaves good unchanged
            with self.assertWarningList([corr_desc]):
                self.assertEqual(bcrypt.genhash(pwd, bad), good)
            with self.assertWarningList([]):
                self.assertEqual(bcrypt.genhash(pwd, good), good)

        #
        # and that verify() works good & bad
        #
        with self.assertWarningList([corr_desc]):
            self.assertTrue(bcrypt.verify(pwd, bad))
        with self.assertWarningList([]):
            self.assertTrue(bcrypt.verify(pwd, good))

        #
        # test normhash cleans things up correctly
        #
        for pwd, bad, good in samples:
            with self.assertWarningList([corr_desc]):
                self.assertEqual(bcrypt.normhash(bad), good)
            with self.assertWarningList([]):
                self.assertEqual(bcrypt.normhash(good), good)
        self.assertEqual(bcrypt.normhash("$md5$abc"), "$md5$abc")
예제 #3
0
파일: pbkdf2.py 프로젝트: Glottotopia/aagd
 def gen():
     for i in irange(block_count):
         digest = prf_func(secret, salt + pack(">L", i+1))
         accum = bytes_to_int(digest)
         for _ in irange(rounds-1):
             digest = prf_func(secret, digest)
             accum ^= bytes_to_int(digest)
         yield int_to_bytes(accum, digest_size)
예제 #4
0
 def gen():
     for i in irange(block_count):
         digest = prf_func(secret, salt + pack(">L", i+1))
         accum = bytes_to_int(digest)
         for _ in irange(rounds-1):
             digest = prf_func(secret, digest)
             accum ^= bytes_to_int(digest)
         yield int_to_bytes(accum, digest_size)
예제 #5
0
파일: pbkdf2.py 프로젝트: cutso/passlib
 def gen():
     for i in irange(block_count):
         digest = keyed_prf(salt + pack(">L", i+1))
         accum = bytes_to_int(digest)
         # speed-critical loop of pbkdf2
         # NOTE: currently converting digests to integers since that XORs faster.
         for _ in irange(rounds-1):
             digest = keyed_prf(digest)
             accum ^= bytes_to_int(digest)
         yield int_to_bytes(accum, digest_size)
예제 #6
0
 def gen():
     for i in irange(block_count):
         digest = keyed_prf(salt + pack(">L", i + 1))
         accum = bytes_to_int(digest)
         # speed-critical loop of pbkdf2
         # NOTE: currently converting digests to integers since that XORs faster.
         for _ in irange(rounds - 1):
             digest = keyed_prf(digest)
             accum ^= bytes_to_int(digest)
         yield int_to_bytes(accum, digest_size)
예제 #7
0
파일: _md4.py 프로젝트: dragoncsc/HDsite
    def _process(self, block):
        """process 64 byte block"""
        # unpack block into 16 32-bit ints
        X = struct.unpack("<16I", block)

        # clone state
        orig = self._state
        state = list(orig)

        # round 1 - F function - (x&y)|(~x & z)
        for a,b,c,d,k,s in self._round1:
            t = (state[a] + F(state[b],state[c],state[d]) + X[k]) & MASK_32
            state[a] = ((t<<s) & MASK_32) + (t>>(32-s))

        # round 2 - G function
        for a,b,c,d,k,s in self._round2:
            t = (state[a] + G(state[b],state[c],state[d]) + X[k] + 0x5a827999) & MASK_32
            state[a] = ((t<<s) & MASK_32) + (t>>(32-s))

        # round 3 - H function - x ^ y ^ z
        for a,b,c,d,k,s in self._round3:
            t = (state[a] + (state[b] ^ state[c] ^ state[d]) + X[k] + 0x6ed9eba1) & MASK_32
            state[a] = ((t<<s) & MASK_32) + (t>>(32-s))

        # add back into original state
        for i in irange(4):
            orig[i] = (orig[i]+state[i]) & MASK_32
예제 #8
0
    def _process(self, block):
        """process 64 byte block"""
        # unpack block into 16 32-bit ints
        X = struct.unpack("<16I", block)

        # clone state
        orig = self._state
        state = list(orig)

        # round 1 - F function - (x&y)|(~x & z)
        for a, b, c, d, k, s in self._round1:
            t = (state[a] + F(state[b], state[c], state[d]) + X[k]) & MASK_32
            state[a] = ((t << s) & MASK_32) + (t >> (32 - s))

        # round 2 - G function
        for a, b, c, d, k, s in self._round2:
            t = (state[a] + G(state[b], state[c], state[d]) + X[k] +
                 0x5a827999) & MASK_32
            state[a] = ((t << s) & MASK_32) + (t >> (32 - s))

        # round 3 - H function - x ^ y ^ z
        for a, b, c, d, k, s in self._round3:
            t = (state[a] + (state[b] ^ state[c] ^ state[d]) + X[k] +
                 0x6ed9eba1) & MASK_32
            state[a] = ((t << s) & MASK_32) + (t >> (32 - s))

        # add back into original state
        for i in irange(4):
            orig[i] = (orig[i] + state[i]) & MASK_32
예제 #9
0
파일: digest.py 프로젝트: javierrami/GAM
 def _pbkdf2_looper(keyed_hmac, digest, rounds):
     hexlify = _hexlify
     accum = int(hexlify(digest), 16)
     for _ in irange(rounds - 1):
         digest = keyed_hmac(digest)
         accum ^= int(hexlify(digest), 16)
     return int_to_bytes(accum, len(digest))
예제 #10
0
    def test_04_check_password(self):
        """test check_password()"""
        ht = apache.HtpasswdFile.from_string(self.sample_05)
        self.assertRaises(TypeError, ht.check_password, 1, 'pass9')
        self.assertTrue(ht.check_password("user9","pass9") is None)

        # users 1..6 of sample_01 run through all the main hash formats,
        # to make sure they're recognized.
        for i in irange(1, 7):
            i = str(i)
            try:
                self.assertTrue(ht.check_password("user"+i, "pass"+i))
                self.assertTrue(ht.check_password("user"+i, "pass9") is False)
            except MissingBackendError:
                if i == "5":
                    # user5 uses bcrypt, which is apparently not available right now
                    continue
                raise

        self.assertRaises(ValueError, ht.check_password, "user:"******"pass")

        # test that legacy verify() still works
        with self.assertWarningList(["verify\(\) is deprecated"]*2):
            self.assertTrue(ht.verify("user1", "pass1"))
            self.assertFalse(ht.verify("user1", "pass2"))
예제 #11
0
    def test_04_check_password(self):
        """test check_password()"""
        ht = apache.HtpasswdFile.from_string(self.sample_05)
        self.assertRaises(TypeError, ht.check_password, 1, 'pass9')
        self.assertTrue(ht.check_password("user9", "pass9") is None)

        # users 1..6 of sample_01 run through all the apis hash formats,
        # to make sure they're recognized.
        for i in irange(1, 7):
            i = str(i)
            try:
                self.assertTrue(ht.check_password("user" + i, "pass" + i))
                self.assertTrue(
                    ht.check_password("user" + i, "pass9") is False)
            except MissingBackendError:
                if i == "5":
                    # user5 uses bcrypt, which is apparently not available right now
                    continue
                raise

        self.assertRaises(ValueError, ht.check_password, "user:"******"pass")

        # test that legacy verify() still works
        with self.assertWarningList(["verify\(\) is deprecated"] * 2):
            self.assertTrue(ht.verify("user1", "pass1"))
            self.assertFalse(ht.verify("user1", "pass2"))
예제 #12
0
    def test_04_check_password(self):
        """test check_password()"""
        ht = apache.HtdigestFile.from_string(self.sample_01)
        self.assertRaises(TypeError, ht.check_password, 1, 'realm', 'pass5')
        self.assertRaises(TypeError, ht.check_password, 'user', 1, 'pass5')
        self.assertIs(ht.check_password("user5", "realm", "pass5"), None)
        for i in irange(1, 5):
            i = str(i)
            self.assertTrue(ht.check_password("user" + i, "realm", "pass" + i))
            self.assertIs(ht.check_password("user" + i, "realm", "pass5"),
                          False)

        # default realm
        self.assertRaises(TypeError, ht.check_password, "user5", "pass5")
        ht.default_realm = "realm"
        self.assertTrue(ht.check_password("user1", "pass1"))
        self.assertIs(ht.check_password("user5", "pass5"), None)

        # test that legacy verify() still works
        with self.assertWarningList(["verify\(\) is deprecated"] * 2):
            self.assertTrue(ht.verify("user1", "realm", "pass1"))
            self.assertFalse(ht.verify("user1", "realm", "pass2"))

        # invalid user
        self.assertRaises(ValueError, ht.check_password, "user:"******"realm",
                          "pass")
예제 #13
0
 def _pbkdf2_looper(keyed_hmac, digest, rounds):
     hexlify = _hexlify
     accum = int(hexlify(digest), 16)
     for _ in irange(rounds - 1):
         digest = keyed_hmac(digest)
         accum ^= int(hexlify(digest), 16)
     return int_to_bytes(accum, len(digest))
예제 #14
0
def pbkdf1(digest, secret, salt, rounds, keylen=None):
    """pkcs#5 password-based key derivation v1.5

    :arg digest:
        digest name or constructor.
        
    :arg secret:
        secret to use when generating the key.
        may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8).
        
    :arg salt:
        salt string to use when generating key.
        may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8).

    :param rounds:
        number of rounds to use to generate key.

    :arg keylen:
        number of bytes to generate (if omitted / ``None``, uses digest's native size)

    :returns:
        raw :class:`bytes` of generated key

    .. note::

        This algorithm has been deprecated, new code should use PBKDF2.
        Among other limitations, ``keylen`` cannot be larger
        than the digest size of the specified hash.
    """
    # resolve digest
    const, digest_size, block_size = lookup_hash(digest)

    # validate secret & salt
    secret = to_bytes(secret, param="secret")
    salt = to_bytes(salt, param="salt")

    # validate rounds
    if not isinstance(rounds, int_types):
        raise exc.ExpectedTypeError(rounds, "int", "rounds")
    if rounds < 1:
        raise ValueError("rounds must be at least 1")

    # validate keylen
    if keylen is None:
        keylen = digest_size
    elif not isinstance(keylen, int_types):
        raise exc.ExpectedTypeError(keylen, "int or None", "keylen")
    elif keylen < 0:
        raise ValueError("keylen must be at least 0")
    elif keylen > digest_size:
        raise ValueError("keylength too large for digest: %r > %r" %
                         (keylen, digest_size))

    # main pbkdf1 loop
    block = secret + salt
    for _ in irange(rounds):
        block = const(block).digest()
    return block[:keylen]
예제 #15
0
파일: digest.py 프로젝트: javierrami/GAM
def pbkdf1(digest, secret, salt, rounds, keylen=None):
    """pkcs#5 password-based key derivation v1.5

    :arg digest:
        digest name or constructor.
        
    :arg secret:
        secret to use when generating the key.
        may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8).
        
    :arg salt:
        salt string to use when generating key.
        may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8).

    :param rounds:
        number of rounds to use to generate key.

    :arg keylen:
        number of bytes to generate (if omitted / ``None``, uses digest's native size)

    :returns:
        raw :class:`bytes` of generated key

    .. note::

        This algorithm has been deprecated, new code should use PBKDF2.
        Among other limitations, ``keylen`` cannot be larger
        than the digest size of the specified hash.
    """
    # resolve digest
    const, digest_size, block_size = lookup_hash(digest)
    
    # validate secret & salt
    secret = to_bytes(secret, param="secret")
    salt = to_bytes(salt, param="salt")

    # validate rounds
    if not isinstance(rounds, int_types):
        raise exc.ExpectedTypeError(rounds, "int", "rounds")
    if rounds < 1:
        raise ValueError("rounds must be at least 1")

    # validate keylen
    if keylen is None:
        keylen = digest_size
    elif not isinstance(keylen, int_types):
        raise exc.ExpectedTypeError(keylen, "int or None", "keylen")
    elif keylen < 0:
        raise ValueError("keylen must be at least 0")
    elif keylen > digest_size:
        raise ValueError("keylength too large for digest: %r > %r" %
                         (keylen, digest_size))

    # main pbkdf1 loop
    block = secret + salt
    for _ in irange(rounds):
        block = const(block).digest()
    return block[:keylen]
예제 #16
0
def render_encipher(write, indent=0):
    for i in irange(0, 15, 2):
        write(indent, """\
            # Feistel substitution on left word (round %(i)d)
            r ^= %(left)s ^ p%(i1)d

            # Feistel substitution on right word (round %(i1)d)
            l ^= %(right)s ^ p%(i2)d
        """, i=i, i1=i+1, i2=i+2,
             left=BFSTR, right=BFSTR.replace("l","r"),
             )
예제 #17
0
파일: pwd.py 프로젝트: thebaron/passlib
 def _gen(self):
     while True:
         symbols = [self.rng.choice(self.wordset) for _ in irange(self.size)]
         # check that it satisfies minimum self-information limit
         # set by min_complexity. i.e., reject strings like "aaaaaaaa"
         if _average_entropy(symbols) > self._min_entropy:
             secret = self._sep.join(symbols)
             # check that we don't fall below per-character limit
             # on self information. see __init__ for explanation
             if len(secret) >= self._min_chars:
                 return secret
예제 #18
0
def render_encipher(write, indent=0):
    for i in irange(0, 15, 2):
        write(indent, """\
            # Feistel substitution on left word (round %(i)d)
            r ^= %(left)s ^ p%(i1)d

            # Feistel substitution on right word (round %(i1)d)
            l ^= %(right)s ^ p%(i2)d
        """, i=i, i1=i+1, i2=i+2,
             left=BFSTR, right=BFSTR.replace("l","r"),
             )
예제 #19
0
파일: digest.py 프로젝트: javierrami/GAM
 def _pbkdf2_looper(digest_size, keyed_hmac, digest, rounds):
     """
     py3-only implementation of pbkdf2 inner loop;
     uses 'int.from_bytes' + integer XOR
     """
     from_bytes = int.from_bytes
     BIG = "big"  # endianess doesn't matter, just has to be consistent
     accum = from_bytes(digest, BIG)
     for _ in irange(rounds - 1):
         digest = keyed_hmac(digest)
         accum ^= from_bytes(digest, BIG)
     return accum.to_bytes(digest_size, BIG)
예제 #20
0
파일: binary.py 프로젝트: dragoncsc/HDsite
    def _encode_int(self, value, bits):
        """encode integer into base64 format

        :arg value: non-negative integer to encode
        :arg bits: number of bits to encode

        :returns:
            a string of length ``int(ceil(bits/6.0))``.
        """
        assert value >= 0, "caller did not sanitize input"
        pad = -bits % 6
        bits += pad
        if self.big:
            itr = irange(bits-6, -6, -6)
            # shift to add lsb padding.
            value <<= pad
        else:
            itr = irange(0, bits, 6)
            # padding is msb, so no change needed.
        return join_byte_elems(imap(self._encode64,
                                ((value>>off) & 0x3f for off in itr)))
예제 #21
0
    def _encode_int(self, value, bits):
        """encode integer into base64 format

        :arg value: non-negative integer to encode
        :arg bits: number of bits to encode

        :returns:
            a string of length ``int(ceil(bits/6.0))``.
        """
        assert value >= 0, "caller did not sanitize input"
        pad = -bits % 6
        bits += pad
        if self.big:
            itr = irange(bits - 6, -6, -6)
            # shift to add lsb padding.
            value <<= pad
        else:
            itr = irange(0, bits, 6)
            # padding is msb, so no change needed.
        return join_byte_elems(
            imap(self._encode64, ((value >> off) & 0x3f for off in itr)))
예제 #22
0
 def _pbkdf2_looper(digest_size, keyed_hmac, digest, rounds):
     """
     py3-only implementation of pbkdf2 inner loop;
     uses 'int.from_bytes' + integer XOR
     """
     from_bytes = int.from_bytes
     BIG = "big"  # endianess doesn't matter, just has to be consistent
     accum = from_bytes(digest, BIG)
     for _ in irange(rounds - 1):
         digest = keyed_hmac(digest)
         accum ^= from_bytes(digest, BIG)
     return accum.to_bytes(digest_size, BIG)
예제 #23
0
파일: pwd.py 프로젝트: javierrami/GAM
 def __call__(self, returns=None):
     """
     frontend used by genword() / genphrase() to create passwords
     """
     if returns is None:
         return next(self)
     elif isinstance(returns, int_types):
         return [next(self) for _ in irange(returns)]
     elif returns is iter:
         return self
     else:
         raise exc.ExpectedTypeError(returns, "<None>, int, or <iter>", "returns")
예제 #24
0
파일: pwd.py 프로젝트: docovarr2020/DIYnow
 def __call__(self, returns=None):
     """
     frontend used by genword() / genphrase() to create passwords
     """
     if returns is None:
         return next(self)
     elif isinstance(returns, int_types):
         return [next(self) for _ in irange(returns)]
     elif returns is iter:
         return self
     else:
         raise exc.ExpectedTypeError(returns, "<None>, int, or <iter>", "returns")
예제 #25
0
 def _calc_checksum_builtin(self, secret):
     if isinstance(secret, unicode):
         secret = secret.encode("utf-8")
     if _BNULL in secret:
         raise uh.exc.NullPasswordError(self)
     rounds = self.rounds
     # NOTE: this seed value is NOT the same as the config string
     result = (u("%s$sha1$%s") % (self.salt, rounds)).encode("ascii")
     # NOTE: this algorithm is essentially PBKDF1, modified to use HMAC.
     keyed_hmac = compile_hmac("sha1", secret)
     for _ in irange(rounds):
         result = keyed_hmac(result)
     return h64.encode_transposed_bytes(result, self._chk_offsets).decode("ascii")
예제 #26
0
 def _calc_checksum_builtin(self, secret):
     if isinstance(secret, unicode):
         secret = secret.encode("utf-8")
     if _BNULL in secret:
         raise uh.exc.NullPasswordError(self)
     rounds = self.rounds
     # NOTE: this seed value is NOT the same as the config string
     result = (u("%s$sha1$%s") % (self.salt, rounds)).encode("ascii")
     # NOTE: this algorithm is essentially PBKDF1, modified to use HMAC.
     keyed_hmac = get_keyed_prf("hmac-sha1", secret)[0]
     for _ in irange(rounds):
         result = keyed_hmac(result)
     return h64.encode_transposed_bytes(result, self._chk_offsets).decode("ascii")
예제 #27
0
def pbkdf1(secret, salt, rounds, keylen=None, hash="sha1"):
    """pkcs#5 password-based key derivation v1.5

    :arg secret: passphrase to use to generate key
    :arg salt: salt string to use when generating key
    :param rounds: number of rounds to use to generate key
    :arg keylen: number of bytes to generate (if ``None``, uses digest's native size)
    :param hash:
        hash function to use. must be name of a hash recognized by hashlib.

    :returns:
        raw bytes of generated key

    .. note::

        This algorithm has been deprecated, new code should use PBKDF2.
        Among other limitations, ``keylen`` cannot be larger
        than the digest size of the specified hash.
    """
    # validate secret & salt
    if not isinstance(secret, bytes):
        raise ExpectedTypeError(secret, "bytes", "secret")
    if not isinstance(salt, bytes):
        raise ExpectedTypeError(salt, "bytes", "salt")

    # validate rounds
    if not isinstance(rounds, int_types):
        raise ExpectedTypeError(rounds, "int", "rounds")
    if rounds < 1:
        raise ValueError("rounds must be at least 1")

    # resolve hash
    const, digest_size, block_size = get_hash_info(hash)

    # validate keylen
    if keylen is None:
        keylen = digest_size
    elif not isinstance(keylen, int_types):
        raise ExpectedTypeError(keylen, "int or None", "keylen")
    elif keylen < 0:
        raise ValueError("keylen must be at least 0")
    elif keylen > digest_size:
        raise ValueError("keylength too large for digest: %r > %r" %
                         (keylen, digest_size))

    # main pbkdf1 loop
    block = secret + salt
    for _ in irange(rounds):
        block = const(block).digest()
    return block[:keylen]
예제 #28
0
파일: pbkdf2.py 프로젝트: cutso/passlib
def pbkdf1(secret, salt, rounds, keylen=None, hash="sha1"):
    """pkcs#5 password-based key derivation v1.5

    :arg secret: passphrase to use to generate key
    :arg salt: salt string to use when generating key
    :param rounds: number of rounds to use to generate key
    :arg keylen: number of bytes to generate (if ``None``, uses digest's native size)
    :param hash:
        hash function to use. must be name of a hash recognized by hashlib.

    :returns:
        raw bytes of generated key

    .. note::

        This algorithm has been deprecated, new code should use PBKDF2.
        Among other limitations, ``keylen`` cannot be larger
        than the digest size of the specified hash.
    """
    # validate secret & salt
    if not isinstance(secret, bytes):
        raise ExpectedTypeError(secret, "bytes", "secret")
    if not isinstance(salt, bytes):
        raise ExpectedTypeError(salt, "bytes", "salt")

    # validate rounds
    if not isinstance(rounds, int_types):
        raise ExpectedTypeError(rounds, "int", "rounds")
    if rounds < 1:
        raise ValueError("rounds must be at least 1")

    # resolve hash
    const, digest_size, block_size = get_hash_info(hash)

    # validate keylen
    if keylen is None:
        keylen = digest_size
    elif not isinstance(keylen, int_types):
        raise ExpectedTypeError(keylen, "int or None", "keylen")
    elif keylen < 0:
        raise ValueError("keylen must be at least 0")
    elif keylen > digest_size:
        raise ValueError("keylength too large for digest: %r > %r" %
                         (keylen, digest_size))

    # main pbkdf1 loop
    block = secret + salt
    for _ in irange(rounds):
        block = const(block).digest()
    return block[:keylen]
예제 #29
0
    def check_int_pair(self, bits, encoded_pairs):
        """helper to check encode_intXX & decode_intXX functions"""
        rng = self.getRandom()
        engine = self.engine
        encode = getattr(engine, "encode_int%s" % bits)
        decode = getattr(engine, "decode_int%s" % bits)
        pad = -bits % 6
        chars = (bits + pad) // 6
        upper = 1 << bits

        # test encode func
        for value, encoded in encoded_pairs:
            result = encode(value)
            self.assertIsInstance(result, bytes)
            self.assertEqual(result, encoded)
        self.assertRaises(ValueError, encode, -1)
        self.assertRaises(ValueError, encode, upper)

        # test decode func
        for value, encoded in encoded_pairs:
            self.assertEqual(decode(encoded), value,
                             "encoded %r:" % (encoded, ))
        m = self.m
        self.assertRaises(ValueError, decode, m(0) * (chars + 1))
        self.assertRaises(ValueError, decode, m(0) * (chars - 1))
        self.assertRaises(ValueError, decode, self.bad_byte * chars)
        self.assertRaises(TypeError, decode, engine.charmap[0])
        self.assertRaises(TypeError, decode, None)

        # do random testing.
        from passlib.utils import getrandstr
        for i in irange(100):
            # generate random value, encode, and then decode
            value = rng.randint(0, upper - 1)
            encoded = encode(value)
            self.assertEqual(len(encoded), chars)
            self.assertEqual(decode(encoded), value)

            # generate some random encoded data, decode, then encode.
            encoded = getrandstr(rng, engine.bytemap, chars)
            value = decode(encoded)
            self.assertGreaterEqual(value, 0,
                                    "decode %r out of bounds:" % encoded)
            self.assertLess(value, upper, "decode %r out of bounds:" % encoded)
            result = encode(value)
            if pad:
                self.assertEqual(result[:-2], encoded[:-2])
            else:
                self.assertEqual(result, encoded)
예제 #30
0
    def test_04_check_password(self):
        "test check_password()"
        ht = apache.HtpasswdFile.from_string(self.sample_01)
        self.assertRaises(TypeError, ht.check_password, 1, 'pass5')
        self.assertTrue(ht.check_password("user5","pass5") is None)
        for i in irange(1,5):
            i = str(i)
            self.assertTrue(ht.check_password("user"+i, "pass"+i))
            self.assertTrue(ht.check_password("user"+i, "pass5") is False)

        self.assertRaises(ValueError, ht.check_password, "user:"******"pass")

        # test that legacy verify() still works
        with self.assertWarningList(["verify\(\) is deprecated"]*2):
            self.assertTrue(ht.verify("user1", "pass1"))
            self.assertFalse(ht.verify("user1", "pass2"))
예제 #31
0
    def test_04_check_password(self):
        "test check_password()"
        ht = apache.HtpasswdFile.from_string(self.sample_01)
        self.assertRaises(TypeError, ht.check_password, 1, 'pass5')
        self.assertTrue(ht.check_password("user5","pass5") is None)
        for i in irange(1,5):
            i = str(i)
            self.assertTrue(ht.check_password("user"+i, "pass"+i))
            self.assertTrue(ht.check_password("user"+i, "pass5") is False)

        self.assertRaises(ValueError, ht.check_password, "user:"******"pass")

        # test that legacy verify() still works
        with self.assertWarningList(["verify\(\) is deprecated"]*2):
            self.assertTrue(ht.verify("user1", "pass1"))
            self.assertFalse(ht.verify("user1", "pass2"))
예제 #32
0
    def check_int_pair(self, bits, encoded_pairs):
        """helper to check encode_intXX & decode_intXX functions"""
        rng = self.getRandom()
        engine = self.engine
        encode = getattr(engine, "encode_int%s" % bits)
        decode = getattr(engine, "decode_int%s" % bits)
        pad = -bits % 6
        chars = (bits+pad)//6
        upper = 1<<bits

        # test encode func
        for value, encoded in encoded_pairs:
            result = encode(value)
            self.assertIsInstance(result, bytes)
            self.assertEqual(result, encoded)
        self.assertRaises(ValueError, encode, -1)
        self.assertRaises(ValueError, encode, upper)

        # test decode func
        for value, encoded in encoded_pairs:
            self.assertEqual(decode(encoded), value, "encoded %r:" % (encoded,))
        m = self.m
        self.assertRaises(ValueError, decode, m(0)*(chars+1))
        self.assertRaises(ValueError, decode, m(0)*(chars-1))
        self.assertRaises(ValueError, decode, self.bad_byte*chars)
        self.assertRaises(TypeError, decode, engine.charmap[0])
        self.assertRaises(TypeError, decode, None)

        # do random testing.
        from passlib.utils import getrandstr
        for i in irange(100):
            # generate random value, encode, and then decode
            value = rng.randint(0, upper-1)
            encoded = encode(value)
            self.assertEqual(len(encoded), chars)
            self.assertEqual(decode(encoded), value)

            # generate some random encoded data, decode, then encode.
            encoded = getrandstr(rng, engine.bytemap, chars)
            value = decode(encoded)
            self.assertGreaterEqual(value, 0, "decode %r out of bounds:" % encoded)
            self.assertLess(value, upper, "decode %r out of bounds:" % encoded)
            result = encode(value)
            if pad:
                self.assertEqual(result[:-2], encoded[:-2])
            else:
                self.assertEqual(result, encoded)
예제 #33
0
    def test_codec(self):
        """test encode_bytes/decode_bytes against random data"""
        engine = self.engine
        from passlib.utils import getrandbytes, getrandstr
        rng = self.getRandom()
        saw_zero = False
        for i in irange(500):
            #
            # test raw -> encode() -> decode() -> raw
            #

            # generate some random bytes
            size = rng.randint(1 if saw_zero else 0, 12)
            if not size:
                saw_zero = True
            enc_size = (4*size+2)//3
            raw = getrandbytes(rng, size)

            # encode them, check invariants
            encoded = engine.encode_bytes(raw)
            self.assertEqual(len(encoded), enc_size)

            # make sure decode returns original
            result = engine.decode_bytes(encoded)
            self.assertEqual(result, raw)

            #
            # test encoded -> decode() -> encode() -> encoded
            #

            # generate some random encoded data
            if size % 4 == 1:
                size += rng.choice([-1,1,2])
            raw_size = 3*size//4
            encoded = getrandstr(rng, engine.bytemap, size)

            # decode them, check invariants
            raw = engine.decode_bytes(encoded)
            self.assertEqual(len(raw), raw_size, "encoded %d:" % size)

            # make sure encode returns original (barring padding bits)
            result = engine.encode_bytes(raw)
            if size % 4:
                self.assertEqual(result[:-1], encoded[:-1])
            else:
                self.assertEqual(result, encoded)
예제 #34
0
    def test_codec(self):
        """test encode_bytes/decode_bytes against random data"""
        engine = self.engine
        from passlib.utils import getrandbytes, getrandstr
        rng = self.getRandom()
        saw_zero = False
        for i in irange(500):
            #
            # test raw -> encode() -> decode() -> raw
            #

            # generate some random bytes
            size = rng.randint(1 if saw_zero else 0, 12)
            if not size:
                saw_zero = True
            enc_size = (4*size+2)//3
            raw = getrandbytes(rng, size)

            # encode them, check invariants
            encoded = engine.encode_bytes(raw)
            self.assertEqual(len(encoded), enc_size)

            # make sure decode returns original
            result = engine.decode_bytes(encoded)
            self.assertEqual(result, raw)

            #
            # test encoded -> decode() -> encode() -> encoded
            #

            # generate some random encoded data
            if size % 4 == 1:
                size += rng.choice([-1,1,2])
            raw_size = 3*size//4
            encoded = getrandstr(rng, engine.bytemap, size)

            # decode them, check invariants
            raw = engine.decode_bytes(encoded)
            self.assertEqual(len(raw), raw_size, "encoded %d:" % size)

            # make sure encode returns original (barring padding bits)
            result = engine.encode_bytes(raw)
            if size % 4:
                self.assertEqual(result[:-1], encoded[:-1])
            else:
                self.assertEqual(result, encoded)
예제 #35
0
    def test_04_check_password(self):
        """test check_password()"""
        ht = apache.HtdigestFile.from_string(self.sample_01)
        self.assertRaises(TypeError, ht.check_password, 1, 'realm', 'pass5')
        self.assertRaises(TypeError, ht.check_password, 'user', 1, 'pass5')
        self.assertIs(ht.check_password("user5", "realm","pass5"), None)
        for i in irange(1,5):
            i = str(i)
            self.assertTrue(ht.check_password("user"+i, "realm", "pass"+i))
            self.assertIs(ht.check_password("user"+i, "realm", "pass5"), False)

        # default realm
        self.assertRaises(TypeError, ht.check_password, "user5", "pass5")
        ht.default_realm = "realm"
        self.assertTrue(ht.check_password("user1", "pass1"))
        self.assertIs(ht.check_password("user5", "pass5"), None)

        # invalid user
        self.assertRaises(ValueError, ht.check_password, "user:"******"realm", "pass")
예제 #36
0
    def test_04_check_password(self):
        """test check_password()"""
        ht = apache.HtpasswdFile.from_string(self.sample_05)
        self.assertRaises(TypeError, ht.check_password, 1, 'pass9')
        self.assertTrue(ht.check_password("user9","pass9") is None)

        # users 1..6 of sample_01 run through all the main hash formats,
        # to make sure they're recognized.
        for i in irange(1, 7):
            i = str(i)
            try:
                self.assertTrue(ht.check_password("user"+i, "pass"+i))
                self.assertTrue(ht.check_password("user"+i, "pass9") is False)
            except MissingBackendError:
                if i == "5":
                    # user5 uses bcrypt, which is apparently not available right now
                    continue
                raise

        self.assertRaises(ValueError, ht.check_password, "user:"******"pass")
예제 #37
0
파일: oracle.py 프로젝트: Glottotopia/aagd
def des_cbc_encrypt(key, value, iv=b('\x00') * 8, pad=b('\x00')):
    """performs des-cbc encryption, returns only last block.

    this performs a specific DES-CBC encryption implementation
    as needed by the Oracle10 hash. it probably won't be useful for
    other purposes as-is.

    input value is null-padded to multiple of 8 bytes.

    :arg key: des key as bytes
    :arg value: value to encrypt, as bytes.
    :param iv: optional IV
    :param pad: optional pad byte

    :returns: last block of DES-CBC encryption of all ``value``'s byte blocks.
    """
    value += pad * (-len(value) % 8) # null pad to multiple of 8
    hash = iv # start things off
    for offset in irange(0,len(value),8):
        chunk = xor_bytes(hash, value[offset:offset+8])
        hash = des_encrypt_block(key, chunk)
    return hash
예제 #38
0
def des_cbc_encrypt(key, value, iv=b'\x00' * 8, pad=b'\x00'):
    """performs des-cbc encryption, returns only last block.

    this performs a specific DES-CBC encryption implementation
    as needed by the Oracle10 hash. it probably won't be useful for
    other purposes as-is.

    input value is null-padded to multiple of 8 bytes.

    :arg key: des key as bytes
    :arg value: value to encrypt, as bytes.
    :param iv: optional IV
    :param pad: optional pad byte

    :returns: last block of DES-CBC encryption of all ``value``'s byte blocks.
    """
    value += pad * (-len(value) % 8)  # null pad to multiple of 8
    hash = iv  # start things off
    for offset in irange(0, len(value), 8):
        chunk = xor_bytes(hash, value[offset:offset + 8])
        hash = des_encrypt_block(key, chunk)
    return hash
예제 #39
0
    def test_04_check_password(self):
        "test check_password()"
        ht = apache.HtdigestFile.from_string(self.sample_01)
        self.assertRaises(TypeError, ht.check_password, 1, 'realm', 'pass5')
        self.assertRaises(TypeError, ht.check_password, 'user', 1, 'pass5')
        self.assertIs(ht.check_password("user5", "realm","pass5"), None)
        for i in irange(1,5):
            i = str(i)
            self.assertTrue(ht.check_password("user"+i, "realm", "pass"+i))
            self.assertIs(ht.check_password("user"+i, "realm", "pass5"), False)

        # default realm
        self.assertRaises(TypeError, ht.check_password, "user5", "pass5")
        ht.default_realm = "realm"
        self.assertTrue(ht.check_password("user1", "pass1"))
        self.assertIs(ht.check_password("user5", "pass5"), None)

        # test that legacy verify() still works
        with self.assertWarningList(["verify\(\) is deprecated"]*2):
            self.assertTrue(ht.verify("user1", "realm", "pass1"))
            self.assertFalse(ht.verify("user1", "realm", "pass2"))

        # invalid user
        self.assertRaises(ValueError, ht.check_password, "user:"******"realm", "pass")
예제 #40
0
파일: digest.py 프로젝트: javierrami/GAM
def pbkdf2_hmac(digest, secret, salt, rounds, keylen=None):
    """pkcs#5 password-based key derivation v2.0 using HMAC + arbitrary digest.

    :arg digest:
        digest name or constructor.

    :arg secret:
        passphrase to use to generate key.
        may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8).

    :arg salt:
        salt string to use when generating key.
        may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8).

    :param rounds:
        number of rounds to use to generate key.

    :arg keylen:
        number of bytes to generate.
        if omitted / ``None``, will use digest's native output size.

    :returns:
        raw bytes of generated key

    .. versionchanged:: 1.7

        This function will use the first available of the following backends:

        * `fastpbk2 <https://pypi.python.org/pypi/fastpbkdf2>`_
        * :func:`hashlib.pbkdf2_hmac` (only available in py2 >= 2.7.8, and py3 >= 3.4)
        * builtin pure-python backend

        See :data:`passlib.crypto.digest.PBKDF2_BACKENDS` to determine
        which backend(s) are in use.
    """
    # validate secret & salt
    secret = to_bytes(secret, param="secret")
    salt = to_bytes(salt, param="salt")

    # resolve digest
    digest_info = lookup_hash(digest)
    digest_size = digest_info.digest_size

    # validate rounds
    if not isinstance(rounds, int_types):
        raise exc.ExpectedTypeError(rounds, "int", "rounds")
    if rounds < 1:
        raise ValueError("rounds must be at least 1")

    # validate keylen
    if keylen is None:
        keylen = digest_size
    elif not isinstance(keylen, int_types):
        raise exc.ExpectedTypeError(keylen, "int or None", "keylen")
    elif keylen < 1:
        # XXX: could allow keylen=0, but want to be compat w/ stdlib
        raise ValueError("keylen must be at least 1")

    # find smallest block count s.t. keylen <= block_count * digest_size;
    # make sure block count won't overflow (per pbkdf2 spec)
    # this corresponds to throwing error if keylen > digest_size * MAX_UINT32
    # NOTE: stdlib will throw error at lower bound (keylen > MAX_SINT32)
    # NOTE: have do this before other backends checked, since fastpbkdf2 raises wrong error
    #       (InvocationError, not OverflowError)
    block_count = (keylen + digest_size - 1) // digest_size
    if block_count > MAX_UINT32:
        raise OverflowError("keylen too long for digest")

    #
    # check for various high-speed backends
    #

    # ~3x faster than pure-python backend
    # NOTE: have to do this after above guards since fastpbkdf2 lacks bounds checks.
    if digest_info.supported_by_fastpbkdf2:
        return _fast_pbkdf2_hmac(digest_info.name, secret, salt, rounds, keylen)

    # ~1.4x faster than pure-python backend
    # NOTE: have to do this after fastpbkdf2 since hashlib-ssl is slower,
    #       will support larger number of hashes.
    if digest_info.supported_by_hashlib_pbkdf2:
        return _stdlib_pbkdf2_hmac(digest_info.name, secret, salt, rounds, keylen)

    #
    # otherwise use our own implementation
    #

    # generated keyed hmac
    keyed_hmac = compile_hmac(digest, secret)

    # get helper to calculate pbkdf2 inner loop efficiently
    calc_block = _get_pbkdf2_looper(digest_size)

    # assemble & return result
    return join_bytes(
        calc_block(keyed_hmac, keyed_hmac(salt + _pack_uint32(i)), rounds)
        for i in irange(1, block_count + 1)
    )[:keylen]
예제 #41
0
파일: digest.py 프로젝트: javierrami/GAM
    def _get_pbkdf2_looper(digest_size):
        """
        We want a helper function which performs equivalent of the following::

          def helper(keyed_hmac, digest, rounds):
              accum = digest
              for _ in irange(rounds - 1):
                  digest = keyed_hmac(digest)
                  accum ^= digest
              return accum

        However, no efficient way to implement "bytes ^ bytes" in python.
        Instead, using approach where we dynamically compile a helper function based
        on digest size.  Instead of a single `accum` var, this helper breaks the digest
        into a series of integers.

        It stores these in a series of`accum_<i>` vars, and performs `accum ^= digest`
        by unpacking digest and perform xor for each "accum_<i> ^= digest_<i>".
        this keeps everything in locals, avoiding excessive list creation, encoding or decoding,
        etc.

        :param digest_size:
            digest size to compile for, in bytes. (must be multiple of 4).

        :return:
            helper function with call signature outlined above.
        """
        #
        # cache helpers
        #
        try:
            return _looper_cache[digest_size]
        except KeyError:
            pass

        #
        # figure out most efficient struct format to unpack digest into list of native ints
        #
        if _have_64_bit and not digest_size & 0x7:
            # digest size multiple of 8, on a 64 bit system -- use array of UINT64
            count = (digest_size >> 3)
            fmt = "=%dQ" % count
        elif not digest_size & 0x3:
            if _have_64_bit:
                # digest size multiple of 4, on a 64 bit system -- use array of UINT64 + 1 UINT32
                count = (digest_size >> 3)
                fmt = "=%dQI" % count
                count += 1
            else:
                # digest size multiple of 4, on a 32 bit system -- use array of UINT32
                count = (digest_size >> 2)
                fmt = "=%dI" % count
        else:
            # stopping here, cause no known hashes have digest size that isn't multiple of 4 bytes.
            # if needed, could go crazy w/ "H" & "B"
            raise NotImplementedError("unsupported digest size: %d" % digest_size)
        struct = Struct(fmt)

        #
        # build helper source
        #
        tdict = dict(
            digest_size=digest_size,
            accum_vars=", ".join("acc_%d" % i for i in irange(count)),
            digest_vars=", ".join("dig_%d" % i for i in irange(count)),
        )

        # head of function
        source = (
                        "def helper(keyed_hmac, digest, rounds):\n"
                        "    '''pbkdf2 loop helper for digest_size={digest_size}'''\n"
                        "    unpack_digest = struct.unpack\n"
                        "    {accum_vars} = unpack_digest(digest)\n"
                        "    for _ in irange(1, rounds):\n"
                        "        digest = keyed_hmac(digest)\n"
                        "        {digest_vars} = unpack_digest(digest)\n"
        ).format(**tdict)

        # xor digest
        for i in irange(count):
            source +=   "        acc_%d ^= dig_%d\n" % (i, i)

        # return result
        source +=       "    return struct.pack({accum_vars})\n".format(**tdict)

        #
        # compile helper
        #
        code = compile(source, "<generated by passlib.crypto.digest._get_pbkdf2_looper()>", "exec")
        gdict = dict(irange=irange, struct=struct)
        ldict = dict()
        eval(code, gdict, ldict)
        helper = ldict['helper']
        if __debug__:
            helper.__source__ = source

        #
        # store in cache
        #
        _looper_cache[digest_size] = helper
        return helper
예제 #42
0
    """
    global mock_fips_mode
    mock_fips_mode = enable
    lookup_hash.clear_cache()


# helper for UTs
if as_bool(os.environ.get("PASSLIB_MOCK_FIPS_MODE")):
    _set_mock_fips_mode()

#=============================================================================
# hmac utils
#=============================================================================

#: translation tables used by compile_hmac()
_TRANS_5C = join_byte_values((x ^ 0x5C) for x in irange(256))
_TRANS_36 = join_byte_values((x ^ 0x36) for x in irange(256))


def compile_hmac(digest, key, multipart=False):
    """
    This function returns an efficient HMAC function, hardcoded with a specific digest & key.
    It can be used via ``hmac = compile_hmac(digest, key)``.

    :arg digest:
        digest name or constructor.

    :arg key:
        secret key as :class:`!bytes` or :class:`!unicode` (unicode will be encoded using utf-8).

    :param multipart:
예제 #43
0
def write_expand_function(write, indent=0):
    write(
        indent,
        """\
        def expand(self, key_words):
            \"""unrolled version of blowfish key expansion\"""
            #assert len(key_words) >= 18, "size of key_words must be >= 18"

            P, S = self.P, self.S
            S0, S1, S2, S3 = S

            #=============================================================
            # integrate key
            #=============================================================
        """,
    )
    for i in irange(18):
        write(
            indent + 1,
            """\
            p%(i)d = P[%(i)d] ^ key_words[%(i)d]
        """,
            i=i,
        )
    write(
        indent + 1,
        """\

        #=============================================================
        # update P
        #=============================================================

        #------------------------------------------------
        # update P[0] and P[1]
        #------------------------------------------------
        l, r = p0, 0

        """,
    )

    render_encipher(write, indent + 1)

    write(
        indent + 1,
        """\

        p0, p1 = l, r = r ^ p17, l

        """,
    )

    for i in irange(2, 18, 2):
        write(
            indent + 1,
            """\
            #------------------------------------------------
            # update P[%(i)d] and P[%(i1)d]
            #------------------------------------------------
            l ^= p0

            """,
            i=i,
            i1=i + 1,
        )

        render_encipher(write, indent + 1)

        write(
            indent + 1,
            """\
            p%(i)d, p%(i1)d = l, r = r ^ p17, l

            """,
            i=i,
            i1=i + 1,
        )

    write(
        indent + 1,
        """\

        #------------------------------------------------
        # save changes to original P array
        #------------------------------------------------
        P[:] = (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9,
          p10, p11, p12, p13, p14, p15, p16, p17)

        #=============================================================
        # update S
        #=============================================================

        for box in S:
            j = 0
            while j < 256:
                l ^= p0

        """,
    )

    render_encipher(write, indent + 3)

    write(
        indent + 3,
        """\

                box[j], box[j+1] = l, r = r ^ p17, l
                j += 2
        """,
    )
예제 #44
0
def varlist(name, count):
    return ", ".join(name + str(x) for x in irange(count))
예제 #45
0
    def _get_pbkdf2_looper(digest_size):
        """
        We want a helper function which performs equivalent of the following::

          def helper(keyed_hmac, digest, rounds):
              accum = digest
              for _ in irange(rounds - 1):
                  digest = keyed_hmac(digest)
                  accum ^= digest
              return accum

        However, no efficient way to implement "bytes ^ bytes" in python.
        Instead, using approach where we dynamically compile a helper function based
        on digest size.  Instead of a single `accum` var, this helper breaks the digest
        into a series of integers.

        It stores these in a series of`accum_<i>` vars, and performs `accum ^= digest`
        by unpacking digest and perform xor for each "accum_<i> ^= digest_<i>".
        this keeps everything in locals, avoiding excessive list creation, encoding or decoding,
        etc.

        :param digest_size:
            digest size to compile for, in bytes. (must be multiple of 4).

        :return:
            helper function with call signature outlined above.
        """
        #
        # cache helpers
        #
        try:
            return _looper_cache[digest_size]
        except KeyError:
            pass

        #
        # figure out most efficient struct format to unpack digest into list of native ints
        #
        if _have_64_bit and not digest_size & 0x7:
            # digest size multiple of 8, on a 64 bit system -- use array of UINT64
            count = (digest_size >> 3)
            fmt = "=%dQ" % count
        elif not digest_size & 0x3:
            if _have_64_bit:
                # digest size multiple of 4, on a 64 bit system -- use array of UINT64 + 1 UINT32
                count = (digest_size >> 3)
                fmt = "=%dQI" % count
                count += 1
            else:
                # digest size multiple of 4, on a 32 bit system -- use array of UINT32
                count = (digest_size >> 2)
                fmt = "=%dI" % count
        else:
            # stopping here, cause no known hashes have digest size that isn't multiple of 4 bytes.
            # if needed, could go crazy w/ "H" & "B"
            raise NotImplementedError("unsupported digest size: %d" %
                                      digest_size)
        struct = Struct(fmt)

        #
        # build helper source
        #
        tdict = dict(
            digest_size=digest_size,
            accum_vars=", ".join("acc_%d" % i for i in irange(count)),
            digest_vars=", ".join("dig_%d" % i for i in irange(count)),
        )

        # head of function
        source = (
            "def helper(keyed_hmac, digest, rounds):\n"
            "    '''pbkdf2 loop helper for digest_size={digest_size}'''\n"
            "    unpack_digest = struct.unpack\n"
            "    {accum_vars} = unpack_digest(digest)\n"
            "    for _ in irange(1, rounds):\n"
            "        digest = keyed_hmac(digest)\n"
            "        {digest_vars} = unpack_digest(digest)\n").format(**tdict)

        # xor digest
        for i in irange(count):
            source += "        acc_%d ^= dig_%d\n" % (i, i)

        # return result
        source += "    return struct.pack({accum_vars})\n".format(**tdict)

        #
        # compile helper
        #
        code = compile(
            source,
            "<generated by passlib.crypto.digest._get_pbkdf2_looper()>",
            "exec")
        gdict = dict(irange=irange, struct=struct)
        ldict = dict()
        eval(code, gdict, ldict)
        helper = ldict['helper']
        if __debug__:
            helper.__source__ = source

        #
        # store in cache
        #
        _looper_cache[digest_size] = helper
        return helper
예제 #46
0
파일: pwd.py 프로젝트: cutso/passlib
 def __call__(self, count=None):
     """create and return passwords"""
     if count is None:
         return self._gen()
     else:
         return [self._gen() for _ in irange(count)]
예제 #47
0
파일: pwd.py 프로젝트: javierrami/GAM
 def __next__(self):
     words = (self.rng.choice(self.words) for _ in irange(self.length))
     return self.sep.join(words)
예제 #48
0
파일: pwd.py 프로젝트: Sriramg89/Restaurant
 def __next__(self):
     words = (self.rng.choice(self.words) for _ in irange(self.length))
     return self.sep.join(words)
예제 #49
0
파일: pbkdf2.py 프로젝트: Glottotopia/aagd
    # else we've done what we can
    warn("norm_hash_name(): unknown hash: %r" % (orig,), PasslibRuntimeWarning)
    name2 = name.replace("-", "")
    row = _nhn_cache[orig] = (name2, name)
    return row[idx]

# TODO: get_hash() func which wraps norm_hash_name(), hashlib.<attr>, and hashlib.new

#=============================================================================
# general prf lookup
#=============================================================================
_BNULL = b('\x00')
_XY_DIGEST = b(',\x1cb\xe0H\xa5\x82M\xfb>\xd6\x98\xef\x8e\xf9oQ\x85\xa3i')

_trans_5C = join_byte_values((x ^ 0x5C) for x in irange(256))
_trans_36 = join_byte_values((x ^ 0x36) for x in irange(256))

def _get_hmac_prf(digest):
    "helper to return HMAC prf for specific digest"
    def tag_wrapper(prf):
        prf.__name__ = "hmac_" + digest
        prf.__doc__ = ("hmac_%s(key, msg) -> digest;"
                       " generated by passlib.utils.pbkdf2.get_prf()" %
                       digest)

    if _EVP and digest == "sha1":
        # use m2crypto function directly for sha1, since that's it's default digest
        try:
            result = _EVP.hmac(b('x'),b('y'))
        except ValueError: # pragma: no cover
예제 #50
0
def pbkdf2_hmac(digest, secret, salt, rounds, keylen=None):
    """pkcs#5 password-based key derivation v2.0 using HMAC + arbitrary digest.

    :arg digest:
        digest name or constructor.

    :arg secret:
        passphrase to use to generate key.
        may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8).

    :arg salt:
        salt string to use when generating key.
        may be :class:`!bytes` or :class:`unicode` (encoded using UTF-8).

    :param rounds:
        number of rounds to use to generate key.

    :arg keylen:
        number of bytes to generate.
        if omitted / ``None``, will use digest's native output size.

    :returns:
        raw bytes of generated key

    .. versionchanged:: 1.7

        This function will use the first available of the following backends:

        * `fastpbk2 <https://pypi.python.org/pypi/fastpbkdf2>`_
        * :func:`hashlib.pbkdf2_hmac` (only available in py2 >= 2.7.8, and py3 >= 3.4)
        * builtin pure-python backend

        See :data:`passlib.crypto.digest.PBKDF2_BACKENDS` to determine
        which backend(s) are in use.
    """
    # validate secret & salt
    secret = to_bytes(secret, param="secret")
    salt = to_bytes(salt, param="salt")

    # resolve digest
    digest_info = lookup_hash(digest)
    digest_size = digest_info.digest_size

    # validate rounds
    if not isinstance(rounds, int_types):
        raise exc.ExpectedTypeError(rounds, "int", "rounds")
    if rounds < 1:
        raise ValueError("rounds must be at least 1")

    # validate keylen
    if keylen is None:
        keylen = digest_size
    elif not isinstance(keylen, int_types):
        raise exc.ExpectedTypeError(keylen, "int or None", "keylen")
    elif keylen < 1:
        # XXX: could allow keylen=0, but want to be compat w/ stdlib
        raise ValueError("keylen must be at least 1")

    # find smallest block count s.t. keylen <= block_count * digest_size;
    # make sure block count won't overflow (per pbkdf2 spec)
    # this corresponds to throwing error if keylen > digest_size * MAX_UINT32
    # NOTE: stdlib will throw error at lower bound (keylen > MAX_SINT32)
    # NOTE: have do this before other backends checked, since fastpbkdf2 raises wrong error
    #       (InvocationError, not OverflowError)
    block_count = (keylen + digest_size - 1) // digest_size
    if block_count > MAX_UINT32:
        raise OverflowError("keylen too long for digest")

    #
    # check for various high-speed backends
    #

    # ~3x faster than pure-python backend
    # NOTE: have to do this after above guards since fastpbkdf2 lacks bounds checks.
    if digest_info.supported_by_fastpbkdf2:
        return _fast_pbkdf2_hmac(digest_info.name, secret, salt, rounds,
                                 keylen)

    # ~1.4x faster than pure-python backend
    # NOTE: have to do this after fastpbkdf2 since hashlib-ssl is slower,
    #       will support larger number of hashes.
    if digest_info.supported_by_hashlib_pbkdf2:
        return _stdlib_pbkdf2_hmac(digest_info.name, secret, salt, rounds,
                                   keylen)

    #
    # otherwise use our own implementation
    #

    # generated keyed hmac
    keyed_hmac = compile_hmac(digest, secret)

    # get helper to calculate pbkdf2 inner loop efficiently
    calc_block = _get_pbkdf2_looper(digest_size)

    # assemble & return result
    return join_bytes(
        calc_block(keyed_hmac, keyed_hmac(salt + _pack_uint32(i)), rounds)
        for i in irange(1, block_count + 1))[:keylen]
예제 #51
0
def write_expand_function(write, indent=0):
    write(
        indent, """\
        def expand(self, key_words):
            \"""unrolled version of blowfish key expansion\"""
            ##assert len(key_words) >= 18, "size of key_words must be >= 18"

            P, S = self.P, self.S
            S0, S1, S2, S3 = S

            #=============================================================
            # integrate key
            #=============================================================
        """)
    for i in irange(18):
        write(indent + 1,
              """\
            p%(i)d = P[%(i)d] ^ key_words[%(i)d]
        """,
              i=i)
    write(
        indent + 1, """\

        #=============================================================
        # update P
        #=============================================================

        #------------------------------------------------
        # update P[0] and P[1]
        #------------------------------------------------
        l, r = p0, 0

        """)

    render_encipher(write, indent + 1)

    write(indent + 1, """\

        p0, p1 = l, r = r ^ p17, l

        """)

    for i in irange(2, 18, 2):
        write(indent + 1,
              """\
            #------------------------------------------------
            # update P[%(i)d] and P[%(i1)d]
            #------------------------------------------------
            l ^= p0

            """,
              i=i,
              i1=i + 1)

        render_encipher(write, indent + 1)

        write(indent + 1,
              """\
            p%(i)d, p%(i1)d = l, r = r ^ p17, l

            """,
              i=i,
              i1=i + 1)

    write(
        indent + 1, """\

        #------------------------------------------------
        # save changes to original P array
        #------------------------------------------------
        P[:] = (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9,
          p10, p11, p12, p13, p14, p15, p16, p17)

        #=============================================================
        # update S
        #=============================================================

        for box in S:
            j = 0
            while j < 256:
                l ^= p0

        """)

    render_encipher(write, indent + 3)

    write(
        indent + 3, """\

                box[j], box[j+1] = l, r = r ^ p17, l
                j += 2
        """)
예제 #52
0
파일: digest.py 프로젝트: javierrami/GAM
            _stdlib_pbkdf2_hmac(self.name, b"p", b"s", 1)
            return True
        except ValueError:
            # "unsupported hash type"
            return False

    #=========================================================================
    # eoc
    #=========================================================================

#=============================================================================
# hmac utils
#=============================================================================

#: translation tables used by compile_hmac()
_TRANS_5C = join_byte_values((x ^ 0x5C) for x in irange(256))
_TRANS_36 = join_byte_values((x ^ 0x36) for x in irange(256))

def compile_hmac(digest, key, multipart=False):
    """
    This function returns an efficient HMAC function, hardcoded with a specific digest & key.
    It can be used via ``hmac = compile_hmac(digest, key)``.

    :arg digest:
        digest name or constructor.

    :arg key:
        secret key as :class:`!bytes` or :class:`!unicode` (unicode will be encoded using utf-8).

    :param multipart:
        request a multipart constructor instead (see return description).
예제 #53
0
    "The undiscover'd country, from whose bourn\n"
    "No traveller returns,--puzzles the will,\n"
    "And makes us rather bear those ills we have\n"
    "Than fly to others that we know not of?\n"
    "Thus conscience does make cowards of us all;\n"
    "And thus the native hue of resolution\n"
    "Is sicklied o'er with the pale cast of thought;\n"
    "And enterprises of great pith and moment,\n"
    "With this regard, their currents turn awry,\n"
    "And lose the name of action.--Soft you now!\n"
    "The fair Ophelia!--Nymph, in thy orisons\n"
    "Be all my sins remember'd.\n\x00"  # <- apparently null at end of C string is included (test vector won't pass otherwise)
)

# NOTE: these sequences are pre-calculated iteration ranges used by X & Y loops w/in rounds function below
xr = irange(7)
_XY_ROUNDS = [
    tuple((i, i, i + 3) for i in xr),  # xrounds 0
    tuple((i, i + 1, i + 4) for i in xr),  # xrounds 1
    tuple((i, i + 8, (i + 11) & 15) for i in xr),  # yrounds 0
    tuple((i, (i + 9) & 15, (i + 12) & 15) for i in xr),  # yrounds 1
]
del xr


def raw_sun_md5_crypt(secret, rounds, salt):
    "given secret & salt, return encoded sun-md5-crypt checksum"
    global MAGIC_HAMLET
    assert isinstance(secret, bytes)
    assert isinstance(salt, bytes)
예제 #54
0
파일: binary.py 프로젝트: dragoncsc/HDsite
#: all hex chars
HEX_CHARS = u("0123456789abcdefABCDEF")

#: upper case hex chars
UPPER_HEX_CHARS = u("0123456789ABCDEF")

#: lower case hex chars
LOWER_HEX_CHARS = u("0123456789abcdef")

#-------------------------------------------------------------
# byte strings
#-------------------------------------------------------------

#: special byte string containing all possible byte values
#: NOTE: for efficiency, this is treated as singleton by some of the code
ALL_BYTE_VALUES = join_byte_values(irange(256))

#: some string constants we reuse
B_EMPTY = b''
B_NULL = b'\x00'
B_EQUAL = b'='

#=============================================================================
# byte translation
#=============================================================================

#: base list used to compile byte translations
_TRANSLATE_SOURCE = list(iter_byte_chars(ALL_BYTE_VALUES))

def compile_byte_translation(mapping, source=None):
    """
예제 #55
0
파일: pbkdf2.py 프로젝트: Glottotopia/aagd
def pbkdf1(secret, salt, rounds, keylen=None, hash="sha1"):
    """pkcs#5 password-based key derivation v1.5

    :arg secret: passphrase to use to generate key
    :arg salt: salt string to use when generating key
    :param rounds: number of rounds to use to generate key
    :arg keylen: number of bytes to generate (if ``None``, uses digest's native size)
    :param hash:
        hash function to use. must be name of a hash recognized by hashlib.

    :returns:
        raw bytes of generated key

    .. note::

        This algorithm has been deprecated, new code should use PBKDF2.
        Among other limitations, ``keylen`` cannot be larger
        than the digest size of the specified hash.

    """
    # validate secret & salt
    if not isinstance(secret, bytes):
        raise ExpectedTypeError(secret, "bytes", "secret")
    if not isinstance(salt, bytes):
        raise ExpectedTypeError(salt, "bytes", "salt")

    # validate rounds
    if not isinstance(rounds, int_types):
        raise ExpectedTypeError(rounds, "int", "rounds")
    if rounds < 1:
        raise ValueError("rounds must be at least 1")

    # resolve hash
    try:
        hash_const = getattr(hashlib, hash)
    except AttributeError:
        # check for ssl hash
        # NOTE: if hash unknown, new() will throw ValueError, which we'd just
        #       reraise anyways; so instead of checking, we just let it get
        #       thrown during first use, below
        # TODO: use builtin md4 class if hashlib doesn't have it.
        def hash_const(msg):
            return hashlib.new(hash, msg)

    # prime pbkdf1 loop, get block size
    block = hash_const(secret + salt).digest()

    # validate keylen
    if keylen is None:
        keylen = len(block)
    elif not isinstance(keylen, int_types):
        raise ExpectedTypeError(keylen, "int or None", "keylen")
    elif keylen < 0:
        raise ValueError("keylen must be at least 0")
    elif keylen > len(block):
        raise ValueError("keylength too large for digest: %r > %r" %
                         (keylen, len(block)))

    # main pbkdf1 loop
    for _ in irange(rounds-1):
        block = hash_const(block).digest()
    return block[:keylen]
예제 #56
0
    "The undiscover'd country, from whose bourn\n"
    "No traveller returns,--puzzles the will,\n"
    "And makes us rather bear those ills we have\n"
    "Than fly to others that we know not of?\n"
    "Thus conscience does make cowards of us all;\n"
    "And thus the native hue of resolution\n"
    "Is sicklied o'er with the pale cast of thought;\n"
    "And enterprises of great pith and moment,\n"
    "With this regard, their currents turn awry,\n"
    "And lose the name of action.--Soft you now!\n"
    "The fair Ophelia!--Nymph, in thy orisons\n"
    "Be all my sins remember'd.\n\x00" #<- apparently null at end of C string is included (test vector won't pass otherwise)
)

# NOTE: these sequences are pre-calculated iteration ranges used by X & Y loops w/in rounds function below
xr = irange(7)
_XY_ROUNDS = [
    tuple((i,i,i+3) for i in xr), # xrounds 0
    tuple((i,i+1,i+4) for i in xr), # xrounds 1
    tuple((i,i+8,(i+11)&15) for i in xr), # yrounds 0
    tuple((i,(i+9)&15, (i+12)&15) for i in xr), # yrounds 1
]
del xr

def raw_sun_md5_crypt(secret, rounds, salt):
    """given secret & salt, return encoded sun-md5-crypt checksum"""
    global MAGIC_HAMLET
    assert isinstance(secret, bytes)
    assert isinstance(salt, bytes)

    # validate rounds
예제 #57
0
def varlist(name, count):
    return ", ".join(name + str(x) for x in irange(count))
예제 #58
0
def pbkdf1(secret, salt, rounds, keylen=None, hash="sha1"):
    """pkcs#5 password-based key derivation v1.5

    :arg secret: passphrase to use to generate key
    :arg salt: salt string to use when generating key
    :param rounds: number of rounds to use to generate key
    :arg keylen: number of bytes to generate (if ``None``, uses digest's native size)
    :param hash:
        hash function to use. must be name of a hash recognized by hashlib.

    :returns:
        raw bytes of generated key

    .. note::

        This algorithm has been deprecated, new code should use PBKDF2.
        Among other limitations, ``keylen`` cannot be larger
        than the digest size of the specified hash.

    """
    # validate secret & salt
    if not isinstance(secret, bytes):
        raise ExpectedTypeError(secret, "bytes", "secret")
    if not isinstance(salt, bytes):
        raise ExpectedTypeError(salt, "bytes", "salt")

    # validate rounds
    if not isinstance(rounds, int_types):
        raise ExpectedTypeError(rounds, "int", "rounds")
    if rounds < 1:
        raise ValueError("rounds must be at least 1")

    # resolve hash
    try:
        hash_const = getattr(hashlib, hash)
    except AttributeError:
        # check for ssl hash
        # NOTE: if hash unknown, new() will throw ValueError, which we'd just
        #       reraise anyways; so instead of checking, we just let it get
        #       thrown during first use, below
        # TODO: use builtin md4 class if hashlib doesn't have it.
        def hash_const(msg):
            return hashlib.new(hash, msg)

    # prime pbkdf1 loop, get block size
    block = hash_const(secret + salt).digest()

    # validate keylen
    if keylen is None:
        keylen = len(block)
    elif not isinstance(keylen, int_types):
        raise ExpectedTypeError(keylen, "int or None", "keylen")
    elif keylen < 0:
        raise ValueError("keylen must be at least 0")
    elif keylen > len(block):
        raise ValueError("keylength too large for digest: %r > %r" %
                         (keylen, len(block)))

    # main pbkdf1 loop
    for _ in irange(rounds-1):
        block = hash_const(block).digest()
    return block[:keylen]
예제 #59
0
    # else we've done what we can
    warn("norm_hash_name(): unknown hash: %r" % (orig,), PasslibRuntimeWarning)
    name2 = name.replace("-", "")
    row = _nhn_cache[orig] = (name2, name)
    return row[idx]

# TODO: get_hash() func which wraps norm_hash_name(), hashlib.<attr>, and hashlib.new

#=============================================================================
# general prf lookup
#=============================================================================
_BNULL = b('\x00')
_XY_DIGEST = b(',\x1cb\xe0H\xa5\x82M\xfb>\xd6\x98\xef\x8e\xf9oQ\x85\xa3i')

_trans_5C = join_byte_values((x ^ 0x5C) for x in irange(256))
_trans_36 = join_byte_values((x ^ 0x36) for x in irange(256))

def _get_hmac_prf(digest):
    "helper to return HMAC prf for specific digest"
    def tag_wrapper(prf):
        prf.__name__ = "hmac_" + digest
        prf.__doc__ = ("hmac_%s(key, msg) -> digest;"
                       " generated by passlib.utils.pbkdf2.get_prf()" %
                       digest)

    if _EVP and digest == "sha1":
        # use m2crypto function directly for sha1, since that's it's default digest
        try:
            result = _EVP.hmac(b('x'),b('y'))
        except ValueError: # pragma: no cover