How to create a bitcoin address using simple commandline tools.

in #bitcoin3 years ago

(pic from https://tctechcrunch2011.files.wordpress.com)

Hey Steemit, in this post, I'm going to show you how to create a bitcoin address (private key and public address) using relatively simple commandline tools. This is some good kung-fu to know if you want to store a large amount of bitcoin and you are fairly paranoid.

Though you could do this on Windows, I would not recommend this. Use a Linux machine. Once you've got the tools you need, you should disconnect your machine from the network before generating the private key.

Step 1: Come up with a passphrase

We are going to turn some text into an address, so you need to come up with a passphrase. This is trickier than it sounds, because your passphrase must be very long and something that no bot will ever crack in a reasonable amount of time.

For a safe passphrase I would use something like this:

<name of the account> : <15 words and/or gibberish phrase, and also include a secure password, 12 character with upper and lowercase letters, numbers and symbols

Example:

neoxian test account: banana dogs dodge zebra miles hydra article bellpepper diet yellow cyberware readers thirteen chocolate bones onasdfe33(FF)

A phrase like this should be pretty safe. Write it down somewhere and keep it secret!

Step 2: Turn the passphrase into a private key

Ok, now that you have a good passphrase that's hard to guess and you have written it down, now you need a private key. On a Bash commandline this is easy to do:

echo -n "<phrase>" | sha256sum

Example:

echo -n "don't use this" | sha256sum

Result:
6782e7c3203a097a9b4c399d2ce9160e037f13646721dad9ea851ee89ac6716e

The result hexadecimal value is your private key, again you must keep this very safe.

Step 3: Generate the public address from your private key

Ok, you have your new private key, great! But you need to get the public address for this new account to be useful. There are a few ways to do this, but I'm going to recommend a fairly short bash script that should be easy to audit and make sure nothing nefarious is going on:

https://github.com/grondilu/bitcoin-bash-tools
This script is copyright (C) 2013 Lucien Grondin ([email protected])

I'll also include the script on the bottom of this post just to preserve it on the Steem blockchain (it's not very long).

Ok, so obtain the script and look it over to make sure it's ok, then run it:

source bitcoin.sh

Then

newBitcoinKey 0x<your private key> or
newBitcoinKey 0x6782e7c3203a097a9b4c399d2ce9160e037f13646721dad9ea851ee89ac6716e

You will get an output like:

secret exponent:          0x6782E7C3203A097A9B4C399D2CE9160E037F13646721DAD9EA851EE89AC6716E
public key:
    X:                    4CD1F49268836DA32D48C72C26F409E8E0E28E80EE94F997AF60D6BD2F01A37F
    Y:                    836299336CDDD125D9BBC74644EA85583F36651C639CA4CCA346DF7C14AEABF4
compressed:
    WIF:                  KzgvWdT3gLBk512EuwUL6XAvqyPjBeQ9C2C3a5hVvvL9AqK8fjfV
    bitcoin address:      1Dt7xMGaAKAyJUyhmGdPdB12Au4PzEabKi
uncompressed:
    WIF:                  5Jbse5BS5P25KaY6REFMBmSp6CsTn1KPFH8VDw5eNHAKcnsNqvE
    bitcoin address:      1D5GpSFUrgjaHaTEipDXjENCYWx7NoZdX3

Ok what you want is in the "uncompressed" section. There is a WIF which is a shorter version of your private key, and then below that is your public bitcoin address. The bitcoin address is the public address you can share with others.

Write these down in a safe place.

There you go! You have now made your very own bitcoin address.

Test it out using a tiny amount of bitcoin before using it seriously!!!!

Be careful!! Test it before putting serious money into it.

Measure twice, cut once!!

This is a good rule of thumb for any kind of crypto-anything! Be cautious!

This script is copyright (C) 2013 Lucien Grondin ([email protected])

#!/bin/bash
# Various bash bitcoin tools
#
# requires dc, the unix desktop calculator (which should be included in the
# 'bc' package)
#
# This script requires bash version 4 or above.
#
# This script uses GNU tools.  It is therefore not guaranted to work on a POSIX
# system.
# 
# Copyright (C) 2013 Lucien Grondin ([email protected])
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.


if ((BASH_VERSINFO[0] < 4))
then
    echo "This script requires bash version 4 or above." >&2
    exit 538510
fi

declare -a base58=(
      1 2 3 4 5 6 7 8 9
    A B C D E F G H   J K L M N   P Q R S T U V W X Y Z
    a b c d e f g h i j k   m n o p q r s t u v w x y z
)
unset dcr; for i in {0..57}; do dcr+="${i}s${base58[i]}"; done
declare ec_dc='
I16i7sb0sa[[_1*lm1-*lm%q]Std0>tlm%Lts#]s%[Smddl%x-lm/rl%xLms#]s~
483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
2 100^d14551231950B75FC4402DA1732FC9BEBF-so1000003D1-ddspsm*+sGi
[_1*l%x]s_[+l%x]s+[*l%x]s*[-l%x]s-[l%xsclmsd1su0sv0sr1st[q]SQ[lc
0=Qldlcl~xlcsdscsqlrlqlu*-ltlqlv*-lulvstsrsvsulXx]dSXxLXs#LQs#lr
l%x]sI[lpSm[+q]S0d0=0lpl~xsydsxd*3*lal+x2ly*lIx*l%xdsld*2lx*l-xd
lxrl-xlll*xlyl-xrlp*+Lms#L0s#]sD[lpSm[+q]S0[2;AlDxq]Sdd0=0rd0=0d
2:Alp~1:A0:Ad2:Blp~1:B0:B2;A2;B=d[0q]Sx2;A0;B1;Bl_xrlm*+=x0;A0;B
l-xlIxdsi1;A1;Bl-xl*xdsld*0;Al-x0;Bl-xd0;Arl-xlll*x1;Al-xrlp*+L0
s#Lds#Lxs#Lms#]sA[rs.0r[rl.lAxr]SP[q]sQ[d0!<Qd2%1=P2/l.lDxs.lLx]
dSLxs#LPs#LQs#]sM[lpd1+4/r|]sR
';

decodeBase58() {
    echo -n "$1" | sed -e's/^\(1*\).*/\1/' -e's/1/00/g' | tr -d '\n'
    dc -e "$dcr 16o0$(sed 's/./ 58*l&+/g' <<<$1)p" |
    while read n; do echo -n ${n/\\/}; done
}
encodeBase58() {
    echo -n "$1" | sed -e's/^\(\(00\)*\).*/\1/' -e's/00/1/g' | tr -d '\n'
    dc -e "16i ${1^^} [3A ~r d0<x]dsxx +f" |
    while read -r n; do echo -n "${base58[n]}"; done
}

checksum() {
    perl -we "print pack 'H*', '$1'" |
    openssl dgst -sha256 -binary |
    openssl dgst -sha256 -binary |
    perl -we "print unpack 'H8', join '', <>"
}

checkBitcoinAddress() {
    if [[ "$1" =~ ^[$(IFS= ; echo "${base58[*]}")]+$ ]]
    then
        local h="$(decodeBase58 "$1")"
        checksum "${h:0:-8}" | grep -qi "^${h:${#h}-8}$"
    else return 2
    fi
}

hash160() {
    openssl dgst -sha256 -binary |
    openssl dgst -rmd160 -binary |
    perl -we "print unpack 'H*', join '', <>"
}

hexToAddress() {
    local x="$(printf "%2s%${3:-40}s" ${2:-00} $1 | sed 's/ /0/g')"
    encodeBase58 "$x$(checksum "$x")"
    echo
}

newBitcoinKey() {
    if [[ "$1" =~ ^[5KL] ]] && checkBitcoinAddress "$1"
    then
    local decoded="$(decodeBase58 "$1")"
    if [[ "$decoded" =~ ^80([0-9A-F]{64})(01)?[0-9A-F]{8}$ ]]
    then $FUNCNAME "0x${BASH_REMATCH[1]}"
    fi
    elif [[ "$1" =~ ^[0-9]+$ ]]
    then $FUNCNAME "0x$(dc -e "16o$1p")"
    elif [[ "${1^^}" =~ ^0X([0-9A-F]{1,64})$ ]]
    then 
    local exponent="${BASH_REMATCH[1]}"
    local uncompressed_wif="$(hexToAddress "$exponent" 80 64)"
    local compressed_wif="$(hexToAddress "${exponent}01" 80 66)"
    dc -e "$ec_dc lG I16i${exponent^^}ri lMx 16olm~ n[ ]nn" |
    {
        read y x
        X="$(printf "%64s" $x| sed 's/ /0/g')"
        Y="$(printf "%64s" $y| sed 's/ /0/g')"
        if [[ "$y" =~ [02468ACE]$ ]]
        then y_parity="02"
        else y_parity="03"
        fi
        uncompressed_addr="$(hexToAddress "$(perl -e "print pack q(H*), q(04$X$Y)" | hash160)")"
        compressed_addr="$(hexToAddress "$(perl -e "print pack q(H*), q($y_parity$X)" | hash160)")"
        echo ---
            echo "secret exponent:          0x$exponent"
        echo "public key:"
        echo "    X:                    $X"
        echo "    Y:                    $Y"
            echo "compressed:"
            echo "    WIF:                  $compressed_wif"
            echo "    bitcoin address:      $compressed_addr"
            echo "uncompressed:"
            echo "    WIF:                  $uncompressed_wif"
            echo "    bitcoin address:      $uncompressed_addr"
    }
    elif test -z "$1"
    then $FUNCNAME "0x$(openssl rand -rand <(date +%s%N; ps -ef) -hex 32 2>&-)"
    else
    echo unknown key format "$1" >&2
    return 2
    fi
}

vanityAddressFromPublicPoint() {
    if [[ "$1" =~ ^04([0-9A-F]{64})([0-9A-F]{64})$ ]]
    then
    dc <<<"$ec_dc 16o
    0 ${BASH_REMATCH[1]} ${BASH_REMATCH[2]} rlp*+ 
    [lGlAxdlm~rn[ ]nn[ ]nr1+prlLx]dsLx
    " |
    while read -r x y n
    do
        local public_key="$(printf "04%64s%64s" $x $y | sed 's/ /0/g')"
        local h="$(perl -e "print pack q(H*), q($public_key)" | hash160)"
        local addr="$(hexToAddress "$h")"
        if [[ "$addr" =~ "$2" ]]
        then
        echo "FOUND! $n: $addr"
        return
        else echo "$n: $addr"
        fi
    done
    else 
    echo unexpected format for public point >&2
    return 1
    fi
}
Sort:  

I forget to tell you something @neoxian. It's gonna take me a while because I have to get a linux OS device and learn the script as fast as possible. I am still gonna try it out soon.

Let me know when you try it out.

Thanks for this piece of enlightenment. I will try it out.

This Glacier protocal has a method for using Casino Grade Dice as a way to generate random numbers to create your Bitcoin Wallet address!

https://news.bitcoin.com/extreme-cold-storage-fortress-solitude-bitcoins/

Hmm, I'm not sure I'm that paranoid, but thanks.

nicely explained but need to try it first :)

I'm trying to understand this but my coding weakness is affecting me. I really need to learn to code.

@neoxian boss, could you help with a pointer to where to start from?

I only have basic understanding of HTML and CSS

You need to learn about Linux and the Bash command shell.

I hope to begin the learning process soon. I really need to know how to code

I suppose coding is not my forte buddy
Some of them went above mu head !1

Neat, thanks for spreading the crypto knowledge. I'll try it out!

Thank you so much this was much needed. I need all the help i can get . 😁

This is a good tutorial and i am sure it is worth trying out. But will this also work for bitcoin cash or gold as well? I use windows but you advice against using such OS, probably I might try it soon when i get a linux OS computer.

Yes it should also work for bitcoin cash and bitcoin gold. Linux is awesome, you should be using it anyways ;)

can you make a guide for beginners :D thanks for this post BTW

Hmm, this was my beginners guide..although I'll admit it does require some commandline kung-fu, and it isn't really for complete newbies.

i will try it asap use if any problem i know where are you :=)

There is no way you read it that fast.