def pbkdf2_hmac(digest, secret, salt, rounds, keylen=None): secret = to_bytes(secret, param='secret') salt = to_bytes(salt, param='salt') digest_info = lookup_hash(digest) digest_size = digest_info.digest_size if not isinstance(rounds, int_types): raise exc.ExpectedTypeError(rounds, 'int', 'rounds') if rounds < 1: raise ValueError('rounds must be at least 1') if keylen is None: keylen = digest_size else: if not isinstance(keylen, int_types): raise exc.ExpectedTypeError(keylen, 'int or None', 'keylen') else: if keylen < 1: raise ValueError('keylen must be at least 1') block_count = (keylen + digest_size - 1) // digest_size if block_count > MAX_UINT32: raise OverflowError('keylen too long for digest') if digest_info.supported_by_fastpbkdf2: return _fast_pbkdf2_hmac(digest_info.name, secret, salt, rounds, keylen) if digest_info.supported_by_hashlib_pbkdf2: return _stdlib_pbkdf2_hmac(digest_info.name, secret, salt, rounds, keylen) keyed_hmac = compile_hmac(digest, secret) calc_block = _get_pbkdf2_looper(digest_size) return join_bytes( calc_block(keyed_hmac, keyed_hmac(salt + _pack_uint32(i)), rounds) for i in irange(1, block_count + 1))[:keylen]
def genhash(cls, secret, config): uh.validate_secret(secret) secret = to_bytes(secret, 'utf-8') self = cls.from_string(config) if self.type_d: type = _argon2_cffi.low_level.Type.D else: type = _argon2_cffi.low_level.Type.I try: result = bascii_to_str( _argon2_cffi.low_level.hash_secret( type=type, memory_cost=self.memory_cost, time_cost=self.rounds, parallelism=self.parallelism, salt=to_bytes(self.salt), hash_len=self.checksum_size, secret=secret, version=self.version)) except _argon2_cffi.exceptions.HashingError as err: raise cls._adapt_backend_error(err, hash=config) if self.version == 16: result = result.replace('$v=16$', '$') return result
def pbkdf1(digest, secret, salt, rounds, keylen=None): const, digest_size, block_size = lookup_hash(digest) secret = to_bytes(secret, param='secret') salt = to_bytes(salt, param='salt') if not isinstance(rounds, int_types): raise exc.ExpectedTypeError(rounds, 'int', 'rounds') if rounds < 1: raise ValueError('rounds must be at least 1') if keylen is None: keylen = digest_size else: if not isinstance(keylen, int_types): raise exc.ExpectedTypeError(keylen, 'int or None', 'keylen') else: if keylen < 0: raise ValueError('keylen must be at least 0') else: if keylen > digest_size: raise ValueError( 'keylength too large for digest: %r > %r' % (keylen, digest_size)) block = secret + salt for _ in irange(rounds): block = const(block).digest() return block[:keylen]
def hash(cls, secret, user, realm, encoding=None): if not encoding: encoding = cls.default_encoding uh.validate_secret(secret) if isinstance(secret, unicode): secret = secret.encode(encoding) user = to_bytes(user, encoding, 'user') realm = to_bytes(realm, encoding, 'realm') data = render_bytes('%s:%s:%s', user, realm, secret) return hashlib.md5(data).hexdigest()
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
def hash(cls, secret): uh.validate_secret(secret) secret = to_bytes(secret, 'utf-8') try: return bascii_to_str( _argon2_cffi.low_level.hash_secret( type=_argon2_cffi.low_level.Type.I, memory_cost=cls.memory_cost, time_cost=cls.default_rounds, parallelism=cls.parallelism, salt=to_bytes(cls._generate_salt()), hash_len=cls.checksum_size, secret=secret)) except _argon2_cffi.exceptions.HashingError as err: raise cls._adapt_backend_error(err)
def verify(cls, secret, hash): uh.validate_secret(secret) secret = to_bytes(secret, 'utf-8') hash = to_bytes(hash, 'ascii') if hash.startswith('$argon2d$'): type = _argon2_cffi.low_level.Type.D else: type = _argon2_cffi.low_level.Type.I try: result = _argon2_cffi.low_level.verify_secret(hash, secret, type) return True except _argon2_cffi.exceptions.VerifyMismatchError: return False except _argon2_cffi.exceptions.VerificationError as err: raise cls._adapt_backend_error(err, hash=hash)
def _calc_checksum(self, secret): uh.validate_secret(secret) secret = to_bytes(secret, 'utf-8') if self.type_d: type = _argon2pure.ARGON2D else: type = _argon2pure.ARGON2I kwds = dict(password=secret, salt=self.salt, time_cost=self.rounds, memory_cost=self.memory_cost, parallelism=self.parallelism, tag_length=self.checksum_size, type_code=type, version=self.version) if self.max_threads > 0: kwds['threads'] = self.max_threads if self.pure_use_threads: kwds['use_threads'] = True if self.data: kwds['associated_data'] = self.data try: return _argon2pure.argon2(**kwds) except _argon2pure.Argon2Error as err: raise self._adapt_backend_error(err, self=self)
def _calc_checksum(self, secret): secret = to_bytes(secret, param='secret') return _scrypt.scrypt(secret, self.salt, n=1 << self.rounds, r=self.block_size, p=self.parallelism, keylen=self.checksum_size)
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))
def test_90_decode(self): from otp.ai.passlib.utils import to_unicode, to_bytes handler = self.handler for secret, hash in self.known_correct_hashes: usecret = to_unicode(secret) bsecret = to_bytes(secret) self.assertEqual(handler.decode(hash), usecret) self.assertEqual(handler.decode(hash, None), bsecret) self.assertRaises(UnicodeDecodeError, handler.decode, '0958EDC8A9F495F6F8A5FD', 'ascii') return
def test_13_whitespace(self): source = to_bytes( '\nuser2:pass2\nuser4:pass4\nuser7:pass7\r\n \t \nuser1:pass1\n # legacy users\n#user6:pass6\nuser5:pass5\n\n' ) ht = apache.HtpasswdFile.from_string(source) self.assertEqual(sorted(ht.users()), ['user1', 'user2', 'user4', 'user5', 'user7']) ht.set_hash('user4', 'althash4') self.assertEqual(sorted(ht.users()), ['user1', 'user2', 'user4', 'user5', 'user7']) ht.set_hash('user6', 'althash6') self.assertEqual( sorted(ht.users()), ['user1', 'user2', 'user4', 'user5', 'user6', 'user7']) ht.delete('user7') self.assertEqual(sorted(ht.users()), ['user1', 'user2', 'user4', 'user5', 'user6']) target = to_bytes( '\nuser2:pass2\nuser4:althash4\n \t \nuser1:pass1\n # legacy users\n#user6:pass6\nuser5:pass5\nuser6:althash6\n' ) self.assertEqual(ht.to_string(), target)
def test_to_bytes(self): from otp.ai.passlib.utils import to_bytes self.assertEqual(to_bytes(u('abc')), 'abc') self.assertEqual(to_bytes(u('\x00\xff')), '\x00\xc3\xbf') self.assertEqual(to_bytes(u('\x00\xff'), 'latin-1'), '\x00\xff') self.assertRaises(ValueError, to_bytes, u('\x00\xff'), 'ascii') self.assertEqual(to_bytes('abc'), 'abc') self.assertEqual(to_bytes('\x00\xff'), '\x00\xff') self.assertEqual(to_bytes('\x00\xc3\xbf'), '\x00\xc3\xbf') self.assertEqual(to_bytes('\x00\xc3\xbf', 'latin-1'), '\x00\xc3\xbf') self.assertEqual(to_bytes('\x00\xc3\xbf', 'latin-1', '', 'utf-8'), '\x00\xff') self.assertRaises(AssertionError, to_bytes, 'abc', None) self.assertRaises(TypeError, to_bytes, None) return
def test_01_from_path(self): path = self.mktemp() set_file(path, self.sample_config_1s) policy = CryptPolicy.from_path(path) self.assertEqual(policy.to_dict(), self.sample_config_1pd) set_file(path, self.sample_config_1s.replace('\n', '\r\n')) policy = CryptPolicy.from_path(path) self.assertEqual(policy.to_dict(), self.sample_config_1pd) uc2 = to_bytes(self.sample_config_1s, 'utf-16', source_encoding='utf-8') set_file(path, uc2) policy = CryptPolicy.from_path(path, encoding='utf-16') self.assertEqual(policy.to_dict(), self.sample_config_1pd)
def _parse_secret_pair(self, tag, value): if isinstance(tag, native_string_types): pass else: if isinstance(tag, int): tag = str(tag) else: raise TypeError('tag must be unicode/string: %r' % (tag, )) if not _tag_re.match(tag): raise ValueError('tag contains invalid characters: %r' % (tag, )) if not isinstance(value, bytes): value = to_bytes(value, param='secret %r' % (tag, )) if not value: raise ValueError('tag contains empty secret: %r' % (tag, )) return (tag, value)
def test_02_from_string(self): policy = CryptPolicy.from_string(self.sample_config_1s) self.assertEqual(policy.to_dict(), self.sample_config_1pd) policy = CryptPolicy.from_string( self.sample_config_1s.replace('\n', '\r\n')) self.assertEqual(policy.to_dict(), self.sample_config_1pd) data = to_unicode(self.sample_config_1s) policy = CryptPolicy.from_string(data) self.assertEqual(policy.to_dict(), self.sample_config_1pd) uc2 = to_bytes(self.sample_config_1s, 'utf-16', source_encoding='utf-8') policy = CryptPolicy.from_string(uc2, encoding='utf-16') self.assertEqual(policy.to_dict(), self.sample_config_1pd) policy = CryptPolicy.from_string(self.sample_config_4s) self.assertEqual(policy.to_dict(), self.sample_config_4pd)
def load(self, source, update=False, section='passlib', encoding='utf-8'): parse_keys = True if isinstance(source, unicode_or_bytes_types): if PY3: source = to_unicode(source, encoding, param='source') else: source = to_bytes(source, 'utf-8', source_encoding=encoding, param='source') source = self._parse_ini_stream( NativeStringIO(source), section, '<string passed to CryptContext.load()>') else: if isinstance(source, CryptContext): source = dict(source._config.iter_config(resolve=True)) parse_keys = False else: if not hasattr(source, 'items'): raise ExpectedTypeError(source, 'string or dict', 'source') if parse_keys: parse = self._parse_config_key source = dict( (parse(key), value) for key, value in iteritems(source)) if update and self._config is not None: if not source: return tmp = source source = dict(self._config.iter_config(resolve=True)) source.update(tmp) config = _CryptConfig(source) self._config = config self._reset_dummy_verify() self._get_record = config.get_record self._identify_record = config.identify_record if config.context_kwds: self.__dict__.pop('_strip_unused_context_kwds', None) else: self._strip_unused_context_kwds = None return
def compile_hmac(digest, key, multipart=False): digest_info = lookup_hash(digest) const, digest_size, block_size = digest_info if not isinstance(key, bytes): key = to_bytes(key, param='key') klen = len(key) if klen > block_size: key = const(key).digest() klen = digest_size if klen < block_size: key += '\x00' * (block_size - klen) _inner_copy = const(key.translate(_TRANS_36)).copy _outer_copy = const(key.translate(_TRANS_5C)).copy if multipart: def hmac(): inner = _inner_copy() def finalize(): outer = _outer_copy() outer.update(inner.digest()) return outer.digest() return (inner.update, finalize) else: def hmac(msg): inner = _inner_copy() inner.update(msg) outer = _outer_copy() outer.update(inner.digest()) return outer.digest() hmac.digest_info = digest_info return hmac
def load_string(self, data): data = to_bytes(data, self.encoding, 'data') self._mtime = 0 self._load_lines(BytesIO(data))
def _calc_checksum(self, secret): if isinstance(secret, unicode): secret = secret.encode('utf-8') user = to_bytes(self.user, 'utf-8', param='user') return str_to_uascii(md5(secret + user).hexdigest())