I am signing a transaction by using a private key in AWS Cloud HSM. But not able to recover the correct public key from the signature. Every time I try to run ECRecover method, it generates different public key.
I am able to retrieve the R and S from ECDSA signature generated by AWS Cloud HSM in the following code:
import (
"github.com/btcsuite/btcd/btcec"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
)
// SignatureValues returns signature values [R || S]
func (e *Ethereum) SignatureValues(sig []byte) (r, s *big.Int, err error) {
r = new(big.Int).SetBytes(sig[:32])
s = new(big.Int).SetBytes(sig[32:64])
return r, s, nil
}
And below code snippet tries to find the correct signature to be verified:
sig := make([]byte, 65)
denTwo := big.NewInt(2)
rightS := big.NewInt(0)
curve := btcec.S256()
/*
URL: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md
All transaction signatures whose s-value is greater than secp256k1n/2 are now considered invalid.
The ECDSA recover precompiled contract remains unchanged and will keep accepting high s-values; this is useful
e.g. if a contract recovers old Bitcoin signatures.
*/
rightS = rightS.Div(curve.Params().N, denTwo)
if rightS.Cmp(S) == -1 {
S = S.Sub(curve.Params().N, S)
log.Println("S: ", S.String())
rbytes, sbytes := R.Bytes(), S.Bytes()
copy(sig[32-len(rbytes):32], rbytes)
copy(sig[64-len(sbytes):64], sbytes)
log.Println("Result : ", verifyECRecover(hash.Bytes(), sig, expectedPubKey))
} else {
rbytes, sbytes := R.Bytes(), S.Bytes()
copy(sig[32-len(rbytes):32], rbytes)
copy(sig[64-len(sbytes):64], sbytes)
log.Println("Else Result : ", verifyECRecover(hash.Bytes(), sig, expectedPubKey))
}
verification := ethcrypto.VerifySignature(expectedPubKey, hash.Bytes(), sig)
Below code method is VerifyECRecover:
func verifyECRecover(hash, sig, expectedPubKey []byte) bool {
for v := 0; v < 2; v++ {
sig[64] = byte(v)
if pubkey, err := ethcrypto.Ecrecover(hash, sig); err == nil {
if bytes.Equal(pubkey, expectedPubKey) {
log.Println("Matched")
return true
}
log.Println("Not Matched")
} else {
log.Println("Error: ", err)
}
}
return false
}
I am not able to get the correct public key, so that I can submit the transaction to ethereum blockchain. Can anyone help me in solving this?