synchro/wordhash

Generate hashes in a human-readable format

v1.0.1 2020-10-21 17:33 UTC

This package is auto-updated.

Last update: 2024-04-22 02:08:58 UTC


README

By Marcus Bointon (@Synchro).

Test Status Type Coverage Total Downloads Latest Version License

Hashes are functions which map arbitrary-sized data into a fixed-size value. They are effectively very large numbers that are usually presented as hexadecimal (e.g. 5d41402abc4b2a76b9719d911017c592) or base-64 strings (e.g. XUFAKrxLKna5cZ2REBfFkg).

While it's easy for a computer to spot differences between such random-looking strings, it's much harder for us humans. For example, it's difficult for you to tell whether Mk3PAn3UowqTLEQfNlol6GsXPe+kuOWJSCU0cbgbcs8 and Mk3PAn3UowqTLEQfNlo16GsXPe+kuOWJSCU0cbgbcs8 are the same simply by looking at them (they're not!). Sometimes you want a human-readable hash function that makes differences more obvious, and that's what this library provides.

This library uses a truncated SHA-512/256 hash, and maps it into words drawn from a dictionary of 4096 common English words (a random subset of this dictionary). The string hello produces a hash of three-straps-solved-clutch-groove-abode, and that's fairly easy for humans to tell apart from three-straps-solved-lagoon-groove-abode.

Like all good hash functions, it produces wildly different output when presented with only very small differences in the input; hellp produces zlotys-south-remark-lier-rewind-accept.

You can choose how many words it generates (up to 21, equivalent to a 252-bit hash), and what separators appear between the words. It's also possible to substitute your own dictionary.

Security warning!

This is not intended for high-performance or cryptographic purposes; do not hash your passwords with this function!

Usage

All methods are static, so there's no need to create an instance.

The generate() method takes three parameters:

  • The string to hash (required)
  • The number of words to use (optional, between 1 and 21, defaults to 5, the equivalent of a 45-bit hash)
  • The separator to use between words (optional, defaults to -)
use Synchro\WordHash\WordHash;
echo WordHash::generate('hello!', 5, '_');

Example output

boil_rife_crepe_trait_carted

If you don't like the default words, or want to use emoji, HTML snippets, a different language, or something else, you can provide your own dictionary. It must contain exactly 4096 unique return-delimited words (see the provided dictionary.txt for reference). The words don't need to be in any particular order, though the provided one is sorted alphabetically.

WordHash::loadDictionary('/path/to/my/dictionary.txt');

Developer info

Requires PHP 7.4+

🧹 Lint the code using PHP Codesniffer:

composer lint

⚗️ Run static analysis using PHPStan or Psalm:

composer test:types
composer test:psalm

✅ Run unit tests using Pest

composer test:unit

🚀 Run the entire test suite:

composer test

Project layout based on Skeleton PHP by Nuno Maduro under the MIT license.