Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

seedlock

guarded memory for bip39 seeds and bip32 keys. mlocked, wiped on drop, never copied into a gc heap.

seedlock = "0.1"

why

a javascript string is immutable, garbage collected, and copied all over the heap. you cannot zero a mnemonic in javascript. every js wallet has this hole and none of them can close it from js.

seedlock keeps the phrase, the seed and every derived key in memory that:

  • is mlocked so it never reaches swap
  • is zeroed on drop
  • compares in constant time
  • prints as redacted in Debug
  • is wiped in the caller's buffer on import

use

use seedlock::{Mnemonic, WordCount, XPrv};

// generate. the phrase never exists outside guarded memory
let m = Mnemonic::generate(WordCount::W12)?;

// or import. your bytes are zeroed for you
let mut phrase = read_from_user();
let m = Mnemonic::from_bytes(&mut phrase)?;
assert!(phrase.iter().all(|&b| b == 0));

let seed = m.to_seed("");
let master = XPrv::from_seed(&seed)?;
let account = master.derive_path("m/44'/60'/0'/0/0")?;

let pubkey = account.public_key();          // safe to hand out
let sig = account.sign_prehash(&digest)?;   // key used in place, never returned

api

Guarded mlocked, zeroizing byte buffer. constant time PartialEq
Mnemonic::generate(WordCount) fresh entropy from the os
Mnemonic::from_bytes(&mut [u8]) validates the checksum, wipes your buffer
Mnemonic::to_seed(passphrase) pbkdf2-hmac-sha512, 2048 rounds
XPrv::from_seed(&Guarded) bip32 master key
XPrv::derive_path("m/44'/60'/0'/0/0") ' or h for hardened
XPrv::public_key() compressed secp256k1, 33 bytes
XPrv::sign_prehash(&[u8; 32]) ecdsa, 64 bytes

12, 15, 18, 21 and 24 word phrases.

verified against

bip39 english vectors (empty and TREZOR passphrases) and bip32 test vector 1. 23 tests.

notes

mlock is unix only. on other platforms the buffer still zeroes on drop, it just is not pinned. Guarded::is_locked() tells you which you got.

expose_secret() exists but is the escape hatch, not the api. reach for sign_prehash first.

licence

MIT

About

guarded memory for bip39 seeds and bip32 keys. mlocked, wiped on drop, never copied into a gc heap

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages