def from_string(cls, hash): # NOTE: assuming hash will be unicode, or use ascii-compatible encoding. if isinstance(hash, unicode): hash = hash.encode("utf-8") if not isinstance(hash, bytes): raise exc.ExpectedStringError(hash, "hash") m = cls._hash_regex.match(hash) if not m: raise exc.MalformedHashError(cls) type, version, memory_cost, time_cost, parallelism, keyid, data, salt, digest = \ m.group("type", "version", "memory_cost", "time_cost", "parallelism", "keyid", "data", "salt", "digest") assert type in [b"i", b"d"], "unexpected type code: %r" % (type,) if keyid: raise NotImplementedError("argon2 'keyid' parameter not supported") return cls( type_d=(type == b"d"), version=int(version) if version else 0x10, memory_cost=int(memory_cost), rounds=int(time_cost), parallelism=int(parallelism), salt=b64s_decode(salt) if salt else None, data=b64s_decode(data) if data else None, checksum=b64s_decode(digest) if digest else None, )
def _parse_scrypt_string(cls, suffix): # break params, salt, and digest sections parts = suffix.split("$") if len(parts) == 3: params, salt, digest = parts elif len(parts) == 2: params, salt = parts digest = None else: raise uh.exc.MalformedHashError(cls, "malformed hash") # break params apart parts = params.split(",") if len(parts) == 3: nstr, bstr, pstr = parts assert nstr.startswith("ln=") assert bstr.startswith("r=") assert pstr.startswith("p=") else: raise uh.exc.MalformedHashError(cls, "malformed settings field") return dict( ident=IDENT_SCRYPT, rounds=int(nstr[3:]), block_size=int(bstr[2:]), parallelism=int(pstr[2:]), salt=b64s_decode(salt.encode("ascii")), checksum=b64s_decode(digest.encode("ascii")) if digest else None, )
def from_string(cls, hash): # NOTE: assuming hash will be unicode, or use ascii-compatible encoding. # TODO: switch to working w/ str or unicode if isinstance(hash, unicode): hash = hash.encode("utf-8") if not isinstance(hash, bytes): raise exc.ExpectedStringError(hash, "hash") m = cls._hash_regex.match(hash) if not m: raise exc.MalformedHashError(cls) type, version, memory_cost, time_cost, parallelism, keyid, data, salt, digest = \ m.group("type", "version", "memory_cost", "time_cost", "parallelism", "keyid", "data", "salt", "digest") if keyid: raise NotImplementedError("argon2 'keyid' parameter not supported") return cls( type=type.decode("ascii"), version=int(version) if version else 0x10, memory_cost=int(memory_cost), rounds=int(time_cost), parallelism=int(parallelism), salt=b64s_decode(salt) if salt else None, data=b64s_decode(data) if data else None, checksum=b64s_decode(digest) if digest else None, )
def test_b64s_decode(self): """b64s_decode()""" from passlib.utils.binary import b64s_decode # accept bytes or unicode self.assertEqual(b64s_decode(b"abc"), hb("69b7")) self.assertEqual(b64s_decode(u("abc")), hb("69b7")) # reject non-ascii unicode self.assertRaises(ValueError, b64s_decode, u("ab\xff")) # underlying a2b_ascii treats non-base64 chars as "Incorrect padding" self.assertRaises(TypeError, b64s_decode, b"ab\xff") self.assertRaises(TypeError, b64s_decode, b"ab!") self.assertRaises(TypeError, b64s_decode, u("ab!")) # insert correct padding, handle dirty padding bits self.assertEqual(b64s_decode(b"abcd"), hb("69b71d")) # 0 mod 4 self.assertRaises(ValueError, b64s_decode, b"abcde") # 1 mod 4 self.assertEqual(b64s_decode(b"abcdef"), hb("69b71d79")) # 2 mod 4, dirty padding bits self.assertEqual(b64s_decode(b"abcdeQ"), hb("69b71d79")) # 2 mod 4, clean padding bits self.assertEqual(b64s_decode(b"abcdefg"), hb("69b71d79f8")) # 3 mod 4, clean padding bits
def test_b64s_decode(self): """b64s_decode()""" from passlib.utils.binary import b64s_decode # accept bytes or unicode self.assertEqual(b64s_decode(b"abc"), hb("69b7")) self.assertEqual(b64s_decode(u("abc")), hb("69b7")) # reject non-ascii unicode self.assertRaises(ValueError, b64s_decode, u("ab\xff")) # underlying a2b_ascii treats non-base64 chars as "Incorrect padding" self.assertRaises(TypeError, b64s_decode, b"ab\xff") self.assertRaises(TypeError, b64s_decode, b"ab!") self.assertRaises(TypeError, b64s_decode, u("ab!")) # insert correct padding, handle dirty padding bits self.assertEqual(b64s_decode(b"abcd"), hb("69b71d")) # 0 mod 4 self.assertRaises(ValueError, b64s_decode, b"abcde") # 1 mod 4 self.assertEqual(b64s_decode(b"abcdef"), hb("69b71d79")) # 2 mod 4, dirty padding bits self.assertEqual(b64s_decode(b"abcdeQ"), hb("69b71d79")) # 2 mod 4, clean padding bits self.assertEqual(b64s_decode(b"abcdefg"), hb("69b71d79f8")) # 3 mod 4, clean padding bits