Skip to content

mowind/web3signer-go

Repository files navigation

web3signer-go

πŸš€ A production-ready Go implementation of Web3 signer with MPC-KMS signing support

License: GPL v3 CI Go Report Card GoDoc

Overview

web3signer-go is a lightweight, secure signing service inspired by Consensys/web3signer, specifically focusing on MPC-KMS (Multi-Party Computation Key Management Service) signing.

It provides a transparent HTTP JSON-RPC proxy that:

  • βœ… Signs transactions using secure MPC-KMS (key never exposed)
  • βœ… Forwards all other requests to downstream Ethereum nodes
  • βœ… Standard Ethereum JSON-RPC - drop-in replacement for direct node access

Key Differentiators

Feature web3signer-go Original web3signer
Signing Methods MPC-KMS only File, Vault, AWS KMS, YubiHSM, etc.
Architecture Simple, focused Complex, extensible
Language Go Java
Deployment Single binary, minimal deps JVM, heavier footprint
Use Case Production MPC-KMS deployments Multi-backend signing scenarios

Features

  • βœ… MPC-KMS Integration - Secure multi-party computation key management
  • βœ… JSON-RPC Server - HTTP server with JSON-RPC 2.0 support
  • βœ… Transaction Signing - Supports eth_sign, eth_signTransaction, eth_sendTransaction
  • βœ… Smart Contract Support - EIP-1559 and legacy transaction types
  • βœ… Downstream Forwarding - Transparent proxy to Ethereum nodes
  • βœ… Health Checks - /health and /ready endpoints for monitoring
  • βœ… CORS Support - Configurable CORS headers for web applications
  • βœ… Configuration Management - CLI flags, config files, and environment variables
  • βœ… Structured Logging - Logrus-based logging with configurable levels
  • βœ… Comprehensive Testing - Unit tests and integration tests with high coverage
  • βœ… Docker Support - Multi-stage Dockerfile for production deployments
  • βœ… CI/CD Pipeline - Automated testing, linting, and security scanning
  • βœ… TLS Support - HTTPS/TLS for secure communication
  • βœ… Authentication - JWT Bearer token and API-Key authentication
  • βœ… Security Hardening - Constant-time comparisons, input validation, rate limiting

Quick Start

Prerequisites

  • Go 1.25 or later
  • MPC-KMS service endpoint
  • Downstream JSON-RPC service (e.g., Ethereum node)

Installation

From Source

# Clone the repository
git clone https://github.com/mowind/web3signer-go.git
cd web3signer-go

# Build the binary
make build

# Or install directly
go install ./cmd/web3signer/

Using Docker

# Build the Docker image
docker build -t web3signer:latest .

# Run the container
docker run -d \
  --name web3signer \
  -p 9000:9000 \
  -e WEB3SIGNER_HTTP_HOST=0.0.0.0 \
  -e WEB3SIGNER_HTTP_PORT=9000 \
  -e WEB3SIGNER_KMS_ENDPOINT=http://kms.example.com:8080 \
  -e WEB3SIGNER_KMS_ACCESS_KEY_ID=YOUR_ACCESS_KEY \
  -e WEB3SIGNER_KMS_SECRET_KEY=YOUR_SECRET_KEY \
  -e WEB3SIGNER_KMS_KEY_ID=YOUR_KEY_ID \
  -e WEB3SIGNER_DOWNSTREAM_HTTP_HOST=http://localhost \
  -e WEB3SIGNER_DOWNSTREAM_HTTP_PORT=8545 \
  web3signer:latest

For detailed deployment instructions, see DEPLOYMENT.md.

Basic Usage

# Run with command-line flags
./build/web3signer \
  --http-host localhost \
  --http-port 9000 \
  --kms-endpoint http://kms.example.com:8080 \
  --kms-access-key-id YOUR_ACCESS_KEY \
  --kms-secret-key YOUR_SECRET_KEY \
  --kms-key-id YOUR_KEY_ID \
  --downstream-http-host http://localhost \
  --downstream-http-port 8545 \
  --downstream-http-path / \
  --log-level info

Configuration File

Create a configuration file ~/.web3signer.yaml:

http:
  host: localhost
  port: 9000
  max-request-size-mb: 10
  # allowed-origins: "https://example.com,https://api.example.com"  # Default: http://localhost:*,http://127.0.0.1:*
  tls-enabled: false
  # tls-cert-file: /path/to/cert.pem
  # tls-key-file: /path/to/key.pem

auth:
  enabled: true
  secret: your_shared_secret_here

kms:
  endpoint: http://kms.example.com:8080
  access-key-id: YOUR_ACCESS_KEY
  secret-key: YOUR_SECRET_KEY
  key-id: YOUR_KEY_ID

downstream:
  http-host: http://localhost
  http-port: 8545
  http-path: /

log:
  level: info
  format: json

Then run with:

./build/web3signer --config ~/.web3signer.yaml

JSON-RPC Methods

Supported Signing Methods

  • eth_sign - Sign arbitrary data
  • eth_signTransaction - Sign a transaction
  • eth_sendTransaction - Sign and send a transaction

Forwarded Methods

All other JSON-RPC methods are forwarded to the configured downstream service, including:

  • eth_getBalance
  • eth_getTransactionCount
  • eth_call
  • eth_getBlockByNumber
  • net_version
  • web3_clientVersion
  • And more...

Project Structure

web3signer-go/
β”œβ”€β”€ cmd/                    # Application entry points
β”‚   β”œβ”€β”€ web3signer/         # Main application
β”‚   └── test-kms/           # KMS test utilities
β”œβ”€β”€ internal/               # Private application code
β”‚   β”œβ”€β”€ config/             # Configuration types and validation
β”‚   β”œβ”€β”€ kms/                # MPC-KMS HTTP client
β”‚   β”œβ”€β”€ server/             # HTTP server with Gin
β”‚   β”œβ”€β”€ router/             # JSON-RPC routing and handlers
β”‚   β”œβ”€β”€ jsonrpc/            # JSON-RPC types and utilities
β”‚   β”œβ”€β”€ downstream/         # Downstream service HTTP client
β”‚   β”œβ”€β”€ signer/             # Signing logic (implements ethgo.Key)
β”‚   └── errors/             # Error types and handling
β”œβ”€β”€ test/                   # Integration tests and mocks
β”œβ”€β”€ scripts/                # Build and deployment scripts
β”œβ”€β”€ .github/                # GitHub workflows and CI/CD
β”œβ”€β”€ Dockerfile              # Multi-stage Docker build
β”œβ”€β”€ Makefile                # Build and test commands
β”œβ”€β”€ DEPLOYMENT.md           # Detailed deployment guide
β”œβ”€β”€ CLAUDE.md               # AI-assisted development context
└── README.md               # This file

Development

Prerequisites

  • Go 1.25 or later
  • Docker (optional, for containerized deployment)
  • golangci-lint (install with make install-tools)

Build Commands

# Build all binaries
make build

# Build specific binary
go build -o web3signer ./cmd/web3signer

# Clean build artifacts
make clean

# Check development environment
make env

Testing

# Run all tests
make test

# Run tests with coverage
make test-coverage

# Generate HTML coverage report
make coverage

# Run integration tests
make integration-test

# Run tests for specific package
go test ./internal/kms/...

# Run tests with verbose output
go test -v ./...

# Run tests with race detector
go test -race ./...

Code Quality

# Format code
make fmt

# Run vet
make vet

# Run linter
make lint

# Tidy dependencies
make tidy

# Run all checks (test + lint)
make check

# Install development tools
make install-tools

Using the Test KMS Tool

The project includes a test KMS client for development:

# Build the test-kms tool
make build

# Test a signing operation
./build/test-kms \
  --endpoint http://localhost:8080 \
  --access-key-id YOUR_ACCESS_KEY \
  --secret-key YOUR_SECRET_KEY \
  --key-id YOUR_KEY_ID

Configuration Reference

HTTP Server Configuration

  • --http-host - Server host (default: localhost)
  • --http-port - Server port (default: 9000)
  • --http-max-request-size - Maximum request body size in MB (default: 10)
  • --http-allowed-origins - CORS allowed origins (default: http://localhost:*, http://127.0.0.1:*; use * to allow all origins)
  • --tls-enabled - Enable TLS/HTTPS (default: false)
  • --tls-cert-file - Path to TLS certificate file (required if TLS enabled)
  • --tls-key-file - Path to TLS private key file (required if TLS enabled)
  • --tls-auto-redirect - Auto redirect HTTP to HTTPS (default: false)

Authentication Configuration

  • --auth-enabled - Enable authentication middleware (default: false)
  • --auth-secret - Shared secret for Bearer tokens and API-Keys (required if auth enabled)

MPC-KMS Configuration

  • --kms-endpoint - MPC-KMS endpoint URL (required)
  • --kms-access-key-id - Access key ID (required)
  • --kms-secret-key - Secret key (required)
  • --kms-key-id - Key ID for signing (required)
  • --kms-address - Ethereum address associated with the key (required)

Downstream Service Configuration

  • --downstream-http-host - Downstream service host (default: http://localhost)
  • --downstream-http-port - Downstream service port (default: 8545)
  • --downstream-http-path - Downstream service path (default: /)

Logging Configuration

  • --log-level - Log level: debug, info, warn, error, fatal (default: info)

Environment Variables

All configuration options can be set via environment variables using the WEB3SIGNER_ prefix:

export WEB3SIGNER_HTTP_HOST=0.0.0.0
export WEB3SIGNER_HTTP_PORT=9000
export WEB3SIGNER_HTTP_MAX_REQUEST_SIZE_MB=10
export WEB3SIGNER_HTTP_ALLOWED_ORIGINS="https://example.com,https://api.example.com"
export WEB3SIGNER_TLS_ENABLED=false
export WEB3SIGNER_AUTH_ENABLED=true
export WEB3SIGNER_AUTH_SECRET=your_shared_secret
export WEB3SIGNER_KMS_ENDPOINT=http://kms.example.com:8080
export WEB3SIGNER_KMS_ACCESS_KEY_ID=your_access_key
export WEB3SIGNER_KMS_SECRET_KEY=your_secret_key
export WEB3SIGNER_KMS_KEY_ID=your_key_id

API Documentation

Health Endpoints

Endpoint Method Description
/health GET Service health check
/ready GET Service readiness check

Note: These endpoints bypass authentication (if enabled) for monitoring purposes.

Response Example:

{
  "status": "healthy",
  "time": "2026-01-20T08:00:00Z"
}

JSON-RPC Endpoint

Endpoint Method Description
/ POST JSON-RPC 2.0 endpoint

Authentication

When authentication is enabled (--auth-enabled=true), requests must include one of the following:

Option 1: Bearer Token

curl -X POST https://localhost:9000/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your_shared_secret" \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_accounts"}'

Option 2: API-Key Header

curl -X POST https://localhost:9000/ \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your_shared_secret" \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_accounts"}'

Security Notes:

  • Both methods use the same shared secret configured via --auth-secret
  • Constant-time comparison prevents timing attacks
  • Generic error messages prevent information leakage
  • Whitelisted paths (/health, /ready) bypass authentication

Supported Signing Methods

Method Description
eth_sign Sign arbitrary data with the configured key
eth_signTransaction Sign a transaction (returns signed transaction)
eth_sendTransaction Sign and send a transaction to the network
eth_accounts Returns the configured Ethereum address

Example Requests

Sign a Transaction

curl -X POST http://localhost:9000/ \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_signTransaction",
    "params": [{
      "from": "0xYourAddress",
      "to": "0xRecipientAddress",
      "gas": "0x5208",
      "gasPrice": "0x4a817c800",
      "nonce": "0x0",
      "value": "0xde0b6b3a7640000",
      "chainId": "0x1"
    }]
  }'

Send a Transaction

curl -X POST http://localhost:9000/ \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "eth_sendTransaction",
    "params": [{
      "from": "0xYourAddress",
      "to": "0xRecipientAddress",
      "gas": "0x5208",
      "maxFeePerGas": "0x4a817c800",
      "maxPriorityFeePerGas": "0x4a817c800",
      "nonce": "0x1",
      "value": "0xde0b6b3a7640000",
      "chainId": "0x1"
    }]
  }'

Contributing

We welcome contributions! Please see our development guidelines:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feat/amazing-feature)
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all checks pass (make check)
  6. Commit with Conventional Commits
  7. Push and create a pull request

Development Workflow

# 1. Fork and clone
git clone https://github.com/YOUR_USERNAME/web3signer-go.git
cd web3signer-go

# 2. Create feature branch
git checkout -b feat/amazing-feature

# 3. Make changes and test
make test
make lint

# 4. Commit your changes
git add .
git commit -m "feat(module): add amazing feature"

# 5. Push and create PR
git push origin feat/amazing-feature

Code Style Guidelines

  • Follow standard Go conventions and Effective Go
  • Run make fmt before committing
  • Ensure make lint passes without errors
  • Maintain test coverage for all changes
  • Write clear, self-documenting code

Commit Message Format

We follow Conventional Commits:

feat(kms): add support for multiple key IDs
fix(signer): correct EIP-1559 transaction calculation
docs(readme): update deployment instructions
test(router): add integration test for batch requests
ci(docker): optimize multi-stage build

Roadmap

In Progress

  • Multi-key support (currently single key-id)
  • Asynchronous signing approval workflow (MPC-KMS task polling)

Planned

  • Prometheus metrics endpoint
  • Kubernetes deployment manifests
  • Performance benchmarking
  • Webhook notifications for signing events
  • Enhanced logging and tracing support
  • Rate limiting and request throttling

Documentation

  • πŸ“– CLAUDE.md - AI-assisted development context and architecture guide
  • πŸ“¦ DEPLOYMENT.md - Detailed deployment guide with Docker and production configurations
  • πŸ”§ API Documentation - JSON-RPC endpoints and examples

Support

  • πŸ› Bug Reports: GitHub Issues
  • πŸ’‘ Feature Requests: GitHub Discussions
  • πŸ“§ Security Issues: Please report security vulnerabilities privately via GitHub's security advisory features

License

This project is licensed under the GNU General Public License v3.0 (GPLv3). See the LICENSE file for details.

Acknowledgments


Made with ❀️ by the web3signer-go team

About

A Go implementation of web3signer with MPC-KMS (Multi-Party Computation - Key Management Service) signing support.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages