
| Gem Version | Locale | Lexicon SHA |
|---|---|---|
| 0.3.0 | Miami | 4eea29f |
StoryKey
StoryKey is a Brainwallet inspired by BIP39 written in Ruby. It converts an arbitrary string of data, such as a cryptocurrency private key, into an English paragraph intended for longterm human memory. It also assists in decoding the story back into its original form.
Each story is provided in two formats:
- Humanized
- Version locale header ("In Miami I saw...")
- Enumerated phrases
- Colorized parts of speech (adjectives, verbs, nouns)
- Grammatical filler (articles, prepositions, conjunctions, punctuation)
- Tokenized
- Ordered list of unique tokens
- Space-delimited lowercase alphanumeric/dash
- Useful as a seed phrase for generating derivative keys
Features
- Encodes arbitrary length data from 1 to 512 bits (default 256)
- Includes checksum for integrity
- Includes version slug to ensure accurate decoding
- Uses a repeating English grammar to aid in mnemonics
- Uses a lexicon curated for mental visualization
- Avoids token repetition
- Provides interactive command-line recovery
Each token of the story, which may be a single word or short compound phrase, encodes 10 bits. The checksum length is variable based on the input size and space available in the last two tokens after accounting for a 4-bit footer. Here are a few example key sizes along with their respective story and checksum sizes.
| Key bits | Story tokens | Checksum bits |
|---|---|---|
| 64 | 8 | 12 |
| 128 | 14 | 8 |
| 192 | 21 | 14 |
| 256 | 27 | 10 |
| 384 | 40 | 12 |
| 512 | 53 | 14 |
An example key and its associated story and seed phrase are shown below.

Key:
CH8krjSZpGFmxnKo9QPqQEd9oMUkXnLcUhhEQFLrGCtg
Story:
In Miami I saw
1. a pensive Ellen Ripley surpass a musician,
2. an unhappy pug drink vodka with a dove,
3. an opulent Dante Alighieri diagnose Huckleberry Finn,
4. a frantic sister eat pretzels with Mozart,
5. a cunning meerkat trim a balloonist,
6. a rich ocelot step to John Wayne,
7. and a civilian convict a locust.
Seed Phrase:
pensive ellen-ripley surpass musician unhappy pug drink-vodka dove opulent dante-alighieri diagnose huckleberry-finn frantic sister eat-pretzels mozart cunning meerkat trim balloonist rich ocelot step john-wayne civilian convict locust
This paragraph or seed phrase can be deterministically decoded back into its original form using the same version of StoryKey. The locale of the story (e.g. Miami) identifies that version. During key recovery, an exception will be raised if:
- the
version slugdoes not match the current version of StoryKey - the embedded
checksumdoes not match the expected value
Lexicon Curation
The lexicon was selected using the following criteria:
- Anthropomorphism. All parts of speech - adjective, noun, and verb - must fit logically when composed into phrases. To accommodate, entries were selected based on how closely they could produce a mental image of commonly known anthropomorphic entities interacting with one another. To produce enough verbs, compound actions such as "eat breakfast" were also used.
- Adjectives: personal physical qualities, moods, colors, textures
- Nouns: famous people/characters, professions, animals
- Verbs: physical actions connecting subject/object, favoring transitive, sometimes compound
- Visualization. Entries should be concrete vs abstract and convey vivid mental imagery.
- Cultural acceptability. Reject sexually suggestive and other controversial imagery.
- Eliminate similar base words across parts of speech.
- Balance brevity with clarity.
Graphical Visualization
When AI becomes more common, StoryKey stories may be converted to graphical panels similar to the DALL-E Project. This will likely aid in mnemonics process for many users.
Installation
Add this line to your application's Gemfile:
gem 'story_key'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install story_key
Usage
This library may be used by calling Ruby methods or directly from the command line.
Command Line Usage
Invoke the command line interface by running bin/storykey.
StoryKey commands:
storykey decode [STORY] # Decode a story passed as an argument or from a file
storykey encode [KEY] # Encode a key passed as an argument or from a file
storykey help [COMMAND] # Describe available commands or one specific command
storykey new [BITSIZE] # Create a new key/story (default 256 bits, max 512)
storykey recover # Decode a story interactively
The command line also features an interactive recovery tool to aid in converting a story back into its source key. Run bin/storykey recover to initiate the process:

Ruby Usage
After installing the gem, you may run bin/console or require the gem in your own project.
Generate new key/story
Generate a new random key/story pair.
3.1.1# StoryKey.generate
=>
["4eqfoXzMDyqQW6p8zAQj7c8KkynK5K2BW6D5Vfp7xCaQ",
#<struct StoryKey::Story
text=
"In Miami I saw a dim Balrog eat hummus with an appraiser, a facetious scholar play badminton with an economist, a witty uncle insure Bruce Willis, an appreciative dolphin blare at a cyclist, a blissful James Bond undercut a connoisseur, a green Hugh Jackman eat cheese with a bison, and Elvis Presley snorkel with a counselor.",
humanized=
"In \e[31mMiami\e[0m I saw\n1. a \e[36mdim\e[0m \e[33mBalrog\e[0m \e[35meat hummus\e[0m with an \e[33mappraiser\e[0m,\n2. a \e[36mfacetious\e[0m \e[33mscholar\e[0m \e[35mplay badminton\e[0m with an \e[33meconomist\e[0m,\n3. a \e[36mwitty\e[0m \e[33muncle\e[0m \e[35minsure\e[0m \e[33mBruce Willis\e[0m,\n4. an \e[36mappreciative\e[0m \e[33mdolphin\e[0m \e[35mblare\e[0m at a \e[33mcyclist\e[0m,\n5. a \e[36mblissful\e[0m \e[33mJames Bond\e[0m \e[35mundercut\e[0m a \e[33mconnoisseur\e[0m,\n6. a \e[36mgreen\e[0m \e[33mHugh Jackman\e[0m \e[35meat cheese\e[0m with a \e[33mbison\e[0m,\n7. and \e[33mElvis Presley\e[0m \e[35msnorkel\e[0m with a \e[33mcounselor\e[0m.",
tokenized=
"dim balrog eat-hummus appraiser facetious scholar play-badminton economist witty uncle insure bruce-willis appreciative dolphin blare cyclist blissful james-bond undercut connoisseur green hugh-jackman eat-cheese bison elvis-presley snorkel counselor">]
Encode key => story
Produce an English paragraph given input data (e.g. a cryptocurrency private key):
3.1.1# StoryKey.encode(key: '4eqfoXzMDyqQW6p8zAQj7c8KkynK5K2BW6D5Vfp7xCaQ')
=>
#<struct StoryKey::Story
text=
"In Miami I saw a dim Balrog eat hummus with an appraiser, a facetious scholar play badminton with an economist, a witty uncle insure Bruce Willis, an appreciative dolphin blare at a cyclist, a blissful James Bond undercut a connoisseur, a green Hugh Jackman eat cheese with a bison, and Elvis Presley snorkel with a counselor.",
humanized=
"In \e[31mMiami\e[0m I saw\n1. a \e[36mdim\e[0m \e[33mBalrog\e[0m \e[35meat hummus\e[0m with an \e[33mappraiser\e[0m,\n2. a \e[36mfacetious\e[0m \e[33mscholar\e[0m \e[35mplay badminton\e[0m with an \e[33meconomist\e[0m,\n3. a \e[36mwitty\e[0m \e[33muncle\e[0m \e[35minsure\e[0m \e[33mBruce Willis\e[0m,\n4. an \e[36mappreciative\e[0m \e[33mdolphin\e[0m \e[35mblare\e[0m at a \e[33mcyclist\e[0m,\n5. a \e[36mblissful\e[0m \e[33mJames Bond\e[0m \e[35mundercut\e[0m a \e[33mconnoisseur\e[0m,\n6. a \e[36mgreen\e[0m \e[33mHugh Jackman\e[0m \e[35meat cheese\e[0m with a \e[33mbison\e[0m,\n7. and \e[33mElvis Presley\e[0m \e[35msnorkel\e[0m with a \e[33mcounselor\e[0m.",
tokenized=
"dim balrog eat-hummus appraiser facetious scholar play-badminton economist witty uncle insure bruce-willis appreciative dolphin blare cyclist blissful james-bond undercut connoisseur green hugh-jackman eat-cheese bison elvis-presley snorkel counselor">
key may be in the form of a hexidecimal (ab29f3), a binary string (1001101), a decimal (230938), or a base58 string (uMBca). If not in the default base58, format must be provided.
Decode story => key
Recover source data (e.g. a cryptocurrency private key) based on the English paragraph:
3.1.1# StoryKey.decode(story: 'In Miami I saw an official Benjamin Franklin transport Matt Damon')
=> "4NTM"
Development
After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.
When editing the lexicon, be sure to:
- Run
rake lexicon:buildto re-generate the data file - Copy the lexicon SHA into
version.rbas well as this README (if publishing) - Increment the semantic version of the gem (if publishing)
When incrementing the semantic version post-1.0, be sure to:
- Create a new
VERSION_SLUG, adhering to the locale convention - Append a row to the version reference at the top of this README
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/jcraigk/story_key.
License
The gem is available as open source under the terms of the MIT License.