viem-goviem-go

Signature Utilities

Utilities for signing, verifying, and recovering Ethereum signatures

Utilities for signing, verifying, and recovering Ethereum signatures.

recoverMessageAddress

Recover the address that signed a message:

1import "github.com/ChefBingbong/viem-go/utils/signature"
2
3address, err := signature.RecoverMessageAddress(
4 "Hello, Ethereum!",
5 "0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c",
6)
7if err != nil {
8 log.Fatal(err)
9}
10
11fmt.Printf("Signer: %s\n", address.Hex())

recoverAddress

Recover address from a hash and signature:

1// For raw hash recovery (not message)
2address, err := signature.RecoverAddress(hash, sig)

recoverPublicKey

Recover the public key from a signature:

pubKey, err := signature.RecoverPublicKey(hash, sig)
fmt.Printf("Public Key: 0x%x\n", pubKey)

recoverTypedDataAddress

Recover address from EIP-712 typed data signature:

1address, err := signature.RecoverTypedDataAddress(typedData, sig)

verifyMessage

Verify a message signature matches an address:

1valid, err := signature.VerifyMessage(
2 expectedAddress,
3 "Hello, Ethereum!",
4 sig,
5)
6if err != nil {
7 log.Fatal(err)
8}
9
10fmt.Printf("Valid: %v\n", valid)

verifyTypedData

Verify an EIP-712 typed data signature:

1valid, err := signature.VerifyTypedData(
2 expectedAddress,
3 typedData,
4 sig,
5)

parseSignature

Parse a hex signature into its components:

1sig, err := signature.ParseSignature(
2 "0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c",
3)
4
5fmt.Printf("R: 0x%x\n", sig.R)
6fmt.Printf("S: 0x%x\n", sig.S)
7fmt.Printf("V: %d\n", sig.V)

serializeSignature

Combine signature components into a hex string:

1hexSig := signature.SerializeSignature(signature.Signature{
2 R: r,
3 S: s,
4 V: v,
5})
6fmt.Printf("Signature: %s\n", hexSig)

Compact Signatures (EIP-2098)

Convert to/from compact signature format:

// To compact (64 bytes)
compact := signature.SignatureToCompactSignature(sig)

// From compact
sig := signature.CompactSignatureToSignature(compact)

ERC-6492 Signatures

For smart contract wallet signatures:

// Check if signature is ERC-6492 format
isErc6492 := signature.IsErc6492Signature(sig)

// Parse ERC-6492 signature
parsed, err := signature.ParseErc6492Signature(sig)
// Returns: factoryAddress, factoryData, originalSig

// Create ERC-6492 signature
erc6492Sig := signature.SerializeErc6492Signature(
    factoryAddress,
    factoryData,
    originalSig,
)

Common Use Cases

Verify User Signed Terms

func verifyTermsAcceptance(userAddress common.Address, sig string) error {
    terms := "I accept the Terms of Service v1.0"
    
    valid, err := signature.VerifyMessage(userAddress, terms, sig)
    if err != nil {
        return err
    }
    if !valid {
        return errors.New("invalid signature")
    }
    
    return nil
}

Off-chain Order Signing

// Define order type
orderTypedData := signature.TypedDataDefinition{
    Domain: signature.TypedDataDomain{
        Name:              "My DEX",
        Version:           "1",
        ChainId:           big.NewInt(1),
        VerifyingContract: dexContract,
    },
    Types: map[string][]signature.TypedDataField{
        "Order": {
            {Name: "maker", Type: "address"},
            {Name: "tokenIn", Type: "address"},
            {Name: "tokenOut", Type: "address"},
            {Name: "amountIn", Type: "uint256"},
            {Name: "minAmountOut", Type: "uint256"},
            {Name: "deadline", Type: "uint256"},
        },
    },
    PrimaryType: "Order",
    Message: orderData,
}

// Sign order
sig, _ := account.SignTypedData(orderTypedData)

// Later, verify order
valid, _ := signature.VerifyTypedData(maker, orderTypedData, sig)