How to use a coldcard MK3 to derive your new account password from a 24 word seed

in HiveDevs2 years ago

Each hive account has four keys which can be used to sign broadcast operations. As the key name says (owner key, active key, posting key), they have different use cases. Normally, a single password is used to derive these four keys from it. This has the advantage that only one passphrase needs to be securely stored.

I can change my account keys by generating a new password:
New Password

You need to BACK IT UP BY STORING IN YOUR PASSWORD MANAGER OR A TEXT FILE., but what happens when your hard drive is failing or your password manager (lost the master password, ...)? You can print it, but what happens in case of a fire or water damage?

Using your bitcoin seed for Hive

When you have stored your bitcoin seed (consisting normally of 24 words) in metal, it would be great if you could use this also to store your Hive password.

It is possible to use BIP-85 (Deterministic Entropy From BIP32 Keychains) for creating a new password for a hive account using a coldcard mk3 hardware wallet (As far as I know this is the only device that support BIP85).

coldcard

When I use the derived WIF to create a new Password for my Hive account, I do not need to store my Hive keys and Password anymore, as they can be recreated from the securely stored bitcoin seed (I need to remember the used index number, or I need to try all possible numbers from 0 to 9999).

Thus I can increase my account security when I do not store the password and the owner key in my computer.

How to use the coldcard mk3 to create a new Password for Hive

This guide will use the coldcard mk3 which has the necessary bip-85 support and python (beem) for generating and changing the account keys.

Storing a WIF on a sdcard

At first we use the coldcard to derive a new WIF and store it on a sdcard.

Go to Advanced
Then to Derive Entropy
We need to select WIF:
Then to WIF
Select a number you can remember:
Select a number
Store the WIF to the MicroSD:
Press 1 to store the WIF on the sd card

Reading the WIF from the sdcard and change the HIVE keys

We need the following python packages:

pip3 install beem

The WIF from the coldcard needs firstly converted into a HIVE WIF and then a password is derived by applying PasswordKey to it and adding a P:

from beemgraphenebase.account import PrivateKey, PasswordKey
WIF="xxx" # from coldcard
wif = PrivateKey(WIF)
pk = PasswordKey("", str(wif), role="")
password = 'P' + str(pk.get_private())
print(password)

password is the new account password that can be set in https://wallet.hive.blog/@<username>/password

After changing the account password, the new posting, active and memo key should be stored and the Password and the WIF on the sdcard should be deleted.

Whenever, an account key is getting lost or when the owner key is needed,
it can be created from the derive WIF which is created by the coldcard.

It is also possible to automate everything. The following script will

  • Read the sdcard and extract the WIF
  • Create a new Password for the account
  • Change the account password by broadcasting update_account
from beem import Hive
from beemgraphenebase.account import PrivateKey, PasswordKey
import argparse
from prettytable import PrettyTable
import sys
import getpass


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Derives a new password from a coldcard WIF")
    parser.add_argument('wiffile', type=str, nargs='?',
                        help='colcard wif key file to read.')
    parser.add_argument('account', type=str, nargs='?',
                        help='account name.')    
    args = parser.parse_args()
    wiffile = args.wiffile
    account = args.account
    next_var = ""
    wif = ""
    path = ""
    with open(wiffile) as fp: 
        for line in fp:
            if line.strip() == "":
                continue
            if line.strip() == "WIF (privkey):":
                next_var = "wif"
                continue
            elif "Path Used" in line.strip():
                next_var = "path"
                continue
            if next_var == "wif":
                wif = line.strip()
            elif next_var == "path":
                path = line
            next_var = ""
    wif = PrivateKey(wif)
    pk = PasswordKey("", str(wif), role="")
    password = 'P' + str(pk.get_private())
    
    owner_key = PasswordKey(account, password, role="owner")
    owner_pubkey = format(owner_key.get_public_key(), "STM")
    
    active_key = PasswordKey(account, password, role="active")
    active_pubkey = format(active_key.get_public_key(), "STM")
    
    posting_key = PasswordKey(account, password, role="posting")
    posting_pubkey = format(posting_key.get_public_key(), "STM")
    
    memo_key = PasswordKey(account, password, role="memo")
    memo_pubkey = format(memo_key.get_public_key(), "STM")
    
    
    t = PrettyTable(["Key", "Value"])
    t.align = "l"
    t.add_row(["Account", account])
    t.add_row(["Path", path])   
    t.add_row(["New owner pubkey", owner_pubkey])
    t.add_row(["New active pubkey", active_pubkey])   
    t.add_row(["New posting pubkey", posting_pubkey])   
    t.add_row(["New memo pubkey", memo_pubkey])   
    print(t)
    ret = input("Broadcast update_account with new keys? [y/n]")
    if ret in ["y", "yes"]:
        owner_key = getpass.getpass(prompt="current owner key:")
        hive = Hive(keys=[owner_key])
        tx = hive.update_account(account, owner_key=owner_pubkey, active_key=active_pubkey,
                                 posting_key=posting_pubkey, memo_key=memo_pubkey)
        print(tx)
    
    ret = input("Show private keys? [y/n]")
    if ret in ["y", "yes"]:
        t = PrettyTable(["Key", "Value"])
        t.align = "l"
        t.add_row(["active privkey", str(active_key.get_private_key())])   
        t.add_row(["posting privkey", str(posting_key.get_private_key())])   
        t.add_row(["memo privkey", str(memo_key.get_private_key())])
        print(t)
    ret = input("Show owner key and password? [y/n]")
    if ret in ["y", "yes"]:
        t = PrettyTable(["Key", "Value"])
        t.align = "l"
        t.add_row(["owner privkey", str(owner_key.get_private_key())])
        t.add_row(["Password", str(password)])
        print(t)
    del owner_key
    del memo_key
    del posting_key
    del active_key
    del password

This needs to be stored as py file (e.g. new_password.py) and can then be called:

python3 new_password.py F:\drv-wif-idx0.txt holger80

where F:\drv-wif-idx0.txt is the path to the exported WIF file.

Deleting the WIF text file on the sdcard needs to be done by hand (remember to store the used index number).

I'm currently adding this also to beempy, the CLI tool in beem.
There is also a second way in creating a new password from a seed using hardware wallet (signing a message), which I'm investigating right now.


If you like what I do, consider casting a vote for me as witness on Hivesigner or on PeakD

Sort:  

@holger80,
Interesting, never seen this device before!
$tan

Cheers~


Congratulations, @theguruasia You Successfully Trended The Post Shared By @holger80.
You Utilized 3/3 Daily Summon Bot Calls.

TAN Current Market Price : 1.250 HIVE

Upvoted to thank you @holger80 for supporting the CO2Fund by, e.g., supporting posts, banner presentation, SP/HP delegation, dustsweeper gifts, helpful tools, etc.

$tangent


Congratulations, @asimo You Successfully Trended The Post Shared By @holger80.
You Utilized 1/3 Daily Summon Bot Calls.

TAN Current Market Price : 1.500 HIVE


Congratulations @holger80, You Earned 1.797 TAN & Curators Made 1.258 TAN.

tangent.token


Join CORE / VAULT Token Discord Channel or Trade TANGENT Token
TAN Current Market Price : 0.887 HIVE

I am very motivated with you, for your constant positive evaluations of my publications. Thank you. God will always be with you. Hugs from Venezuela. Success for you is my sincere wish this Christmas.