Exemple #1
0
func GenerateKeyPair() ([]byte, []byte) {
	var seckey []byte = randentropy.GetEntropyCSPRNG(32)
	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0]))
	var pubkey64 []byte = make([]byte, 64) // secp256k1_pubkey
	var pubkey65 []byte = make([]byte, 65) // 65 byte uncompressed pubkey
	pubkey64_ptr := (*C.secp256k1_pubkey)(unsafe.Pointer(&pubkey64[0]))
	pubkey65_ptr := (*C.uchar)(unsafe.Pointer(&pubkey65[0]))

	ret := C.secp256k1_ec_pubkey_create(
		context,
		pubkey64_ptr,
		seckey_ptr,
	)

	if ret != C.int(1) {
		return GenerateKeyPair() // invalid secret, try again
	}

	var output_len C.size_t

	C.secp256k1_ec_pubkey_serialize( // always returns 1
		context,
		pubkey65_ptr,
		&output_len,
		pubkey64_ptr,
		0, // SECP256K1_EC_COMPRESSED
	)

	return pubkey65, seckey
}
Exemple #2
0
// recovers a public key from the signature
func RecoverPubkey(msg []byte, sig []byte) ([]byte, error) {
	if len(sig) != 65 {
		return nil, errors.New("Invalid signature length")
	}

	msg_ptr := (*C.uchar)(unsafe.Pointer(&msg[0]))
	sig_ptr := (*C.uchar)(unsafe.Pointer(&sig[0]))

	pubkey := make([]byte, 64)
	/*
		this slice is used for both the recoverable signature and the
		resulting serialized pubkey (both types in libsecp256k1 are 65
		bytes). this saves one allocation of 65 bytes, which is nice as
		pubkey recovery is one bottleneck during load in Ethereum
	*/
	bytes65 := make([]byte, 65)

	pubkey_ptr := (*C.secp256k1_pubkey)(unsafe.Pointer(&pubkey[0]))
	recoverable_sig_ptr := (*C.secp256k1_ecdsa_recoverable_signature)(unsafe.Pointer(&bytes65[0]))

	recid := C.int(sig[64])
	ret := C.secp256k1_ecdsa_recoverable_signature_parse_compact(
		context,
		recoverable_sig_ptr,
		sig_ptr,
		recid)

	if ret == C.int(0) {
		return nil, errors.New("Failed to parse signature")
	}

	ret = C.secp256k1_ecdsa_recover(
		context,
		pubkey_ptr,
		recoverable_sig_ptr,
		msg_ptr,
	)

	if ret == C.int(0) {
		return nil, errors.New("Failed to recover public key")
	} else {
		serialized_pubkey_ptr := (*C.uchar)(unsafe.Pointer(&bytes65[0]))

		var output_len C.size_t
		C.secp256k1_ec_pubkey_serialize( // always returns 1
			context,
			serialized_pubkey_ptr,
			&output_len,
			pubkey_ptr,
			0, // SECP256K1_EC_COMPRESSED
		)
		return bytes65, nil
	}
}