Skip to content

bitcoin sig: add public key into signature #670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions cmd/transaction/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,13 +250,25 @@ func GenerateBasicTransaction(
senderAccountAddress = crypto.NewEd25519Signature().GetAddressFromSeed(senderSeed)
case model.SignatureType_BitcoinSignature:
var (
bitcoinSig = crypto.NewBitcoinSignature(crypto.DefaultBitcoinNetworkParams(), crypto.DefaultBitcoinCurve())
pubKey = bitcoinSig.GetPublicKeyFromSeed(senderSeed, crypto.DefaultBitcoinPublicKeyFormat())
err error
bitcoinSig = crypto.NewBitcoinSignature(crypto.DefaultBitcoinNetworkParams(), crypto.DefaultBitcoinCurve())
pubKey, err = bitcoinSig.GetPublicKeyFromSeed(
senderSeed,
crypto.DefaultBitcoinPublicKeyFormat(),
crypto.DefaultBitcoinPrivateKeyLength(),
)
)
senderAccountAddress, err = bitcoinSig.GetAddressPublicKey(pubKey)
if err != nil {
fmt.Println("GenerateBasicTransaction-BitcoinSignature-Failed GetPublicKey")
panic(fmt.Sprintln(
"GenerateBasicTransaction-BitcoinSignature-Failed GetPublicKey",
err.Error(),
))
}
senderAccountAddress, err = bitcoinSig.GetAddressFromPublicKey(pubKey)
if err != nil {
panic(fmt.Sprintln(
"GenerateBasicTransaction-BitcoinSignature-Failed GetPublicKey",
err.Error(),
))
}
default:
panic("GenerateBasicTransaction-Invalid Signature Type")
Expand Down
112 changes: 76 additions & 36 deletions common/crypto/bitcoinSignature.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package crypto

import (
"hash"

"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil"
"github.com/zoobc/zoobc-core/common/blocker"
"github.com/zoobc/zoobc-core/common/model"
"golang.org/x/crypto/sha3"
)

Expand All @@ -30,9 +34,14 @@ func DefaultBitcoinCurve() *btcec.KoblitzCurve {
}

// DefaultBitcoinPublicKeyFormat return recommended public key format
func DefaultBitcoinPublicKeyFormat() btcutil.PubKeyFormat {
func DefaultBitcoinPublicKeyFormat() model.BitcoinPublicKeyFormat {
// https://bitcoin.org/en/glossary/compressed-public-key
return btcutil.PKFCompressed
return model.BitcoinPublicKeyFormat_PublicKeyFormatCompressed
}

// DefaultBitcoinPrivateKeyLength to
func DefaultBitcoinPrivateKeyLength() model.PrivateKeyBytesLength {
return model.PrivateKeyBytesLength_PrivateKey256Bits
}

// NewBitcoinSignature is new instance of bitcoin signature
Expand All @@ -47,7 +56,7 @@ func NewBitcoinSignature(netParams *chaincfg.Params, curve *btcec.KoblitzCurve)
func (*BitcoinSignature) Sign(privateKey *btcec.PrivateKey, payload []byte) ([]byte, error) {
var sig, err = privateKey.Sign(payload)
if err != nil {
return nil, err
return nil, blocker.NewBlocker(blocker.AuthErr, err.Error())
}
return sig.Serialize(), nil
}
Expand All @@ -67,70 +76,101 @@ func (b *BitcoinSignature) GetNetworkParams() *chaincfg.Params {
}

// GetPrivateKeyFromSeed to get private key form seed
func (b *BitcoinSignature) GetPrivateKeyFromSeed(seed string) *btcec.PrivateKey {
func (b *BitcoinSignature) GetPrivateKeyFromSeed(
seed string,
privkeyLength model.PrivateKeyBytesLength,
) (*btcec.PrivateKey, error) {
var (
// Convert seed (secret phrase) to byte array
seedBuffer = []byte(seed)
// Compute SHA3-256 hash of seed (secret phrase)
seedHash = sha3.Sum256(seedBuffer)
privateKey, _ = btcec.PrivKeyFromBytes(b.Curve, seedHash[:])
hasher hash.Hash
privateKey *btcec.PrivateKey
)
return privateKey
switch privkeyLength {
case model.PrivateKeyBytesLength_PrivateKey256Bits:
hasher = sha3.New256()
case model.PrivateKeyBytesLength_PrivateKey384Bits:
hasher = sha3.New384()
case model.PrivateKeyBytesLength_PrivateKey512Bits:
hasher = sha3.New512()
default:
return nil, blocker.NewBlocker(blocker.AppErr, "invalidPrivateKeyLength")
}
hasher.Write(seedBuffer)
privateKey, _ = btcec.PrivKeyFromBytes(b.Curve, hasher.Sum(nil))
return privateKey, nil
}

// GetPublicKeyFromSeed Get the raw public key corresponding to a seed (secret phrase)
func (b *BitcoinSignature) GetPublicKeyFromSeed(
seed string,
format model.BitcoinPublicKeyFormat,
privkeyLength model.PrivateKeyBytesLength,
) ([]byte, error) {
var privateKey, err = b.GetPrivateKeyFromSeed(seed, privkeyLength)
if err != nil {
return nil, err
}
publicKey, err := b.GetPublicKeyFromPrivateKey(privateKey, format)
if err != nil {
return nil, err
}
return publicKey, nil
}

// GetPublicKeyFromPrivateKey get raw public key from private key
// public key format : https://bitcoin.org/en/wallets-guide#public-key-formats
func (b *BitcoinSignature) GetPublicKeyFromSeed(seed string, format btcutil.PubKeyFormat) []byte {
var privateKey = b.GetPrivateKeyFromSeed(seed)
func (*BitcoinSignature) GetPublicKeyFromPrivateKey(
privateKey *btcec.PrivateKey,
format model.BitcoinPublicKeyFormat,
) ([]byte, error) {
switch format {
case btcutil.PKFUncompressed:
return privateKey.PubKey().SerializeUncompressed()
case btcutil.PKFCompressed:
return privateKey.PubKey().SerializeCompressed()
case btcutil.PKFHybrid:
return privateKey.PubKey().SerializeHybrid()
case model.BitcoinPublicKeyFormat_PublicKeyFormatUncompressed:
return privateKey.PubKey().SerializeUncompressed(), nil
case model.BitcoinPublicKeyFormat_PublicKeyFormatCompressed:
return privateKey.PubKey().SerializeCompressed(), nil
default:
return nil
return nil, blocker.NewBlocker(blocker.AppErr, "invalidPublicKeyFormat")
}
}

// GetAddressPublicKey to get address public key from seed
// NOTE: Currently the address is the hex-encoded from serialized public key (pay-to-pubkey)
func (b *BitcoinSignature) GetAddressPublicKey(publicKey []byte) (string, error) {
// GetPublicKeyFromBytes to get public key from raw bytes public key
func (b *BitcoinSignature) GetPublicKeyFromBytes(pubkey []byte) (*btcec.PublicKey, error) {
return btcec.ParsePubKey(pubkey, b.Curve)
}

// GetPublicKeyString will return hex string from bytes public key
func (b *BitcoinSignature) GetPublicKeyString(publicKey []byte) (string, error) {
var address, err = btcutil.NewAddressPubKey(publicKey, b.GetNetworkParams())
if err != nil {
return "", err
return "", blocker.NewBlocker(blocker.ParserErr, err.Error())
}
return address.String(), nil
}

// GetBytesAddressPublicKey Get raw bytes of address
func (b *BitcoinSignature) GetBytesAddressPublicKey(address string) ([]byte, error) {
var decodedAddress, err = btcutil.DecodeAddress(address, b.GetNetworkParams())
// GetAddressFromPublicKey to get address public key from seed
func (b *BitcoinSignature) GetAddressFromPublicKey(publicKey []byte) (string, error) {
var address, err = btcutil.NewAddressPubKey(publicKey, b.GetNetworkParams())
if err != nil {
return nil, err
return "", blocker.NewBlocker(blocker.ParserErr, err.Error())
}
return decodedAddress.ScriptAddress(), nil
return address.EncodeAddress(), nil
}

// GetPublicKeyFromAddress to get public key from address
func (b *BitcoinSignature) GetPublicKeyFromAddress(address string) (*btcec.PublicKey, error) {
rowBytesAddress, err := b.GetBytesAddressPublicKey(address)
if err != nil {
return nil, err
}
publicKey, err := btcec.ParsePubKey(rowBytesAddress, b.Curve)
// GetAddressBytes Get raw bytes of address
func (b *BitcoinSignature) GetAddressBytes(address string) ([]byte, error) {
var decodedAddress, err = btcutil.DecodeAddress(address, b.GetNetworkParams())
if err != nil {
return nil, err
return nil, blocker.NewBlocker(blocker.ParserErr, err.Error())
}
return publicKey, nil
return decodedAddress.ScriptAddress(), nil
}

// GetSignatureFromBytes to get signature type from signature raw bytes
func (b *BitcoinSignature) GetSignatureFromBytes(signatureBytes []byte) (*btcec.Signature, error) {
var signature, err = btcec.ParseSignature(signatureBytes, b.Curve)
if err != nil {
return nil, err
return nil, blocker.NewBlocker(blocker.ParserErr, err.Error())
}
return signature, nil
}
Loading