Skip to content

signinwithethereum/siwe-go

Repository files navigation

Sign in with Ethereum (Go)

Pure-Go implementation of EIP-4361: Sign in with Ethereum.

This package is maintained by the Ethereum Identity Foundation alongside the canonical TypeScript, Python, and Rust libraries. All implementations share the same test vectors, ensuring byte-for-byte parity across languages.

Install

go get github.com/signinwithethereum/siwe-go

Usage

Parsing a message

m, err := siwe.ParseMessage(messageStr)
if err != nil {
    // parse error (structured *siwe.Error)
}

Any non-fatal issues are surfaced via m.Warnings — for example, parsing an address that is not EIP-55 checksummed emits a warning but still succeeds.

Constructing a message

m, err := siwe.InitMessage(
    "example.com",                             // domain
    "0x71C7656EC7ab88b098defB751B7401B5f6d8976F", // address
    "https://example.com",                     // uri
    siwe.GenerateNonce(),                      // nonce
    map[string]interface{}{
        "statement":      "Example statement for SIWE",
        "chainId":        1,
        "expirationTime": time.Now().Add(24 * time.Hour),
        "requestId":      "req-1234",
        "resources":      []string{"https://example.com/resources/1"},
    },
)

Serialize for signing with m.String(). EIP-191 pre-hash is available via m.EIP191Hash() if you want to sign directly.

Verifying

VerifyEIP191 returns the recovered public key for a valid EOA signature:

pub, err := m.VerifyEIP191(signatureHex)

VerifyWith performs full verification including time, domain, nonce, URI, chain-id, and request-id bindings, plus optional contract-wallet fallback. It fails closed: Domain, Nonce, URI, and ChainID are all required and must match the message exactly.

res, err := m.VerifyWith(ctx, signature, siwe.VerifyParams{
    Domain:  &domain,
    Nonce:   &nonce,
    URI:     &uri,
    ChainID: &chainID,
}, siwe.VerifyOptions{})

Smart-contract wallet signatures (EIP-1271 / EIP-6492)

Wire any go-ethereum–compatible caller (*ethclient.Client implements the EthCaller interface) into VerifyOptions.ContractVerifier:

import "github.com/ethereum/go-ethereum/ethclient"

cl, _ := ethclient.Dial("https://mainnet.infura.io/v3/...")
verifier := siwe.NewEthCallerVerifier(cl)

res, err := m.VerifyWith(ctx, signature, siwe.VerifyParams{
    Domain:  &domain,
    Nonce:   &nonce,
    URI:     &uri,
    ChainID: &chainID,
}, siwe.VerifyOptions{
    ContractVerifier: verifier,
})

EOA recovery is attempted first; if it fails, the verifier is consulted via isValidSignature(bytes32,bytes) per EIP-1271. Signatures carrying the EIP-6492 magic suffix are handed to the universal off-chain validator bytecode via eth_call, which covers counterfactual (undeployed) wallets as well as already-deployed ones.

Note: this is verification only. EIP-6492 allows a verifier to optionally submit the factory transaction after a successful check to finalize on-chain deployment ("side-effectful" verification). This library does not do that — if you need the wallet actually deployed, submit the factory call yourself.

Time constraints

ok, err := m.ValidNow()        // current time
ok, err  = m.ValidAt(when)     // specific point

Signing from Go

hash := m.EIP191Hash()
sig, err := crypto.Sign(hash.Bytes(), privateKey)
if err != nil { /* ... */ }
sig[64] += 27 // normalize recovery byte for Ethereum wallets
hexSig := hexutil.Encode(sig)

Error handling

All errors returned by this package are *siwe.Error with a machine-readable Type field corresponding to the SiweErrorType codes used by the canonical TypeScript library. Match with errors.As:

var e *siwe.Error
if errors.As(err, &e) {
    switch e.Type {
    case siwe.ErrExpiredMessage:
    case siwe.ErrNonceMismatch:
    // ...
    }
}

See also

License

Dual-licensed under MIT and Apache-2.0.

About

A Go implementation of EIP-4361 Sign in with Ethereum verification

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Contributors

Languages