diff --git a/crypto/secp256k1/secp256.go b/crypto/secp256k1/secp256.go index 35d0eef34a..ec708acd81 100644 --- a/crypto/secp256k1/secp256.go +++ b/crypto/secp256k1/secp256.go @@ -49,6 +49,41 @@ var ( ErrRecoverFailed = errors.New("recovery failed") ) +func VerifySeckeyValidity(seckey []byte) error { + if len(seckey) != 32 { + return errors.New("priv key is not 32 bytes") + } + var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0])) + ret := C.secp256k1_ec_seckey_verify(context, seckey_ptr) + if int(ret) != 1 { + return errors.New("invalid seckey") + } + return nil +} + +func GeneratePubKey(seckey []byte) ([]byte, error) { + if err := VerifySeckeyValidity(seckey); err != nil { + return nil, err + } + + var pubkey []byte = make([]byte, 64) + var pubkey_ptr *C.secp256k1_pubkey = (*C.secp256k1_pubkey)(unsafe.Pointer(&pubkey[0])) + + var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0])) + + ret := C.secp256k1_ec_pubkey_create( + context, + pubkey_ptr, + seckey_ptr, + ) + + if ret != C.int(1) { + return nil, errors.New("Unable to generate pubkey from seckey") + } + + return pubkey, nil +} + // Sign creates a recoverable ECDSA signature. // The produced signature is in the 65-byte [R || S || V] format where V is 0 or 1. // @@ -165,3 +200,4 @@ func checkSignature(sig []byte) error { } return nil } + diff --git a/crypto/secp256k1/secp256_test.go b/crypto/secp256k1/secp256_test.go index ef2a3a3790..04128366bf 100644 --- a/crypto/secp256k1/secp256_test.go +++ b/crypto/secp256k1/secp256_test.go @@ -236,3 +236,16 @@ func BenchmarkRecover(b *testing.B) { RecoverPubkey(msg, sig) } } + +func TestPubkeyCreate(t *testing.T) { + seckey, _ := hex.DecodeString("ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008") + pubkey1, _ := hex.DecodeString("12aabd7c2132f6690b4754ebb7a2b0e15baa317920c316c60a0f9bc8bf268c85417fc475b2ba24f402f150537e40c10a56adad27d4d32d9b556c255fd2e15aa0") + pubkey2, err := GeneratePubKey(seckey) + if err != nil { + t.Fatalf("recover error: %s", err) + } + if !bytes.Equal(pubkey1, pubkey2) { + t.Errorf("pubkey mismatch: want: %x have: %x", pubkey1, pubkey2) + } +} +