A Solana program that verifies Ethereum signatures using secp256k1 elliptic curve cryptography, enabling cross-chain authentication between Ethereum and Solana blockchains.
- Overview
- Prerequisites
- Cryptographic Theory
- Architecture
- Installation
- Usage
- Testing
- Frontend Application
- Security Considerations
This project implements a cross-chain signature verification system that allows Ethereum signatures to be verified on the Solana blockchain. The system uses the secp256k1 elliptic curve, which is the same curve used by both Bitcoin and Ethereum, enabling seamless cross-chain authentication.
- Ethereum signature verification on Solana
- secp256k1 public key recovery from signatures
- Cross-chain message authentication
- Support for Ethereum's personal message signing format
- Comprehensive test suite with real signature examples
- Rust 1.70.0 or later
- Solana CLI 1.16.0 or later
- Anchor Framework 0.29.0 or later
- Node.js 18.0.0 or later (for testing)
- MetaMask browser extension (for frontend testing)
ECDSA is a cryptographic algorithm used for digital signatures. It provides:
- Authentication: Proves the identity of the signer
- Non-repudiation: Prevents the signer from denying they created the signature
- Integrity: Ensures the message hasn't been tampered with
The secp256k1 curve is defined by the equation:
y² = x³ + 7 (mod p)
where p = 2²⁵⁶ - 2³² - 2⁹ - 2⁸ - 2⁷ - 2⁶ - 2⁴ - 1
Properties:
- 256-bit prime field
- Used by Bitcoin, Ethereum, and many other cryptocurrencies
- Provides approximately 128-bit security level
- Efficient implementation available in most cryptographic libraries
Keccak-256 is a cryptographic hash function that:
- Produces a 256-bit (32-byte) output
- Is the core of the SHA-3 family
- Used by Ethereum for message hashing
- Provides collision resistance and preimage resistance
Ethereum uses a specific format for signing messages:
"\x19Ethereum Signed Message:\n" + length(message) + message
This format prevents replay attacks and ensures signatures are only valid for Ethereum messages.
An ECDSA signature consists of three components:
- r: First 32 bytes of the signature (x-coordinate of a point on the curve)
- s: Second 32 bytes of the signature (y-coordinate of a point on the curve)
- v: Recovery ID (1 byte) - determines which of the two possible y-coordinates to use
Given a message hash and signature (r, s, v), the original public key can be recovered using:
- Calculate the point R on the curve using r and v
- Use the message hash and signature to compute the public key
- Verify the signature is valid for the recovered public key
programs/cross-chain-verify/src/
├── lib.rs # Main program logic
├── instructions/ # Instruction handlers
└── state/ # Account state definitions
- Signature Verification: Implements secp256k1 signature verification
- Public Key Recovery: Recovers Ethereum public keys from signatures
- Message Formatting: Handles Ethereum's personal message format
- Account Management: Stores verification results on-chain
- User signs a message with MetaMask (Ethereum)
- Signature components (r, s, v) are extracted
- Message is formatted according to Ethereum standards
- Solana program verifies the signature using secp256k1
- Public key is recovered and stored on-chain
- Verification result is returned to the user
git clone <repository-url>
cd cross-chain-verify
# Install Rust dependencies
cargo build
# Install Node.js dependencies for testing
yarn install
anchor build
anchor deploy --provider.cluster devnet
import { Program } from "@coral-xyz/anchor"
import { CrossChainVerify } from "./target/types/cross_chain_verify"
// Initialize program
const program = new Program(idl, programId, provider)
// Verify Ethereum signature
const tx = await program.methods
.verifyEthSignature(
message, // String message
signatureR, // [u8; 32] - First 32 bytes of signature
signatureS, // [u8; 32] - Second 32 bytes of signature
recoveryId // u8 - Recovery ID (v - 27)
)
.accounts({
verificationAccount: verificationAccount.publicKey,
user: user.publicKey,
})
.signers([verificationAccount])
.rpc()
// Fetch verification results
const accountData = await program.account.verificationData.fetch(
verificationAccount.publicKey
)
console.log("Message:", accountData.message)
console.log("Is Verified:", accountData.isVerified)
console.log("Signer Public Key:", accountData.signerPubkey)
console.log("Timestamp:", accountData.timestamp)
anchor test
The test suite includes:
- Basic signature verification
- Multiple account verification
- Error handling for invalid signatures
- Public key recovery validation
- Cross-chain signature format testing
The tests use real Ethereum signatures generated from the message "Anchorpoint Assemble" to ensure authenticity and reliability.
A React-based frontend application is available for generating and testing signatures:
Repository: https://github.com/swymbnsl/secp256k1-test-frontend.git
Features:
- MetaMask integration for message signing
- Signature component extraction (r, s, recovery_id)
- Copy-to-clipboard functionality
- Ready-to-use Solana program call generation
- Mobile-responsive design
Usage:
- Connect MetaMask wallet
- Enter message to sign
- Generate signature components
- Copy components for use in Solana program
- Uses industry-standard secp256k1 curve
- Implements proper signature verification
- Validates all signature components
- Handles edge cases and error conditions
- Verifies signatures on-chain
- Stores verification results immutably
- Prevents signature replay attacks
- Validates message format
- Always verify signatures on-chain
- Use proper message formatting
- Validate all input parameters
- Handle errors gracefully
- Implement rate limiting if needed