Pages:
Author

Topic: Zsh/OpenSSL Shell Script Key Generator - page 2. (Read 5513 times)

pc
sr. member
Activity: 253
Merit: 250
December 24, 2012, 10:01:55 PM
#1
I've been intrigued for a while by the use of bitaddress.org and Bitcoin off-the-grid (BOTG) to generate keys for secure storage (and gift-certificate-like paper keys). I particularly liked how BOTG just used basic things that were part of most linux-like systems and straight OpenSSL to generate the keys. (While I think bitaddress.org's code is probably fine, I'm a little paranoid about using Javascript to generate the random numbers, and OpenSSL is basically the standard.) Also, I wanted to play around with learning zsh scripting. I used a lot of the code from BOTG, but adapted it in several ways: (1) Zsh is a little different than most shells, and so I had to make a couple tweaks (like 1-indexing arrays), (2) I'm on a Mac, and a couple of the utilities it used weren't available. (Though for all I know, this won't work on a linux system now), (3) I wanted to support the full range of keys that OpenSSL generated, rather than just most of them (I think that BOTG eliminated about a bit of private key availability, not that it [em]really[/em] matters), (4) I'm not convinced that the BOTG address-generating code worked for addresses that were less than 34 characters, and though I might have I redid it anyway.

I very much appreciate the BOTG base, and it handles a lot more things than this code does. This is just a way to generate a key with OpenSSL and find its address, so that one can send coins there and then later import the key into a wallet. Any contributions here which are mine I put into the public domain. (And as usual, no warranty, while I've tested it for my purposes and it seems good to me and I plan to use it, there's of course the chance of a subtle bug that will mean you can't get your coins or something.)

To run, just put the code in a file and mark it executable. Pass an argument of "1" if you'd like to see all the details of the OpenSSL key to check everything.

Code:
#!/bin/zsh
debug=$1
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)

capitalizeHex() {
    tr "[a-f]" "[A-F]"
}

encodeBase58() {                                 
    initialones=$(sed -e 's/\(\(00\)*\).*/\1/' -e 's/00/1/g' <<<$1)
    echo -n $initialones
    bc <<<"ibase=16; n=$1; while(n>0) { n%3A ; n/=3A }" |
    tail -r |
    while read n
        do echo -n ${base58[n+1]}
    done
}

checksum() {
    xxd -p -r <<<"$1" |
    openssl dgst -sha256 -binary |
    openssl dgst -sha256 -binary |
    xxd -p -c 80 |
    head -c 8 |
    capitalizeHex
}

hexToAddress() {
    echo "$(encodeBase58 "$2$1$(checksum "$2$1")")"
}

privatekey=$(openssl ecparam -genkey -name secp256k1 -noout)
openssldescription=$(openssl ec -text <<<$privatekey 2>/dev/null)
privatekeyhex=$(head -5 <<<$openssldescription | tail -3 | fmt -120 | sed -e 's/[: ]//g' -e 's/^00//' | awk '{printf "%064s\n", $0}' | capitalizeHex)
publickeyhashhex=$(openssl ec -pubout -outform DER <<<$privatekey 2>/dev/null | tail -c 65 | openssl dgst -sha256 -binary | openssl dgst -rmd160 -binary | xxd -p -c 80 | capitalizeHex)
address=$(hexToAddress $publickeyhashhex "00")
privatekeywif=$(hexToAddress $privatekeyhex "80")

(( $debug )) && echo $openssldescription
echo "Private Key Hex:" $privatekeyhex
echo "Private Key WIF:" $privatekeywif
(( $debug )) && echo "Public Key Hash:" $publickeyhashhex
echo "Address:" $address
Pages:
Jump to: