Using openssl, you can convert private keys to public keys from the command line. The following command gives you the public key from a known private key. Part of it is from the same script that has been posted on BitcoinTalk some time ago and referred in this answer.
The private key should be in the form of a PEM file like this:
$ cat private_key.pem
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIMURrYd6CTHlrrV0JOxnze9ldaq3mRYMnYJ8195GldAVoAcGBSuBBAAK
oUQDQgAEANPTV3v+8AMXnIPaerOWziyc6tHbmbhORhbVKv1ACYuO+ohlFaV6QaOz
/AGjoSXV0ZeKxq7FijsAdBzeu23Fgg==
-----END EC PRIVATE KEY-----
Note: if you have a private key in hex format, then you should convert it to PEM format, using the procedure described here.
As said, to obtain the public key from the private key we use openssl:
$ openssl ec -pubout /dev/null
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEANPTV3v+8AMXnIPaerOWziyc6tHbmbhO
RhbVKv1ACYuO+ohlFaV6QaOz/AGjoSXV0ZeKxq7FijsAdBzeu23Fgg==
-----END PUBLIC KEY-----
In order to convert a public key to a bitcoin address, we need some steps:
First we need to compute the hash160 of the public key. This can be done as follows:
$ openssl ec -pubout /dev/null |
openssl ec -pubin -pubout -outform DER 2>/dev/null |
tail -c 65 |
openssl dgst -sha256 -binary |
openssl dgst -rmd160 -binary |
xxd -p -c 80
ab085c55b735d4a811df3f55e6508634f1ce1e27
Then the hash160 has to be used to calculate the checksum as follows:
$ echo -n "ab085c55b735d4a811df3f55e6508634f1ce1e27" |
xxd -p -r |
openssl dgst -sha256 -binary |
openssl dgst -sha256 -binary |
xxd -p -c 80 |
head -c 8
7801f8dc
The hash160, combined with the checksum and with the first byte "00", can be encoded using base 58. This gives us the address:
base58=({1..9} {A..H} {J..N} {P..Z} {a..k} {m..z})
encodeBase58() {
# 58 = 0x3A
bc 0) { n%3A ; n/=3A }" |
tac |
while read n
do echo -n ${base58[n]}
done
}
$ printf "%34s\n" "$(encodeBase58 "00$1$(checksum "$char$1")")" |
sed "y/ /1/"
1GbLZiNzi7DTB4UowMuyqJw5Bh95yCbu3R
Putting all together, we can use the function publicKeyToAddress, as defined below. This can be part of a bash script, or you can type it on the command line.
base58=({1..9} {A..H} {J..N} {P..Z} {a..k} {m..z})
encodeBase58() {
# 58 = 0x3A
bc 0) { n%3A ; n/=3A }" |
tac |
while read n
do echo -n ${base58[n]}
done
}
checksum() {
xxd -p -r /dev/null |
tail -c 65 |
openssl dgst -sha256 -binary |
openssl dgst -rmd160 -binary |
xxd -p -c 80
)
}
$ openssl ec -pubout /dev/null | publicKeyToAddress
1GbLZiNzi7DTB4UowMuyqJw5Bh95yCbu3R