2 stable releases

1.1.0 Dec 7, 2023
1.0.0 Sep 26, 2023

#23 in #bip-39

21 downloads per month

MIT license

32KB
509 lines

seedxor

seedxor builds on top of rust-bip39 and is a fork of seed-xor and lets you XOR bip39 mnemonics as described in Coldcards docs.

It also lets you split existing mnemonics into as many seeds as you wish, and unscramble parts of a seed in random order into valid seeds.

It is also possible to XOR mnemonics with differing numbers of words. For this the xored value takes on the entropy surplus of the longer seed.

Command line example

usage: seedxor [options...]
 -h, --help                        Display this help
 -s, --split <seed>                Split seed into num-seeds
 -n, --num-seeds <num>             Number of seeds to split into or generate
                                   default 2
 -y, --no-validate                 Do not validate a split can be successfully recombined, useful for
                                   non-bip39 seeds, like ethereum
 -g, --generate                    Generate num-seeds
 -w, --word-count <num>            Number of words to generate in the seed
                                   default 24
 -c, --combine <seeds...>          Combine seeds into one seed
 -r, --short                       Display only first 4 letters of seed words
 -u, --unscramble <seed-parts...>  Unscramble seed words in random order to valid seeds
$ seedxor -s 'silent toe meat possible chair blossom wait occur this worth option boy'
vault junior rather gentle fresh measure waste powder resemble ocean until body
defy one debate situate jungle music achieve cradle fiscal govern intact acquire
$ seedxor -c 'vault junior rather gentle fresh measure waste powder resemble ocean until body' 'defy one debate situate jungle music achieve cradle fiscal govern intact acquire'
silent toe meat possible chair blossom wait occur this worth option boy

$ seedxor -r -s 'silent toe meat possible chair blossom wait occur this worth option boy'
sieg facu mult uniq agai spar diag widt foll worl rela twis
abou rate brea eagl cann sile skin ging risk able conc util
$ seedxor -c 'sieg facu mult uniq agai spar diag widt foll worl rela twis' 'abou rate brea eagl cann sile skin ging risk able conc util'
silent toe meat possible chair blossom wait occur this worth option boy
$ seedxor -r -c 'sieg facu mult uniq agai spar diag widt foll worl rela twis' 'abou rate brea eagl cann sile skin ging risk able conc util'
sile toe meat poss chai blos wait occu this wort opti boy

$ seedxor -g
spell system smoke army frame vacant trick jacket anchor gasp acoustic supply deputy portion butter similar trend scorpion cause fish outer armor process faint
solar lab option erosion unit example convince viable soft smart smile spoon range card gentle miracle latin they verify want reject side cheese panther
$ seedxor -c 'spell system smoke army frame vacant trick jacket anchor gasp acoustic supply deputy portion butter similar trend scorpion cause fish outer armor process faint' 'solar lab option erosion unit example convince viable soft smart smile spoon range card gentle miracle latin they verify want reject side cheese panther'
butter patch first doll raise safe side lounge shiver protect solid area melody member lazy easily nice canvas stomach pattern claim slot million stomach

$ seedxor -u 'affair mutual spare' 'smooth mushroom scale' 'include neck grab' 'fly maze obtain'
# total permutations: 24
include neck grab smooth mushroom scale fly maze obtain affair mutual spare
# good: 1 bad: 23 total: 24

$ seedxor -u 'squirrel tray cheese' 'seek enhance oval' 'expect sense fish' 'total salad page'
# total permutations: 24
squirrel tray cheese seek enhance oval expect sense fish total salad page
expect sense fish squirrel tray cheese seek enhance oval total salad page
# good: 2 bad: 22 total: 24

Library Example

use seedxor::{Mnemonic, SeedXor};
use std::str::FromStr;

// Coldcard example: https://github.com/Coldcard/firmware/blob/master/docs/seed-xor.md
let a_str = "romance wink lottery autumn shop bring dawn tongue range crater truth ability miss spice fitness easy legal release recall obey exchange recycle dragon room";
let b_str = "lion misery divide hurry latin fluid camp advance illegal lab pyramid unaware eager fringe sick camera series noodle toy crowd jeans select depth lounge";
let c_str = "vault nominee cradle silk own frown throw leg cactus recall talent worry gadget surface shy planet purpose coffee drip few seven term squeeze educate";
let result_str = "silent toe meat possible chair blossom wait occur this worth option bag nurse find fish scene bench asthma bike wage world quit primary indoor";

// Mnemonic is a wrapper for bip39::Mnemonic which implements the XOR operation `^`.
// Mnemonics can also be created from entropy.
let a = Mnemonic::from_str(a_str).unwrap();
let b = Mnemonic::from_str(b_str).unwrap();
let c = Mnemonic::from_str(c_str).unwrap();
let result = Mnemonic::from_str(result_str).unwrap();

assert_eq!(result, a ^ b ^ c);

// split a into 3 mnemonics
let a = Mnemonic::from_str(a_str).unwrap();
let split = a.splitn(3).unwrap();
let recombined_a = Mnemonic::xor_all(&split).unwrap();
assert_eq!(a_str, recombined_a.to_string());

Dependencies

~1MB
~32K SLoC