move go-crypto files pre-keys merge

This commit is contained in:
Ethan Frey
2017-04-19 16:51:29 +02:00
parent 8bb25ec5ed
commit 17ed6d178d
24 changed files with 0 additions and 0 deletions
-290
View File
@@ -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
}
-37
View File
@@ -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
View File
@@ -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
}
-1
View File
File diff suppressed because one or more lines are too long