示例#1
0
def raw_sun_md5_crypt(secret, rounds, salt):
    global MAGIC_HAMLET
    if rounds <= 0:
        rounds = 0
    real_rounds = 4096 + rounds
    result = md5(secret + salt).digest()
    X_ROUNDS_0, X_ROUNDS_1, Y_ROUNDS_0, Y_ROUNDS_1 = _XY_ROUNDS
    round = 0
    while round < real_rounds:
        rval = [ byte_elem_value(c) for c in result ].__getitem__
        x = 0
        xrounds = X_ROUNDS_1 if rval(round >> 3 & 15) >> (round & 7) & 1 else X_ROUNDS_0
        for i, ia, ib in xrounds:
            a = rval(ia)
            b = rval(ib)
            v = rval(a >> b % 5 & 15) >> (b >> (a & 7) & 1)
            x |= (rval(v >> 3 & 15) >> (v & 7) & 1) << i

        y = 0
        yrounds = Y_ROUNDS_1 if rval(round + 64 >> 3 & 15) >> (round & 7) & 1 else Y_ROUNDS_0
        for i, ia, ib in yrounds:
            a = rval(ia)
            b = rval(ib)
            v = rval(a >> b % 5 & 15) >> (b >> (a & 7) & 1)
            y |= (rval(v >> 3 & 15) >> (v & 7) & 1) << i

        coin = (rval(x >> 3) >> (x & 7) ^ rval(y >> 3) >> (y & 7)) & 1
        h = md5(result)
        if coin:
            h.update(MAGIC_HAMLET)
        h.update(unicode(round).encode('ascii'))
        result = h.digest()
        round += 1

    return h64.encode_transposed_bytes(result, _chk_offsets)
示例#2
0
 def _sanitize(value, char=u('*')):
     if value is None:
         return
     if isinstance(value, bytes):
         from otp.ai.passlib.utils.binary import ab64_encode
         value = ab64_encode(value).decode('ascii')
     else:
         if not isinstance(value, unicode):
             value = unicode(value)
     size = len(value)
     clip = min(4, size // 8)
     return value[:clip] + char * (size - clip)
示例#3
0
def render_mc3(ident, rounds, salt, checksum, sep=u('$'), rounds_base=10):
    if rounds is None:
        rounds = u('')
    else:
        if rounds_base == 16:
            rounds = u('%x') % rounds
        else:
            rounds = unicode(rounds)
    if checksum:
        parts = [ident, rounds, sep, salt, sep, checksum]
    else:
        parts = [ident, rounds, sep, salt]
    return uascii_to_str(join_unicode(parts))
示例#4
0
    def from_string(cls, hash):
        hash = to_unicode(hash, 'ascii', 'hash')
        if hash.startswith(u('$md5$')):
            rounds = 0
            salt_idx = 5
        else:
            if hash.startswith(u('$md5,rounds=')):
                idx = hash.find(u('$'), 12)
                if idx == -1:
                    raise uh.exc.MalformedHashError(cls, 'unexpected end of rounds')
                rstr = hash[12:idx]
                try:
                    rounds = int(rstr)
                except ValueError:
                    raise uh.exc.MalformedHashError(cls, 'bad rounds')

                if rstr != unicode(rounds):
                    raise uh.exc.ZeroPaddedRoundsError(cls)
                if rounds == 0:
                    raise uh.exc.MalformedHashError(cls, 'explicit zero rounds')
                salt_idx = idx + 1
            else:
                raise uh.exc.InvalidHashError(cls)
        chk_idx = hash.rfind(u('$'), salt_idx)
        if chk_idx == -1:
            salt = hash[salt_idx:]
            chk = None
            bare_salt = True
        else:
            if chk_idx == len(hash) - 1:
                if chk_idx > salt_idx and hash[(-2)] == u('$'):
                    raise uh.exc.MalformedHashError(cls, "too many '$' separators")
                salt = hash[salt_idx:-1]
                chk = None
                bare_salt = False
            else:
                if chk_idx > 0 and hash[(chk_idx - 1)] == u('$'):
                    salt = hash[salt_idx:chk_idx - 1]
                    chk = hash[chk_idx + 1:]
                    bare_salt = False
                else:
                    salt = hash[salt_idx:chk_idx]
                    chk = hash[chk_idx + 1:]
                    bare_salt = True
        return cls(rounds=rounds, salt=salt, checksum=chk, bare_salt=bare_salt)
示例#5
0
文件: fshp.py 项目: perpi06/ttoffline
class fshp(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):
    name = 'fshp'
    setting_kwds = ('salt', 'salt_size', 'rounds', 'variant')
    checksum_chars = uh.PADDED_BASE64_CHARS
    ident = u('{FSHP')
    default_salt_size = 16
    max_salt_size = None
    default_rounds = 480000
    min_rounds = 1
    max_rounds = 4294967295L
    rounds_cost = 'linear'
    default_variant = 1
    _variant_info = {0: ('sha1', 20), 
       1: ('sha256', 32), 
       2: ('sha384', 48), 
       3: ('sha512', 64)}
    _variant_aliases = dict([ (unicode(k), k) for k in _variant_info ] + [ (v[0], k) for k, v in iteritems(_variant_info) ])

    @classmethod
    def using(cls, variant=None, **kwds):
        subcls = super(fshp, cls).using(**kwds)
        if variant is not None:
            subcls.default_variant = cls._norm_variant(variant)
        return subcls

    variant = None

    def __init__(self, variant=None, **kwds):
        self.use_defaults = kwds.get('use_defaults')
        if variant is not None:
            variant = self._norm_variant(variant)
        else:
            if self.use_defaults:
                variant = self.default_variant
            else:
                raise TypeError('no variant specified')
        self.variant = variant
        super(fshp, self).__init__(**kwds)
        return

    @classmethod
    def _norm_variant(cls, variant):
        if isinstance(variant, bytes):
            variant = variant.decode('ascii')
        if isinstance(variant, unicode):
            try:
                variant = cls._variant_aliases[variant]
            except KeyError:
                raise ValueError('invalid fshp variant')

        if not isinstance(variant, int):
            raise TypeError('fshp variant must be int or known alias')
        if variant not in cls._variant_info:
            raise ValueError('invalid fshp variant')
        return variant

    @property
    def checksum_alg(self):
        return self._variant_info[self.variant][0]

    @property
    def checksum_size(self):
        return self._variant_info[self.variant][1]

    _hash_regex = re.compile(u('\n            ^\n            \\{FSHP\n            (\\d+)\\| # variant\n            (\\d+)\\| # salt size\n            (\\d+)\\} # rounds\n            ([a-zA-Z0-9+/]+={0,3}) # digest\n            $'), re.X)

    @classmethod
    def from_string(cls, hash):
        hash = to_unicode(hash, 'ascii', 'hash')
        m = cls._hash_regex.match(hash)
        if not m:
            raise uh.exc.InvalidHashError(cls)
        variant, salt_size, rounds, data = m.group(1, 2, 3, 4)
        variant = int(variant)
        salt_size = int(salt_size)
        rounds = int(rounds)
        try:
            data = b64decode(data.encode('ascii'))
        except TypeError:
            raise uh.exc.MalformedHashError(cls)

        salt = data[:salt_size]
        chk = data[salt_size:]
        return cls(salt=salt, checksum=chk, rounds=rounds, variant=variant)

    def to_string(self):
        chk = self.checksum
        salt = self.salt
        data = bascii_to_str(b64encode(salt + chk))
        return '{FSHP%d|%d|%d}%s' % (self.variant, len(salt), self.rounds, data)

    def _calc_checksum(self, secret):
        if isinstance(secret, unicode):
            secret = secret.encode('utf-8')
        return pbkdf1(digest=self.checksum_alg, secret=self.salt, salt=secret, rounds=self.rounds, keylen=self.checksum_size)