Skip to main content

Summary

The IOTA protocol uses a 81-tryte seed to derive all the private keys for one account. This RFC describes a method to represent that seed as a mnemonic sentence - a group of easily comprehensible words.

Motivation

The used seed is a 384-bit or 243-trit random string. There are several ways to represent this in a human-readable form, but a mnemonic sentence is superior to raw binary or ternary strings. These sentences can easily be written down or they can even be recorded over a phone. Furthermore, having raw strings tempts the user to copy and paste the seed due to convenience over security. This practice opens new attack vectors such as theft or manipulation of the string in the clipboard.

Detailed design

The BIP-0039 specification exactly describes an implementation for its use case and how to uniquely represent binary entropy using mnemonic words. However, it is only defined for binary input of 128 - 256 bits. The section(s) below describe the canonical extension of BIP-0039 for longer inputs of 81 trytes or 384 bits.

The 243-trit (81-tryte) seed is used as input for the Kerl hash function to derive the private keys. Therefore, it is first converted to a 384-bit string to be absorbed by Keccak-384. As the set of all possible 243-trit strings is larger than the set of 384-bit strings, the most significant trit is fixed to zero before converting. This means that the 243rd of the seed is ignored and does not have any impact on the following key derivation and does not need to be considered for the encoding.

Generating the mnemonic from seed

  • Interpret the IOTA seed as a little-endian 243-trit balanced ternary integer; assure that its most significant trit is 0 and encode the number as a 384-bit signed integer in big-endian two's complement representation. This exact conversion is also used as part of the current Kerl hash function.
  • Compute the SHA-256 hash of the resulting bit string and use its first 384/32=12 bits as the checksum.
  • The 12-bit checksum is appended to the end of the initial result, making it a 396-bit string.
  • These concatenated bits are split into 36 groups of 11 bits, each encoding a number from 0-2047, corresponding to an index into the wordlist.
  • Finally, convert these numbers into words from any one of the BIP-0039 wordlists and use the joined words as a mnemonic sentence.

Generating the seed from mnemonic

  • Convert the 36-word mnemonic sentence into its corresponding 396-bit string by taking the 11-bit wordlist index for each word and concatenating all the bits.
  • Split the resulting bit string into 384-bit entropy and 12-bit checksum.
  • Verify that the checksum corresponds to the first bits of the SHA-256 hash of the entropy.
  • Convert the 384-bit entropy, interpreted as a signed integer in big-endian two's complement representation, back to a little-endian 243-trit balanced ternary integer. (The most significant trit will always be zero.) This corresponds to the usual 243-trit or 81-tryte IOTA seed.

Examples

  • Using the English word list:
    • IOTA seed (81-tryte): TLEV9HDTGZOXIIGA9DZG9VAKAIUZKNIMAFUGGARTWPOGDLLVUFZZVAABXRMFPWJAYWBBHOERV9EZBAOJD
    • mnemonic (36-word): forget small borrow baby wing law monkey fiber jealous canyon melt all order lift now fish mind index neither discover divert fit curtain raw wealth arrow frozen plug catalog public winner emerge pulse mixture cry arch
  • Using the Japanese word list:
    • IOTA seed (81-tryte): KMQDKKLGGTPUBRJXYWLMQOIA9WIEWUAAJPASYPVAWOTYYH9JESDKPLVZIWITHDIUMLFEWQUQ9LHAV9GHC
    • mnemonic (36-word): げどく まもる してい ていへん つめたい ちつじょ だいたい てうち まいにち さゆう よそく がはく ねらう いちおう くみあわせ ふいうち せつでん きせい すべて きひん しかい さぎょう うけたまわる つとめる おんしゃ きかい なやむ たいせつ うんこう むすめ いってい ふめつ そとづら つくね おいこす ききて

Drawbacks

  • This RFC describes a way to represent computer-generated randomness in a human-readable transcription. It is in no way meant to process user created sentences into a binary key. This technique is also sometimes called a "brain wallet" and must not be confused with these mnemonics.
  • The mnemonics only encode 384 bits of entropy which only covers 242 trits. The 243rd trit will not be encoded and always padded with 0. This is fine, when Kerl is used to derive the private keys, since the Kerl hash function only works on the first 242 trits itself. However, other - currently not used - key derivation functions relying on the full 243-trit entropy are not compatible with this RFC.

Rationale and alternatives

  • BIP-0039 provides an industry standard to present computer generated, secure entropy in a way that can be "processed" by humans in a much less error-prone way. The word lists are chosen in a way to reduce ambiguity, as such, typos can either be autocorrected or corrected with the help of a dictionary. This is in contrast to a raw ternary (or binary) representation, where typos automatically lead to a completely new seed, changing and breaking all successive private keys.
  • Thanks to the integrated 12-bit checksum, it is even possible to detect whether one or more words have been exchanged completely.
  • Presenting the user with a tryte or hex string will lead to situations in which the seed is copied into a text file, while human-readable words encourage the user to copy them on a piece of paper.

Unresolved questions

  • This RFC does not cover usability aspects of entering mnemonics. Forcing the user to enter a mnemonic sentence and then discarding the input, due to one easily correctable typo in one word, would almost be as frustrating as typing a tryte string. Therefore, this must be combined with different usability improvements, e.g. only allowing entering characters that lead to valid words or fixing the word as soon as it can be unambiguously identified.
  • The BIP-0039 specification includes several word lists for different languages. Should these word lists be allowed or is it sufficient to only use the English list?
  • The BIP-0039 specification only considers entropy between 128 and 256 bits, while this RFC extends it in an analogue way for 384 bits. Is it also relevant for certain use cases to extend this for 512 bits (or even longer)?

Reference implementation

Example Go implementation in wollac/iota-crypto-demo:

Copyright

Copyright and related rights waived via CC0.