// NewSignature generates a ECDSA signature given the raw transaction and privateKey to sign with func NewSignature(rawTransaction []byte, privateKey []byte) ([]byte, error) { //Start secp256k1 secp256k1.Start() var privateKey32 [32]byte for i := 0; i < 32; i++ { privateKey32[i] = privateKey[i] } //Get the raw public key publicKey, success := secp256k1.Pubkey_create(privateKey32, false) if !success { return nil, errors.New("Failed to create public key from provided private key.") } //Hash the raw transaction twice with SHA256 before the signing shaHash := sha256.New() shaHash.Write(rawTransaction) var hash []byte = shaHash.Sum(nil) shaHash2 := sha256.New() shaHash2.Write(hash) rawTransactionHashed := shaHash2.Sum(nil) //Sign the raw transaction signedTransaction, success := secp256k1.Sign(rawTransactionHashed, privateKey32, newNonce()) if !success { return nil, errors.New("Failed to sign transaction") } //Verify that it worked. verified := secp256k1.Verify(rawTransactionHashed, signedTransaction, publicKey) if !verified { return nil, errors.New("Failed to verify signed transaction") } //Stop secp256k1 and return signature secp256k1.Stop() return signedTransaction, nil }
// NewPublicKey generates the public key from the private key. // Unfortunately golang ecdsa package does not include a // secp256k1 curve as this is fairly specific to Bitcoin. // Using toxeus/go-secp256k1 which wraps the official bitcoin/c-secp256k1 with cgo. func NewPublicKey(privateKey []byte) ([]byte, error) { var privateKey32 [32]byte for i := 0; i < 32; i++ { privateKey32[i] = privateKey[i] } secp256k1.Start() publicKey, success := secp256k1.Pubkey_create(privateKey32, false) if !success { return nil, errors.New("Failed to create public key from provided private key.") } secp256k1.Stop() return publicKey, nil }