seed-phrases-for-stellar

Utility for generating Stellar accounts from BIP39/Electrum seed phrases


Keywords
Stellar, deterministic, keypair, generation, BIP39, Electrum, mnemonic, seed, phrase
License
MIT
Install
pip install seed-phrases-for-stellar==0.2

Documentation

Build Status

seed-phrases-for-stellar

This Python package provides a command-line script and a library module for generating Stellar accounts from BIP-0039/Electrum seed phrases. It performs deterministic generation of Stellar account keys from mnemonic seed phrases. Each seed phrase may optionally be extended with custom words that play the role of an additional passphrase.

seed-phrases-for-stellar accepts two kinds of mnemonic seed phrases:

Since these are the two major standards for wallet seed phrases, seed-phrases-for-stellar accepts nearly all mnemonic phrases generated by cryptocurrency wallets. Note, however, that this software does NOT perform random generation of high-entropy seed phrases. Its main purpose is to allow cryptocurrency wallet users to derive Stellar account keys from high-entropy seed phrases that they already have and that probably were created by their wallets.

By following either BIP-0039 or Electrum, seed-phrases-for-stellar derives a binary seed from a mnemonic seed phrase. Then it derives Stellar keys from the binary seed, as specified by SEP-0005 (https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md), SLIP-0010 (https://github.com/satoshilabs/slips/blob/master/slip-0010.md) and BIP-0044 (https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki).

Installation

pip3 install seed-phrases-for-stellar

Command-line usage

seed-phrase-to-stellar-keys -h

produces the following output:

usage: seed-phrase-to-stellar-keys [-h] [-n N] [-s] [-l] [-L LANG] [-v] [-F]

Generate Stellar account keys from BIP-0039/Electrum seed phrases

optional arguments:
  -h, --help            show this help message and exit
  -n N, --n_accts N     show keys for multiple accounts (N > 0)
  -s, --show_seed       show the standard BIP-0039 or Electrum seed
  -l, --list_languages  list available languages for BIP-0039 phrases and exit
  -L LANG               language for BIP-0039 seed phrases (default: english)
  -v, --version         show program's version number and exit
  -F, --force           force keypair generation from phrase of unknown type

The default behavior of seed-phrase-to-stellar-keys is to show just the keys
for one Stellar account (the primary account). By default, the binary seed
derived from the seed phrase is not shown. This behavior can be changed by the
'-n N' and '-s' switches.

Examples

1. Key derivation from a BIP-0039 seed phrase

$ seed-phrase-to-stellar-keys

Enter the seed phrase:
illness spike retreat truth genius clock brain pass fit cave bargain toe

Enter optional custom words (passphrase) to extend the seed phrase:


      seed phrase: 'illness spike retreat truth genius clock brain pass fit cave bargain toe'
     custom words: ''
 seed phrase type: BIP-0039

  primary account:
       public key: GDRXE2BQUC3AZNPVFSCEZ76NJ3WWL25FYFK6RGZGIEKWE4SOOHSUJUJ6
     private seed: SBGWSG6BTNCKCOB3DIFBGCVMUPQFYPA2G4O34RMTB343OYPXU5DJDVMN
     

2. Same example as above, now showing the BIP-0039 seed and four accounts

$ seed-phrase-to-stellar-keys -s -n 4

Enter the seed phrase:
illness spike retreat truth genius clock brain pass fit cave bargain toe

Enter optional custom words (passphrase) to extend the seed phrase:


      seed phrase: 'illness spike retreat truth genius clock brain pass fit cave bargain toe'
     custom words: ''
 seed phrase type: BIP-0039
    BIP-0039 seed: e4a5a632e70943ae7f07659df1332160937fad82587216a4c64315a0fb39497ee4a01f76ddab4cba68147977f3a147b6ad584c41808e8238a07f6cc4b582f186

       account #0: ------------- this is the primary account --------------
       public key: GDRXE2BQUC3AZNPVFSCEZ76NJ3WWL25FYFK6RGZGIEKWE4SOOHSUJUJ6
     private seed: SBGWSG6BTNCKCOB3DIFBGCVMUPQFYPA2G4O34RMTB343OYPXU5DJDVMN

       account #1:
       public key: GBAW5XGWORWVFE2XTJYDTLDHXTY2Q2MO73HYCGB3XMFMQ562Q2W2GJQX
     private seed: SCEPFFWGAG5P2VX5DHIYK3XEMZYLTYWIPWYEKXFHSK25RVMIUNJ7CTIS

       account #2:
       public key: GAY5PRAHJ2HIYBYCLZXTHID6SPVELOOYH2LBPH3LD4RUMXUW3DOYTLXW
     private seed: SDAILLEZCSA67DUEP3XUPZJ7NYG7KGVRM46XA7K5QWWUIGADUZCZWTJP

       account #3:
       public key: GAOD5NRAEORFE34G5D4EOSKIJB6V4Z2FGPBCJNQI6MNICVITE6CSYIAE
     private seed: SBMWLNV75BPI2VB4G27RWOMABVRTSSF7352CCYGVELZDSHCXWCYFKXIX

3. Key derivation from an Electrum seed phrase, showing the Electrum seed

$ seed-phrase-to-stellar-keys -s

Enter the seed phrase:
write long buzz fork domain forget punch child entry object load north

Enter optional custom words (passphrase) to extend the seed phrase:


      seed phrase: 'write long buzz fork domain forget punch child entry object load north'
     custom words: ''
 seed phrase type: Electrum standard
    Electrum seed: 4eb18cab8eaa91a4486bb0ef9ad814f3e40f946235ef7996c8e7b2a4186fdde3a841b501a12728d6ffe323c8272957e35334c684576087dee710d09d518bd9b2

  primary account:
       public key: GAF273TDSINGAMNL7OCMFYIBTUIRPFSXUQ6EYPJMVOOCQ3Z5ICSIBBLD
     private seed: SCCK6VFCREX4BFIHIHYX2O6AIIRSEID7HOI47YPB5XNSYLG7SI45D5RT

Note that seed-phrase-to-stellar-keys automatically detects the seed phrase type. Electrum seed phrases have specific subtypes: old (pre 2.0) Electrum, standard (Electrum 2.0 or later), segwit, and 2FA. In addition to distinguishing BIP-0039 seed phrases from Electrum seed phrases, seed-phrase-to-stellar-keys shows the specific subtype of an Electrum seed phrase. This information has no importance for the derivation of Stellar account keys, but it may be helpful to prevent typos from going unnoticed.

4. Key derivation from an Electrum segwit seed phrase, showing the Electrum seed:

$ seed-phrase-to-stellar-keys -s 

Enter the seed phrase:
nerve museum sort subject call unable double rally wheat drip tiger kitchen

Enter optional custom words (passphrase) to extend the seed phrase:


      seed phrase: 'nerve museum sort subject call unable double rally wheat drip tiger kitchen'
     custom words: ''
 seed phrase type: Electrum segwit
    Electrum seed: 68d1e21953e934a7ff2f7d852e4a05d9fd12fbb86e1c49fb822c214a5ce57ee64c714b447ce23edb878cdc99d8adf4e29c3f9c9d237986ef9ac557fa60f37965

  primary account:
       public key: GBJM3LGVJLCM3YNH2IZ3I6U2HTAGKQVFITWWM5X3T4VE5CGNSDAKKG6K
     private seed: SALX6MN3OKWH6WIDYOUJTXOVJUWCYBHP7JNQUFUUD56WOATQVKKDMADE

5. Key derivation from a phrase that is both a BIP-0039 seed phrase and an Electrum seed phrase

BIP-0039 and Electrum seed phrases are not disjoint sets. In the case of a phrase that belongs to both sets, seed-phrase-to-stellar-keys performs the BIP-0039 derivation and, if invoked with the '-s' option (as in the example below), shows the BIP-0039 seed.

$ seed-phrase-to-stellar-keys -s 

Enter the seed phrase:
ivory hollow predict error front energy invite differ general depart repeat prize

Enter optional custom words (passphrase) to extend the seed phrase:
s0me p4ssphr4se         

      seed phrase: 'ivory hollow predict error front energy invite differ general depart repeat prize'
     custom words: 's0me p4ssphr4se'
 seed phrase type: BIP-0039 and Electrum standard
    BIP-0039 seed: c1a65a79988348c001593e22737f285dc49c054b2265394c5dbddf296c89bf5f0af5f8b3b6e231b8711314da6894a816320fb5cedbd99484f9da81dd9a261812

  primary account:
       public key: GDNRZZR5GU6QG5KQUWFE3WWD5L57JQAYC7CBLOIP5GQR2X7C4ZZJBWDR
     private seed: SDUNJQZRBESMERRIJCSIOKCS7K4VQKGM5BT6CLUX7FEQ3STVUAHIVH2V

API usage

The deterministic generation of Stellar account keys from a mnemonic seed phrase is done in two steps:

  1. derive a 64-byte binary seed from a mnemonic seed phrase;
  2. generate Stellar account keypairs from the binary seed.

1. The first step

    from seed_phrases_for_stellar.seed_phrase_to_stellar_keys import to_binary_seed
    my_seed_phrase = '...'
    my_passphrase = '...' 
    my_language = 'english' # or other language listed in
                            # https://github.com/bitcoin/bips/blob/master/bip-0039/bip-0039-wordlists.md
                            # NB: the language is relevant only in the case of a BIP39 seed phrase
    (binary_seed, seed_phrase_type) = to_binary_seed(my_seed_phrase,
                                                     my_passphrase,
                                                     my_language)

At this point, seed_phrase_type is one of the following strings:

  • 'BIP-0039'
  • 'BIP-0039 and Electrum standard'
  • 'BIP-0039 and Electrum segwit'
  • 'BIP-0039 and Electrum 2FA'
  • 'Old (pre 2.0) Electrum'
  • 'Electrum standard'
  • 'Electrum segwit'
  • 'Electrum 2FA'
  • 'UNKNOWN'

If my_seed_phrase is a BIP39-compliant phrase for my_language (this condition covers the first four cases listed above), the to_binary_seed call generates the binary seed as recommended by BIP39. Otherwise, if my_seed_phrase is an Electrum seed phrase (this condition covers the next four cases listed above), the to_binary_seed call generates the binary seed by using Electrum's algorithm. Otherwise (this is the last case listed above), the to_binary_seed call generates the binary seed in a non-standard way.

2. The second step

    from seed_phrases_for_stellar.key_derivation import account_keypair
    account_number = ... # an small unsigned integer (0 for the primary account)
    account_keypair = account_keypair(binary_seed, account_number)

The account_keypair call performs the key derivation specified by SEP-0005, SLIP-0010, and BIP-0044.

3. Alternative BIP39-only implementation of the first step

Note that the first step above handles both BIP39 and Electrum seed phrases. If you do not need to handle Electrum seed phrases, then you can implement the first step by using the package mnemonic (https://github.com/trezor/python-mnemonic), which is the reference implementation of BIP39:

    from mnemonic import Mnemonic
    my_seed_phrase = '...'
    my_passphrase = '...' 
    my_language = 'english' # or other language listed in
                            # https://github.com/bitcoin/bips/blob/master/bip-0039/bip-0039-wordlists.md
    mnemo = Mnemonic(my_language)
    if mnemo.check(my_seed_phrase):
        # my_seed_phrase is a valid BIP39 phrase for my_language   
        binary_seed = Mnemonic.to_seed(my_seed_phrase, my_passphrase)

The second step remains unchanged.