Skip to content

hashes that are easy to read built to your specification

Notifications You must be signed in to change notification settings

apowers313/pyFlexiHumanHash

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

flexi-human-hash

There are lots of packages that convert big random numbers to something readable or create random strings from words, but none are as flexible as I wanted. I created this to be a highly controllable version of the other human hash packages.

Note that this package is well tested and fairly stable, so don't expect to see many changes unless new GitHub issues are opened.

Usage

Install:

pip install flexi-human-hash

Use

from flexihumanhash import FlexiHumanHash
fhh = FlexiHumanHash("{{adj}}-{{noun}}")
print(fhh.hash("hello world"))
# Expected output: "crookedest-valentines"
print(fhh.hash(42))
# Expected output: "worthiest-omelettes"
print(fhh.hash(bytes([0, 1, 3, 5])))
# Expected output: "manila-dive"

Features:

  • Multiple dictionaries: nouns, adjectives, verbs, first name, last name, city
  • Full control over formatting: separators, spaces, additional words, upper case, lower case, numbers
  • Random: You provide the source of randomness (hash, string, uuid, etc) or one will be provided for you
  • Entropy reporting: understand how likely hash collisions are for your given format
  • Extendable: add your own dictionaries and formatting transforms
  • Jinja2-based templating for more features and control

API Examples:

Simple hash converted into a string

fhh = FlexiHumanHash("{{adj}}-{{adj}}-{{noun}}-{{decimal(4)}}")
str(fhh.hash("hello world."))
# Expected output: "manuscript-anatomically-naps-5303"

Another format, random number provided for you

fhh = FlexiHumanHash("{{adj}}, {{adj}} {{noun}} {{hex(4)}}")
print(fhh.rand())
# Expected output: "frolicsome, intelligent mix 89d5"

Another format, md5 hash a string for random numbers, transform names to all caps

fhh = FlexiHumanHash("{{first-name|capitalize}}-{{last-name|capitalize}}-{{decimal(6)}}")
fhh.hash("this is my password...", alg="md5")
# Expected output: "CHARITY-ESMERELDA-903817"
# supported hash algorithms: blake2b (default), blake2s, shake128, shake256, md5, sha1, sha224, sha256, sha384, sha512, sha3-224, sha3-256, sha3-384, sha3-512

Report how much entropy is used for a format to help understand likelihood of collisions

fhh = FlexiHumanHash("{{first-name uppercase}}-{{last-name uppercase}}-{{decimal(6)}}")
print(fhh.entropy)
# Expected output (note BigInt): "70368744177664n"
print(f"Number of combinations: {fhh.entropy:,}")
# Expected output: "Number of combinations: 70,368,744,177,664"
print(f"Entropy: 2^${fhh.entropy_bits}")
# Expected output: "Entropy: 2^46"

Add a dictionary from a file

from pathlib import Path

FlexiTextDict.from_file(Path("./foo.txt")) # file contains one word per line

Add a dictionary programmatically

@register_dict("decimal")
class FlexiDecimalDict(FlexiDict):
    def __init__(self, size: int = 4) -> None:
        self.sz = size

    def get_entry(self, n: int) -> str:
        return f"{n:0{self.sz}d}" 

    @property
    def size(self) -> int:
        ret: int = 10 ** self.sz
        return ret

    def preprocess(self, args: tuple[Any, ...], kwargs: dict[str, Any]) -> FlexiDecimalDict:
        # this gets called if parameters are passed in to Jinja
        return FlexiDecimalDict(*args, **kwargs)

Formats

  • noun
  • verb
  • adjective
  • decimal
    • A decimal number (zero through 10), defaults to four digits long but can be a specified number of digits long
    • {{decimal}} = 2394
    • {{decimal(8)}} = 84258973
    • {{decimal(1)}} = 7
  • hex
    • A hexidecimal number (zero through f), defaults to four nibbles / characters long but can be a specified number of digits long
    • {{hex}} = 3fa8
    • {{hex(8)}} = cb28f30d
    • {{hex(1)}} = e
  • femalename
    • 4,951 English capitalized female first names / given names from @stdlib
  • malename
    • 3,898 English capitalized male first names / given names from @stdlib
  • firstname
    • 8,849 English capitalized first names / given names (female-name and male-name combined)
  • lastname
  • city

Transforms

  • uppercase
    • Converts the first letter of a word to uppercase
    • e.g. "{{noun|upper}}" -> "Word"
  • lowercase
    • Converts an entire word to lowercase
    • e.g. "{{noun|lower}}" -> "word"
  • caps
    • Converts an entire word to uppercase
    • e.g. "{{noun|capitalize}}" -> "WORD"

Issues and pull requests always welcome, even if you're just saying hi. :)

Thank you to @stdlib, categorized-words, all-the-cities, and uuid-readable for their word lists.

About

hashes that are easy to read built to your specification

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published