Skip to main content
added 39 characters in body
Source Link
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
}

    sig := make([]byte, 65)

    denTwo := big.NewInt(2)
    rightS := big.NewInt(0)
    curve := ellipticbtcec.P256S256()

    /*
        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)
import (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
}

    sig := make([]byte, 65)

    denTwo := big.NewInt(2)
    rightS := big.NewInt(0)
    curve := elliptic.P256()

    /*
        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)
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
}

    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)
Source Link

Recover public key from sign generated by AWS Cloud HSM - Golang

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 (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 := elliptic.P256()

    /*
        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?