mirror of
https://github.com/tendermint/tendermint.git
synced 2026-09-05 23:57:04 +00:00
move go-crypto files pre-keys merge
This commit is contained in:
-290
@@ -1,290 +0,0 @@
|
||||
package hd
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"log"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcutil/base58"
|
||||
"github.com/tendermint/go-crypto"
|
||||
"golang.org/x/crypto/ripemd160"
|
||||
)
|
||||
|
||||
func ComputeAddress(pubKeyHex string, chainHex string, path string, index int32) string {
|
||||
pubKeyBytes := DerivePublicKeyForPath(
|
||||
HexDecode(pubKeyHex),
|
||||
HexDecode(chainHex),
|
||||
fmt.Sprintf("%v/%v", path, index),
|
||||
)
|
||||
return AddrFromPubKeyBytes(pubKeyBytes)
|
||||
}
|
||||
|
||||
func ComputePrivateKey(mprivHex string, chainHex string, path string, index int32) string {
|
||||
privKeyBytes := DerivePrivateKeyForPath(
|
||||
HexDecode(mprivHex),
|
||||
HexDecode(chainHex),
|
||||
fmt.Sprintf("%v/%v", path, index),
|
||||
)
|
||||
return HexEncode(privKeyBytes)
|
||||
}
|
||||
|
||||
func ComputeAddressForPrivKey(privKey string) string {
|
||||
pubKeyBytes := PubKeyBytesFromPrivKeyBytes(HexDecode(privKey), true)
|
||||
return AddrFromPubKeyBytes(pubKeyBytes)
|
||||
}
|
||||
|
||||
func SignMessage(privKey string, message string, compress bool) string {
|
||||
prefixBytes := []byte("Bitcoin Signed Message:\n")
|
||||
messageBytes := []byte(message)
|
||||
bytes := []byte{}
|
||||
bytes = append(bytes, byte(len(prefixBytes)))
|
||||
bytes = append(bytes, prefixBytes...)
|
||||
bytes = append(bytes, byte(len(messageBytes)))
|
||||
bytes = append(bytes, messageBytes...)
|
||||
privKeyBytes := HexDecode(privKey)
|
||||
x, y := btcec.S256().ScalarBaseMult(privKeyBytes)
|
||||
ecdsaPubKey := ecdsa.PublicKey{
|
||||
Curve: btcec.S256(),
|
||||
X: x,
|
||||
Y: y,
|
||||
}
|
||||
ecdsaPrivKey := &btcec.PrivateKey{
|
||||
PublicKey: ecdsaPubKey,
|
||||
D: new(big.Int).SetBytes(privKeyBytes),
|
||||
}
|
||||
sigbytes, err := btcec.SignCompact(btcec.S256(), ecdsaPrivKey, crypto.Sha256(crypto.Sha256(bytes)), compress)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return base64.StdEncoding.EncodeToString(sigbytes)
|
||||
}
|
||||
|
||||
// returns MPK, Chain, and master secret in hex.
|
||||
func ComputeMastersFromSeed(seed string) (string, string, string, string) {
|
||||
secret, chain := I64([]byte("Bitcoin seed"), []byte(seed))
|
||||
pubKeyBytes := PubKeyBytesFromPrivKeyBytes(secret, true)
|
||||
return HexEncode(pubKeyBytes), HexEncode(secret), HexEncode(chain), HexEncode(secret)
|
||||
}
|
||||
|
||||
func ComputeWIF(privKey string, compress bool) string {
|
||||
return WIFFromPrivKeyBytes(HexDecode(privKey), compress)
|
||||
}
|
||||
|
||||
func ComputeTxId(rawTxHex string) string {
|
||||
return HexEncode(ReverseBytes(CalcHash256(HexDecode(rawTxHex))))
|
||||
}
|
||||
|
||||
// Private methods...
|
||||
|
||||
func printKeyInfo(privKeyBytes []byte, pubKeyBytes []byte, chain []byte) {
|
||||
if pubKeyBytes == nil {
|
||||
pubKeyBytes = PubKeyBytesFromPrivKeyBytes(privKeyBytes, true)
|
||||
}
|
||||
addr := AddrFromPubKeyBytes(pubKeyBytes)
|
||||
log.Println("\nprikey:\t%v\npubKeyBytes:\t%v\naddr:\t%v\nchain:\t%v",
|
||||
HexEncode(privKeyBytes),
|
||||
HexEncode(pubKeyBytes),
|
||||
addr,
|
||||
HexEncode(chain))
|
||||
}
|
||||
|
||||
func DerivePrivateKeyForPath(privKeyBytes []byte, chain []byte, path string) []byte {
|
||||
data := privKeyBytes
|
||||
parts := strings.Split(path, "/")
|
||||
for _, part := range parts {
|
||||
prime := part[len(part)-1:] == "'"
|
||||
// prime == private derivation. Otherwise public.
|
||||
if prime {
|
||||
part = part[:len(part)-1]
|
||||
}
|
||||
i, err := strconv.Atoi(part)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if i < 0 {
|
||||
panic(errors.New("index too large."))
|
||||
}
|
||||
data, chain = DerivePrivateKey(data, chain, uint32(i), prime)
|
||||
//printKeyInfo(data, nil, chain)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func DerivePublicKeyForPath(pubKeyBytes []byte, chain []byte, path string) []byte {
|
||||
data := pubKeyBytes
|
||||
parts := strings.Split(path, "/")
|
||||
for _, part := range parts {
|
||||
prime := part[len(part)-1:] == "'"
|
||||
if prime {
|
||||
panic(errors.New("cannot do a prime derivation from public key"))
|
||||
}
|
||||
i, err := strconv.Atoi(part)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if i < 0 {
|
||||
panic(errors.New("index too large."))
|
||||
}
|
||||
data, chain = DerivePublicKey(data, chain, uint32(i))
|
||||
//printKeyInfo(nil, data, chain)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func DerivePrivateKey(privKeyBytes []byte, chain []byte, i uint32, prime bool) ([]byte, []byte) {
|
||||
data := []byte{}
|
||||
if prime {
|
||||
i = i | 0x80000000
|
||||
data = append([]byte{byte(0)}, privKeyBytes...)
|
||||
} else {
|
||||
public := PubKeyBytesFromPrivKeyBytes(privKeyBytes, true)
|
||||
data = public
|
||||
}
|
||||
data = append(data, uint32ToBytes(i)...)
|
||||
data2, chain2 := I64(chain, data)
|
||||
x := addScalars(privKeyBytes, data2)
|
||||
return x, chain2
|
||||
}
|
||||
|
||||
func DerivePublicKey(pubKeyBytes []byte, chain []byte, i uint32) ([]byte, []byte) {
|
||||
data := []byte{}
|
||||
data = append(data, pubKeyBytes...)
|
||||
data = append(data, uint32ToBytes(i)...)
|
||||
data2, chain2 := I64(chain, data)
|
||||
data2p := PubKeyBytesFromPrivKeyBytes(data2, true)
|
||||
return addPoints(pubKeyBytes, data2p), chain2
|
||||
}
|
||||
|
||||
func addPoints(a []byte, b []byte) []byte {
|
||||
ap, err := btcec.ParsePubKey(a, btcec.S256())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
bp, err := btcec.ParsePubKey(b, btcec.S256())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sumX, sumY := btcec.S256().Add(ap.X, ap.Y, bp.X, bp.Y)
|
||||
sum := (*btcec.PublicKey)(&btcec.PublicKey{
|
||||
Curve: btcec.S256(),
|
||||
X: sumX,
|
||||
Y: sumY,
|
||||
})
|
||||
return sum.SerializeCompressed()
|
||||
}
|
||||
|
||||
func addScalars(a []byte, b []byte) []byte {
|
||||
aInt := new(big.Int).SetBytes(a)
|
||||
bInt := new(big.Int).SetBytes(b)
|
||||
sInt := new(big.Int).Add(aInt, bInt)
|
||||
x := sInt.Mod(sInt, btcec.S256().N).Bytes()
|
||||
x2 := [32]byte{}
|
||||
copy(x2[32-len(x):], x)
|
||||
return x2[:]
|
||||
}
|
||||
|
||||
func uint32ToBytes(i uint32) []byte {
|
||||
b := [4]byte{}
|
||||
binary.BigEndian.PutUint32(b[:], i)
|
||||
return b[:]
|
||||
}
|
||||
|
||||
func HexEncode(b []byte) string {
|
||||
return hex.EncodeToString(b)
|
||||
}
|
||||
|
||||
func HexDecode(str string) []byte {
|
||||
b, _ := hex.DecodeString(str)
|
||||
return b
|
||||
}
|
||||
|
||||
func I64(key []byte, data []byte) ([]byte, []byte) {
|
||||
mac := hmac.New(sha512.New, key)
|
||||
mac.Write(data)
|
||||
I := mac.Sum(nil)
|
||||
return I[:32], I[32:]
|
||||
}
|
||||
|
||||
// This returns a Bitcoin-like address.
|
||||
func AddrFromPubKeyBytes(pubKeyBytes []byte) string {
|
||||
prefix := byte(0x00) // TODO Make const or configurable
|
||||
h160 := CalcHash160(pubKeyBytes)
|
||||
h160 = append([]byte{prefix}, h160...)
|
||||
checksum := CalcHash256(h160)
|
||||
b := append(h160, checksum[:4]...)
|
||||
return base58.Encode(b)
|
||||
}
|
||||
|
||||
func AddrBytesFromPubKeyBytes(pubKeyBytes []byte) (addrBytes []byte, checksum []byte) {
|
||||
prefix := byte(0x00) // TODO Make const or configurable
|
||||
h160 := CalcHash160(pubKeyBytes)
|
||||
_h160 := append([]byte{prefix}, h160...)
|
||||
checksum = CalcHash256(_h160)[:4]
|
||||
return h160, checksum
|
||||
}
|
||||
|
||||
func WIFFromPrivKeyBytes(privKeyBytes []byte, compress bool) string {
|
||||
prefix := byte(0x80) // TODO Make const or configurable
|
||||
bytes := append([]byte{prefix}, privKeyBytes...)
|
||||
if compress {
|
||||
bytes = append(bytes, byte(1))
|
||||
}
|
||||
checksum := CalcHash256(bytes)
|
||||
bytes = append(bytes, checksum[:4]...)
|
||||
return base58.Encode(bytes)
|
||||
}
|
||||
|
||||
func PubKeyBytesFromPrivKeyBytes(privKeyBytes []byte, compress bool) (pubKeyBytes []byte) {
|
||||
x, y := btcec.S256().ScalarBaseMult(privKeyBytes)
|
||||
pub := (*btcec.PublicKey)(&btcec.PublicKey{
|
||||
Curve: btcec.S256(),
|
||||
X: x,
|
||||
Y: y,
|
||||
})
|
||||
|
||||
if compress {
|
||||
return pub.SerializeCompressed()
|
||||
}
|
||||
return pub.SerializeUncompressed()
|
||||
}
|
||||
|
||||
// Calculate the hash of hasher over buf.
|
||||
func CalcHash(buf []byte, hasher hash.Hash) []byte {
|
||||
hasher.Write(buf)
|
||||
return hasher.Sum(nil)
|
||||
}
|
||||
|
||||
// calculate hash160 which is ripemd160(sha256(data))
|
||||
func CalcHash160(buf []byte) []byte {
|
||||
return CalcHash(CalcHash(buf, sha256.New()), ripemd160.New())
|
||||
}
|
||||
|
||||
// calculate hash256 which is sha256(sha256(data))
|
||||
func CalcHash256(buf []byte) []byte {
|
||||
return CalcHash(CalcHash(buf, sha256.New()), sha256.New())
|
||||
}
|
||||
|
||||
// calculate sha512(data)
|
||||
func CalcSha512(buf []byte) []byte {
|
||||
return CalcHash(buf, sha512.New())
|
||||
}
|
||||
|
||||
func ReverseBytes(buf []byte) []byte {
|
||||
res := []byte{}
|
||||
for i := len(buf) - 1; i >= 0; i-- {
|
||||
res = append(res, buf[i])
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package hd
|
||||
|
||||
/*
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestManual(t *testing.T) {
|
||||
bytes, _ := hex.DecodeString("dfac699f1618c9be4df2befe94dc5f313946ebafa386756bd4926a1ecfd7cf2438426ede521d1ee6512391bc200b7910bcbea593e68d52b874c29bdc5a308ed1")
|
||||
fmt.Println(bytes)
|
||||
puk, prk, ch, se := ComputeMastersFromSeed(string(bytes))
|
||||
fmt.Println(puk, ch, se)
|
||||
|
||||
pubBytes2 := DerivePublicKeyForPath(
|
||||
HexDecode(puk),
|
||||
HexDecode(ch),
|
||||
//"44'/118'/0'/0/0",
|
||||
"0/0",
|
||||
)
|
||||
fmt.Printf("PUB2 %X\n", pubBytes2)
|
||||
|
||||
privBytes := DerivePrivateKeyForPath(
|
||||
HexDecode(prk),
|
||||
HexDecode(ch),
|
||||
//"44'/118'/0'/0/0",
|
||||
//"0/0",
|
||||
"44'/118'/0'/0/0",
|
||||
)
|
||||
fmt.Printf("PRIV %X\n", privBytes)
|
||||
pubBytes := PubKeyBytesFromPrivKeyBytes(privBytes, true)
|
||||
fmt.Printf("PUB %X\n", pubBytes)
|
||||
}
|
||||
|
||||
*/
|
||||
-189
@@ -1,189 +0,0 @@
|
||||
package hd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/sha512"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/tyler-smith/go-bip39"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
"github.com/mndrix/btcutil"
|
||||
"github.com/tyler-smith/go-bip32"
|
||||
|
||||
"github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
type addrData struct {
|
||||
Mnemonic string
|
||||
Master string
|
||||
Seed string
|
||||
Priv string
|
||||
Pub string
|
||||
Addr string
|
||||
}
|
||||
|
||||
// NOTE: atom fundraiser address
|
||||
var hdPath string = "m/44'/118'/0'/0/0"
|
||||
var hdToAddrTable []addrData
|
||||
|
||||
func init() {
|
||||
|
||||
b, err := ioutil.ReadFile("test.json")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(b, &hdToAddrTable)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHDToAddr(t *testing.T) {
|
||||
|
||||
for i, d := range hdToAddrTable {
|
||||
privB, _ := hex.DecodeString(d.Priv)
|
||||
pubB, _ := hex.DecodeString(d.Pub)
|
||||
addrB, _ := hex.DecodeString(d.Addr)
|
||||
seedB, _ := hex.DecodeString(d.Seed)
|
||||
masterB, _ := hex.DecodeString(d.Master)
|
||||
|
||||
seed := bip39.NewSeed(d.Mnemonic, "")
|
||||
|
||||
fmt.Println("================================")
|
||||
fmt.Println("ROUND:", i, "MNEMONIC:", d.Mnemonic)
|
||||
|
||||
// master, priv, pub := tylerSmith(seed)
|
||||
// master, priv, pub := btcsuite(seed)
|
||||
master, priv, pub := gocrypto(seed)
|
||||
|
||||
fmt.Printf("\tNODEJS GOLANG\n")
|
||||
fmt.Printf("SEED \t%X %X\n", seedB, seed)
|
||||
fmt.Printf("MSTR \t%X %X\n", masterB, master)
|
||||
fmt.Printf("PRIV \t%X %X\n", privB, priv)
|
||||
fmt.Printf("PUB \t%X %X\n", pubB, pub)
|
||||
_, _ = priv, privB
|
||||
|
||||
assert.Equal(t, master, masterB, fmt.Sprintf("Expected masters to match for %d", i))
|
||||
assert.Equal(t, priv, privB, "Expected priv keys to match")
|
||||
assert.Equal(t, pub, pubB, fmt.Sprintf("Expected pub keys to match for %d", i))
|
||||
|
||||
var pubT crypto.PubKeySecp256k1
|
||||
copy(pubT[:], pub)
|
||||
addr := pubT.Address()
|
||||
fmt.Printf("ADDR \t%X %X\n", addrB, addr)
|
||||
assert.Equal(t, addr, addrB, fmt.Sprintf("Expected addresses to match %d", i))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func ifExit(err error, n int) {
|
||||
if err != nil {
|
||||
fmt.Println(n, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func gocrypto(seed []byte) ([]byte, []byte, []byte) {
|
||||
|
||||
_, priv, ch, _ := ComputeMastersFromSeed(string(seed))
|
||||
|
||||
privBytes := DerivePrivateKeyForPath(
|
||||
HexDecode(priv),
|
||||
HexDecode(ch),
|
||||
"44'/118'/0'/0/0",
|
||||
)
|
||||
|
||||
pubBytes := PubKeyBytesFromPrivKeyBytes(privBytes, true)
|
||||
|
||||
return HexDecode(priv), privBytes, pubBytes
|
||||
}
|
||||
|
||||
func btcsuite(seed []byte) ([]byte, []byte, []byte) {
|
||||
fmt.Println("HD")
|
||||
masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
|
||||
if err != nil {
|
||||
hmac := hmac.New(sha512.New, []byte("Bitcoin seed"))
|
||||
hmac.Write([]byte(seed))
|
||||
intermediary := hmac.Sum(nil)
|
||||
|
||||
curve := btcutil.Secp256k1()
|
||||
curveParams := curve.Params()
|
||||
|
||||
// Split it into our key and chain code
|
||||
keyBytes := intermediary[:32]
|
||||
fmt.Printf("\t%X\n", keyBytes)
|
||||
fmt.Printf("\t%X\n", curveParams.N.Bytes())
|
||||
keyInt, _ := binary.ReadVarint(bytes.NewBuffer(keyBytes))
|
||||
fmt.Printf("\t%d\n", keyInt)
|
||||
}
|
||||
fh := hdkeychain.HardenedKeyStart
|
||||
k, err := masterKey.Child(uint32(fh + 44))
|
||||
ifExit(err, 44)
|
||||
k, err = k.Child(uint32(fh + 118))
|
||||
ifExit(err, 118)
|
||||
k, err = k.Child(uint32(fh + 0))
|
||||
ifExit(err, 1)
|
||||
k, err = k.Child(uint32(0))
|
||||
ifExit(err, 2)
|
||||
k, err = k.Child(uint32(0))
|
||||
ifExit(err, 3)
|
||||
ecpriv, err := k.ECPrivKey()
|
||||
ifExit(err, 10)
|
||||
ecpub, err := k.ECPubKey()
|
||||
ifExit(err, 11)
|
||||
|
||||
priv := ecpriv.Serialize()
|
||||
pub := ecpub.SerializeCompressed()
|
||||
mkey, _ := masterKey.ECPrivKey()
|
||||
return mkey.Serialize(), priv, pub
|
||||
}
|
||||
|
||||
// return priv and pub
|
||||
func tylerSmith(seed []byte) ([]byte, []byte, []byte) {
|
||||
masterKey, err := bip32.NewMasterKey(seed)
|
||||
if err != nil {
|
||||
hmac := hmac.New(sha512.New, []byte("Bitcoin seed"))
|
||||
hmac.Write([]byte(seed))
|
||||
intermediary := hmac.Sum(nil)
|
||||
|
||||
curve := btcutil.Secp256k1()
|
||||
curveParams := curve.Params()
|
||||
|
||||
// Split it into our key and chain code
|
||||
keyBytes := intermediary[:32]
|
||||
fmt.Printf("\t%X\n", keyBytes)
|
||||
fmt.Printf("\t%X\n", curveParams.N.Bytes())
|
||||
keyInt, _ := binary.ReadVarint(bytes.NewBuffer(keyBytes))
|
||||
fmt.Printf("\t%d\n", keyInt)
|
||||
|
||||
}
|
||||
ifExit(err, 0)
|
||||
fh := bip32.FirstHardenedChild
|
||||
k, err := masterKey.NewChildKey(fh + 44)
|
||||
ifExit(err, 44)
|
||||
k, err = k.NewChildKey(fh + 118)
|
||||
ifExit(err, 118)
|
||||
k, err = k.NewChildKey(fh + 0)
|
||||
ifExit(err, 1)
|
||||
k, err = k.NewChildKey(0)
|
||||
ifExit(err, 2)
|
||||
k, err = k.NewChildKey(0)
|
||||
ifExit(err, 3)
|
||||
|
||||
priv := k.Key
|
||||
pub := k.PublicKey().Key
|
||||
return masterKey.Key, priv, pub
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user