BIP39UI is an Open Source project of VivaRado.
BIP39 editable mnemonic with checksum recalculation, strength evaluation on a vanilla interface with drag/drop and autocomplete.
- VivaRado [email protected]
- Andreas Kalpakidis
- Madina Akhmatova
Introduction / Profile
- Company: VivaRado LLP
- Designer: Andreas Kalpakidis
- Management: Madina Akhmatova
Introduction / Project Overview
- Project Name: BIP39UI
- Code Name: 39
- Proposal Date: 20/09/2024
BIP39UI is project ment to be used for access control, as a replacement to email or phone validation. A client creates a 12 or 24 word mnemonic generated on his machine (client side) for efficiency and load reduction of the servers, by choosing the words from the BIP39 standardized wordlist of 2048 words utilizing a user interface that allows for word to be draggable and discoverable with autocomplete. Post submission the vendor then validates the mnemonic (server side) and if valid, only stores the irreversible seed for later comparisson in password recovery routines maintaining anonymity for the client.
The source consists of BIP39, MnemStrong and the Interface.
Design / BIP39
The BIP39 is responsible for generating a mnemonic of given length, parsing an existing mnemonic as entropy, turning said entropy back to a mnemonic, generating a seed from a mnemonic, and generating a list of valid checksum words if the last word of the mnemonic is missing or invalid. We go over these in detail further down.
To aleviate unnessessary server side load by issuing BIP39, validating and issuing checksums - every time the client interacts with the interface, we provide the appropriate ESM modules, in the file marked as .clt.esm.js, for that to happen on the client. When eventually the client submits the mnemonic to the server, you can run the corresponding validation functions once, in the file marked as .srv.cjs.js, to make sure what you are handling is a valid mnemonic.
Design / BIP39 / Composition
The src/bip39/deps
contains ESM (ECMAScript modules) and CJS (Common JavaScript) files.
Assert
The assertions for the client include an additional report parameter that gets carried all the way from the functions in bip39/index
to the functions src/bip39/deps/assert
, in order to return the assertion results throughout the code.
Crypto
The built in NodeJS.crypto module, is used for various functions like pbkdf2, getRandomValues, createHash
, this is replaced on the client with widely available Web APIs SubtleCrypto and window.crypto
and the coresponding functions, to avoid creating overhead by using third party implementations.
Checksum Recalculation
As our BIP39 implementation is interactive, the checksum will be invalid as soon as the client replaces one of the words or drag/drops another one. For that reason we provide the checksumWords
function that given 12-24 words sans the last (checksum), will recalculate and return the words that are valid for the given mnemonic. We then move those to the interface for the client to pick.
Design / BIP39 / Functions
Here is an overview of the BIP39 function(s):
generateMnemonic ( strength
, report [opt.clsd]
, wordlist [opt.]
)
param strength: mnemonic strength 128-256 bits.
param report: optional client side only, error report boolean
param wordlist: optional imported wordlist for specific language.
returns (report:false): 12-24 words.
returns (report:true): Object { mnemonic: 12-24 words, assertions: Array }
Generates x random words. Uses Cryptographically-Secure Random Number Generator.
entropyToMnemonic ( entropy
, report [opt.clsd]
, wordlist [opt.]
)
param entropy: entropy byte array.
param report: optional client side only, error report boolean
param wordlist: optional imported wordlist for specific language.
returns (report:false): 12-24 words.
returns (report:true): Object { mnemonic: 12-24 words, assertions: Array }
Reversible: Converts raw entropy in form of byte array to mnemonic string.
mnemonicToEntropy ( mnemonic
, report [opt.clsd]
, wordlist [opt.]
)
param mnemonic: 12-24 words.
param report: optional client side only, error report boolean
param wordlist: optional imported wordlist for specific language.
returns (report:false): Buffer / Uint8Array (clsd)
returns (report:true): Object { mnemonic: 12-24 words, assertions: Array }
Reversible: Converts mnemonic string to raw entropy in form of byte array.
validateMnemonic ( mnemonic
, report [opt.clsd]
, wordlist [opt.]
)
param mnemonic: 12-24 words.
param report: optional client side only, error report boolean
param wordlist: optional imported wordlist for specific language.
returns (report:false): boolean
returns (report:true): Object { mnemonic: 12-24 words, assertions: Array }
Validates mnemonic for being 12-24 words contained in wordlist.
mnemonicToSeed ( mnemonic
, passphrase
, report [opt.clsd]
, wordlist [opt.]
)
param mnemonic: mnemonic 12-24 words (string | Uint8Array).
param passphrase: optional string that will additionally protect the key.
param report: optional client side only, error report boolean
param wordlist: imported wordlist for specific language.
returns (report:false): 64 bytes of key data.
returns (report:true): Object { seed: 64 bytes of key data, assertions: Array }
Irreversible (Sync/Async): Uses KDF to derive 64 bytes of key data from mnemonic and optional password.
checksumWords ( mnemonic
, wordlist [opt.]
)
param mnemonic: mnemonic 12-24 words (Array).
param wordlist: optional imported wordlist for specific language.
returns: Array with valid checksum words.
Generates array of valid checksum words given a mnemonic with invalid checksum.
Design / MnemStrong
The MnemStrong is responsible for evaluating given mnemonic, it is based on zxcvbn with all the bloat removed as we are not evaluating a password comprised of alphanumeric plus common symbols, but a mnemonic constructed by words from a predefined wordlist. The evaluation functions detect dictionary words (words in the wordlist), unbroken repetition (repeated words) and dictionary sequences (words in sequence just as they appear in the wordlist ). The percentage estimation is based on average BIP39 scores for 128 that is (92 rounded to 100) and 256 that is (176 rounded to 180) Bit mnemonics.
Design / MnemStrong / Composition
The src/mnemstrong/deps
contains ESM (ECMAScript modules) and CJS (Common JavaScript) files. Even though we provide ESM and CJS for Mnemstrong those are essentially the same files.
Design / MnemStrong / Functions
Here is an overview of the MnemStrong function(s):
mnemstrong ( mnemonic
)
param mnemonic: mnemonic 12-24 words (Array).
returns:
Object { sequence: matches Array, report_calc_time: Number, feedback: warning Array, crack_times_seconds: Object, crack_times_display: Object, score: Number, percentage: percent Number }
Evaluates a mnemonic.
Design / Interface
The Interface provides the interactivity with the wordlist to the client, specifically there is the ability to select the strength/size of the mnemonic between two options (128/256) using a dropdown like this.
The input fields are draggable, can autocomplete and are arrow navigable. There also is a generate button.
Design / Interface / Composition
The src/interface
contains ESM (ECMAScript modules) only, the CSS is located in the src/interface/styles
directory.
Design / Interface / MnemonicUI
This module is responsible for all the interface interactions, and binds together all the rest of the interface classes. It initiates the MnemStrong class and Autocomplete class and manages their state in relation to the mnemonic and checksum recalculation.
Design / Interface / MnemonicUI / Usage
Initiating the Mnemonic user interface by including the MnemonicUI class:
<script src="./src/interface/mnemonicui.esm.js" type="module"></script>
The code bellow is included in the file above. Both bip39
and MnemonicUI
are exposed to the window, so you can run them at will.
mnemostrong:
If you do not want the mnemonic strength check to run, include mnemostrong:false
in the config.
populate:
If you do not want the input fields populated, include populate:false
in the config.
// For active interface during mnemonic creation.
new MnemonicInterface();
// For passive interface during mnemonic recovery.
var config = {
"mnemstrong":false,
"populate": false
}
new MnemonicInterface(config);
Design / Interface / MnemonicUI / Functions
Here is an overview of the MnemonicUI functions:
reflectChecksumElm ()
Defines the interactivity of checksum elements by setting the element
draggable
attribute to false or true and adding or removing thechecksum_elm
class for current checksum and ante checksum respectively.
Distributes the appropriate wordlist array (dictionary or valid checksums) to the elements currently in the checksum positions (index 12 or 24) by retargeting the Autocomplete class usingAutocomplete.destroy()
on current and ante checksum, andAutocomplete.reattach()
toself.autcom_sc
andself.autcom_ac
. These are the two groups of autocompletes, theautcom_sc
sans checksum (without checksums) andautcom_ac
avec checksum (with checksums).
Then updates the results poolAutocomplete.setpool()
of the current checksum element with the valid checksums array set toself._cfg._vc
frommnem_evaluate()
.
Finally is sets the current checksum element's input value to the first value from the valid checksums array.
reflectMnemonic ( strength
)
param strength: Number 128 or 256.
Generates a mnemonic of strength 128 or 256 and sets the values to the input field elements.
reflectActive ( strength
, reflchs
)
param strength: Number 128, 256 or 0.
param reflchs: boolean (reflect checksum), default is false.
Sets the
self._cfg._ml
(mnemonic length) according to the active selection of the dropdown. Resets the object order stored indata-index
attribute.
Calls for mnemonic generation, evaluation and checksum element update and refreshes the data-index attribute.
reflectFeedback ( mv
, ms
)
param mv: Array (mnemonic validation).
param ms: Array (mnemonic strength).
Visual alerts and strength bar visuals.
mnemEvaluate ( updchs
, reflchs
, cb
)
param updchs: boolean (update checksum).
param reflchs: boolean (reflect checksum).
param cb: callback function.
Runs validations and evaluations of current mnemonic with valid checksum. Forwards the feedback to
reflect_feedback
for visual alerts and strength bar visuals on the client. Updates current mnemonic arrayself._cfg._cm
ifupdchs
is true. Updates checksum element value ifreflchs
is true.
initAutocompleteGroups ()
Initiate the AutoComplete groups
self.autcom_sc
andself.autcom_ac
.
initDraggable ()
Initiate dragstart, dragover, drop, dragend events on passphrase inputs container. Prevent checksum elements from being draggable. Evaluate mnemonic on drop and generate a new mnemonic. Manage Autocomplete reattachment to input groups.
Design / Interface / AutoComplete
Autocomplete is responsible for displaying the input fields and their adding interactivity by setting events like input search, arrow navigation, click outside and escape press to close the dropdown. Loading the words to the interface and updating valid checksum words.
Design / Interface / AutoComplete / Functions
Here is an overview of the AutoComplete functions:
externalEvents ()
Setup external events, up and down arrow navigation, escape key press and click outside.
selctEvt ( self
, ac
)
param self: passing object context to avoid event
this
collision.
param ac: autocomplete input element.
Click on autocomplete dropdown element.
inputEvt ( self
, ac
)
param self: passing object context to avoid event
this
collision.
param ac: autocomplete input element.
Handle autocomplete field input event.
clickEvt ( self
, ac
)
param self: passing object context to avoid event
this
collision.
param ac: autocomplete input element.
Handle click event on autocomplete dropdown elements.
exterEvtHandler ()
Close the autocomplete on click outside the autocomplete.
arrowEvtHandler ()
Navigate the autocomplete results with up and down arrow.
clickEvtHandler ( ac
)
param ac: autocomplete input element.
Pick item in autocomplete dropdown on click.
selctEvtHandler ( ac
)
param ac: autocomplete input element.
Select autocomplete input text on click.
inputEvtHandler ( ac
)
param ac: autocomplete input element.
Initiate search pool filtering on input event.
activate ( ac
)
param ac: autocomplete input element.
Activate external events and click event for autocomplete.
toggle ( ac
)
param ac: autocomplete input element.
Toggle show / hide of autocomplete dropdown.
show ( ac
)
param ac: autocomplete input element.
Show autocomplete dropdown.
hide ( ac
, emit
)
param ac: autocomplete input element.
param emit: emit the event, default is false.
Hide autocomplete dropdown.
filterRes ( ac
, marker
, term
)
param ac: autocomplete input element.
param marker: autocomplete dropdown item element.
param term: search term
Results pool filtering.
termInPool ( ac
, term
)
param ac: autocomplete input element.
param term: search term
Input of words not currently in the search pool or input is empty, results in error.
inputReflection ( e
, ac
)
param e: event.
param ac: autocomplete input element.
Manage the way the autocomplete reacts to input value.
fillSearchPool ( ac
, serv_array
)
param ac: autocomplete input element.
param serv_array: wordlist Array.
Create autocomplete element pool from provided array.
clearHiLight ()
Clear highlight from arrow navigation.
build ( ac
)
param ac: autocomplete input element.
Build autocomplete.
interact ( ac
)
param ac: autocomplete input element.
Set up autocomplete input element events.
reattach ( ac
)
param ac: autocomplete input element.
Reattach input to autocomplete class
destroy ( self
, ac
, remove
)
param self: passing object context to avoid event
this
collision.
param ac: autocomplete input element.
param remove: boolean, remove element from dom.
Destroy autocomplete and remove events from input.
Design / Interface / Reports
Contains the strength_check
and display_alert
report rendering functions.
Design / Interface / Reports / Functions
Here is an overview of the Reports functions:
strengthCheck ( strength_bar
, value
)
param strength_bar: strength bar element.
param value: Number.
Display strength value on strength bar as percentage.
displayAlert ( alert_data
, target_alert
, animation
)
param alert_data: feedback array.
param target_alert: alert element.
param animation: Boolean.
Display feedback as alerts.
To work on extending this module a few things are provided:
Run in browser with reload allong with gulp watch:
npm run dev
Just build with gulp
npm run build
Test the server side functions
npm run test
BIP39UI does not have any dependencies, other than those for development (--save-dev).
To install:
npm install
BIP39: Bitcoin Improvement Proposal 0039.
opt.: Optional.
clsd: Client Side.
BIP39 Mediawiki GitHub