示例#1
0
def _raw_sha2_crypt(pwd, salt, rounds, use_512=False):
    if isinstance(pwd, unicode):
        pwd = pwd.encode('utf-8')
    if _BNULL in pwd:
        raise uh.exc.NullPasswordError(
            sha512_crypt if use_512 else sha256_crypt)
    pwd_len = len(pwd)
    salt = salt.encode('ascii')
    salt_len = len(salt)
    if use_512:
        hash_const = hashlib.sha512
        transpose_map = _512_transpose_map
    else:
        hash_const = hashlib.sha256
        transpose_map = _256_transpose_map
    db = hash_const(pwd + salt + pwd).digest()
    a_ctx = hash_const(pwd + salt)
    a_ctx_update = a_ctx.update
    a_ctx_update(repeat_string(db, pwd_len))
    i = pwd_len
    while i:
        a_ctx_update(db if i & 1 else pwd)
        i >>= 1

    da = a_ctx.digest()
    if pwd_len < 96:
        dp = repeat_string(hash_const(pwd * pwd_len).digest(), pwd_len)
    else:
        tmp_ctx = hash_const(pwd)
        tmp_ctx_update = tmp_ctx.update
        i = pwd_len - 1
        while i:
            tmp_ctx_update(pwd)
            i -= 1

        dp = repeat_string(tmp_ctx.digest(), pwd_len)
    ds = hash_const(salt * (16 + byte_elem_value(da[0]))).digest()[:salt_len]
    dp_dp = dp + dp
    dp_ds = dp + ds
    perms = [dp, dp_dp, dp_ds, dp_ds + dp, ds + dp, ds + dp_dp]
    data = [(perms[even], perms[odd]) for even, odd in _c_digest_offsets]
    dc = da
    blocks, tail = divmod(rounds, 42)
    while blocks:
        for even, odd in data:
            dc = hash_const(odd + hash_const(dc + even).digest()).digest()

        blocks -= 1

    if tail:
        pairs = tail >> 1
        for even, odd in data[:pairs]:
            dc = hash_const(odd + hash_const(dc + even).digest()).digest()

        if tail & 1:
            dc = hash_const(dc + data[pairs][0]).digest()
    return h64.encode_transposed_bytes(dc, transpose_map).decode('ascii')
示例#2
0
 def _calc_checksum(self, secret):
     asa = self._is_asa
     if isinstance(secret, unicode):
         secret = secret.encode('utf-8')
     spoil_digest = None
     if len(secret) > self.truncate_size:
         if self.use_defaults:
             msg = 'Password too long (%s allows at most %d bytes)' % (
                 self.name, self.truncate_size)
             raise uh.exc.PasswordSizeError(self.truncate_size, msg=msg)
         else:
             spoil_digest = secret + _DUMMY_BYTES
     user = self.user
     if user:
         if isinstance(user, unicode):
             user = user.encode('utf-8')
         if not asa or len(secret) < 28:
             secret += repeat_string(user, 4)
     if asa and len(secret) > 16:
         pad_size = 32
     else:
         pad_size = 16
     secret = right_pad_string(secret, pad_size)
     if spoil_digest:
         secret += spoil_digest
     digest = md5(secret).digest()
     digest = join_byte_elems(c for i, c in enumerate(digest) if i + 1 & 3)
     return h64.encode_bytes(digest).decode('ascii')
示例#3
0
 def _norm_digest_args(cls, secret, ident, new=False):
     if isinstance(secret, unicode):
         secret = secret.encode('utf-8')
     uh.validate_secret(secret)
     if new:
         cls._check_truncate_policy(secret)
     if _BNULL in secret:
         raise uh.exc.NullPasswordError(cls)
     if cls._has_2a_wraparound_bug and len(secret) >= 255:
         secret = secret[:72]
     if ident == IDENT_2A:
         pass
     else:
         if ident == IDENT_2B:
             if cls._lacks_2b_support:
                 ident = cls._fallback_ident
         else:
             if ident == IDENT_2Y:
                 if cls._lacks_2y_support:
                     ident = cls._fallback_ident
             else:
                 if ident == IDENT_2:
                     if cls._lacks_20_support:
                         if secret:
                             secret = repeat_string(secret, 72)
                         ident = cls._fallback_ident
                 else:
                     if ident == IDENT_2X:
                         raise RuntimeError(
                             '$2x$ hashes not currently supported by passlib'
                         )
                     else:
                         raise AssertionError('unexpected ident value: %r' %
                                              ident)
     return (secret, ident)
示例#4
0
 def check_bcryptor(secret, hash):
     secret = to_native_str(secret,
                            self.FuzzHashGenerator.password_encoding)
     if hash.startswith((IDENT_2B, IDENT_2Y)):
         hash = IDENT_2A + hash[4:]
     else:
         if hash.startswith(IDENT_2):
             hash = IDENT_2A + hash[3:]
             if secret:
                 secret = repeat_string(secret, 72)
     return Engine(False).hash_key(secret, hash) == hash
示例#5
0
 def generate(self):
     opts = super(_bcrypt_test.FuzzHashGenerator, self).generate()
     secret = opts['secret']
     other = opts['other']
     settings = opts['settings']
     ident = settings.get('ident')
     if ident == IDENT_2X:
         del settings['ident']
     else:
         if ident == IDENT_2 and other and repeat_string(
                 to_bytes(other), len(
                     to_bytes(secret))) == to_bytes(secret):
             opts['secret'], opts['other'] = self.random_password_pair()
     return opts
示例#6
0
 def check_bcrypt(secret, hash):
     secret = to_bytes(secret, self.FuzzHashGenerator.password_encoding)
     if hash.startswith(IDENT_2B):
         hash = IDENT_2A + hash[4:]
     else:
         if hash.startswith(IDENT_2):
             hash = IDENT_2A + hash[3:]
             if secret:
                 secret = repeat_string(secret, 72)
         else:
             if hash.startswith(
                     IDENT_2Y) and bcrypt.__version__ == '3.0.0':
                 hash = IDENT_2B + hash[4:]
         hash = to_bytes(hash)
         try:
             return bcrypt.hashpw(secret, hash) == hash
         except ValueError:
             raise ValueError('bcrypt rejected hash: %r (secret=%r)' %
                              (hash, secret))
示例#7
0
def _raw_md5_crypt(pwd, salt, use_apr=False):
    if isinstance(pwd, unicode):
        pwd = pwd.encode('utf-8')
    if _BNULL in pwd:
        raise uh.exc.NullPasswordError(md5_crypt)
    pwd_len = len(pwd)
    salt = salt.encode('ascii')
    if use_apr:
        magic = _APR_MAGIC
    else:
        magic = _MD5_MAGIC
    db = md5(pwd + salt + pwd).digest()
    a_ctx = md5(pwd + magic + salt)
    a_ctx_update = a_ctx.update
    a_ctx_update(repeat_string(db, pwd_len))
    i = pwd_len
    evenchar = pwd[:1]
    while i:
        a_ctx_update(_BNULL if i & 1 else evenchar)
        i >>= 1

    da = a_ctx.digest()
    pwd_pwd = pwd + pwd
    pwd_salt = pwd + salt
    perms = [
        pwd, pwd_pwd, pwd_salt, pwd_salt + pwd, salt + pwd, salt + pwd_pwd
    ]
    data = [(perms[even], perms[odd]) for even, odd in _c_digest_offsets]
    dc = da
    blocks = 23
    while blocks:
        for even, odd in data:
            dc = md5(odd + md5(dc + even).digest()).digest()

        blocks -= 1

    for even, odd in data[:17]:
        dc = md5(odd + md5(dc + even).digest()).digest()

    return h64.encode_transposed_bytes(dc, _transpose_map).decode('ascii')
示例#8
0
 def key_to_words(data, size=18):
     dlen = len(data)
     if not dlen:
         return [0] * size
     data = repeat_string(data, size << 2)
     return struct.unpack('>%dI' % (size, ), data)
示例#9
0
class _bcrypt_sha256_test(HandlerCase):
    handler = hash.bcrypt_sha256
    reduce_default_rounds = True
    forbidden_characters = None
    fuzz_salts_need_bcrypt_repair = True
    alt_safe_crypt_handler = hash.bcrypt
    has_os_crypt_fallback = True
    known_correct_hashes = [
        ('',
         '$bcrypt-sha256$2a,5$E/e/2AOhqM5W/KJTFQzLce$F6dYSxOdAEoJZO2eoHUZWZljW/e0TXO'
         ),
        ('password',
         '$bcrypt-sha256$2a,5$5Hg1DKFqPE8C2aflZ5vVoe$12BjNE0p7axMg55.Y/mHsYiVuFBDQyu'
         ),
        (UPASS_TABLE,
         '$bcrypt-sha256$2a,5$.US1fQ4TQS.ZTz/uJ5Kyn.$QNdPDOTKKT5/sovNz1iWg26quOU4Pje'
         ),
        (UPASS_TABLE.encode('utf-8'),
         '$bcrypt-sha256$2a,5$.US1fQ4TQS.ZTz/uJ5Kyn.$QNdPDOTKKT5/sovNz1iWg26quOU4Pje'
         ),
        ('password',
         '$bcrypt-sha256$2b,5$5Hg1DKFqPE8C2aflZ5vVoe$12BjNE0p7axMg55.Y/mHsYiVuFBDQyu'
         ),
        (UPASS_TABLE,
         '$bcrypt-sha256$2b,5$.US1fQ4TQS.ZTz/uJ5Kyn.$QNdPDOTKKT5/sovNz1iWg26quOU4Pje'
         ),
        (repeat_string('abc123', 72),
         '$bcrypt-sha256$2b,5$X1g1nh3g0v4h6970O68cxe$r/hyEtqJ0teqPEmfTLoZ83ciAI1Q74.'
         ),
        (repeat_string('abc123', 72) + 'qwr',
         '$bcrypt-sha256$2b,5$X1g1nh3g0v4h6970O68cxe$021KLEif6epjot5yoxk0m8I0929ohEa'
         ),
        (repeat_string('abc123', 72) + 'xyz',
         '$bcrypt-sha256$2b,5$X1g1nh3g0v4h6970O68cxe$7.1kgpHduMGEjvM3fX6e/QCvfn6OKja'
         )
    ]
    known_correct_configs = [(
        '$bcrypt-sha256$2a,5$5Hg1DKFqPE8C2aflZ5vVoe', 'password',
        '$bcrypt-sha256$2a,5$5Hg1DKFqPE8C2aflZ5vVoe$12BjNE0p7axMg55.Y/mHsYiVuFBDQyu'
    )]
    known_malformed_hashes = [
        '$bcrypt-sha256$2a,5$5Hg1DKF!PE8C2aflZ5vVoe$12BjNE0p7axMg55.Y/mHsYiVuFBDQyu',
        '$bcrypt-sha256$2c,5$5Hg1DKFqPE8C2aflZ5vVoe$12BjNE0p7axMg55.Y/mHsYiVuFBDQyu',
        '$bcrypt-sha256$2x,5$5Hg1DKFqPE8C2aflZ5vVoe$12BjNE0p7axMg55.Y/mHsYiVuFBDQyu',
        '$bcrypt-sha256$2a,05$5Hg1DKFqPE8C2aflZ5vVoe$12BjNE0p7axMg55.Y/mHsYiVuFBDQyu',
        '$bcrypt-sha256$2a,5$5Hg1DKFqPE8C2aflZ5vVoe$'
    ]

    def setUp(self):
        if TEST_MODE('full') and self.backend == 'builtin':
            key = 'PASSLIB_BUILTIN_BCRYPT'
            orig = os.environ.get(key)
            if orig:
                self.addCleanup(os.environ.__setitem__, key, orig)
            else:
                self.addCleanup(os.environ.__delitem__, key)
            os.environ[key] = 'enabled'
        super(_bcrypt_sha256_test, self).setUp()
        warnings.filterwarnings(
            'ignore', '.*backend is vulnerable to the bsd wraparound bug.*')

    def populate_settings(self, kwds):
        if self.backend == 'builtin':
            kwds.setdefault('rounds', 4)
        super(_bcrypt_sha256_test, self).populate_settings(kwds)

    def test_30_HasManyIdents(self):
        raise self.skipTest('multiple idents not supported')

    def test_30_HasOneIdent(self):
        handler = self.handler
        handler(use_defaults=True)
        self.assertRaises(ValueError, handler, ident='$2y$', use_defaults=True)

    class FuzzHashGenerator(HandlerCase.FuzzHashGenerator):
        def random_rounds(self):
            return self.randintgauss(5, 8, 6, 1)