EIP-4361, JWT, and RSA vs. ECDSA: Building a Secure Web3 Authentication Flow

This article focuses on the complete authentication loop that combines EIP-4361 login, ECDSA-based wallet signature verification, and RSA-based JWT issuance. It addresses the fragility of Web2 password logins, the lack of standardization in Web3 identity, and fragmented authorization across microservices. Keywords: EIP-4361, JWT, ECDSA.

Technical Specifications at a Glance

Parameter Details
Domain Web3 Security / Identity Authentication / Cryptography
Primary Protocols EIP-4361, JWT (RFC 7519)
Core Algorithms RSA, ECC, ECDSA, Keccak-256
Chain and Curve Ethereum, secp256k1
Signature Algorithm Examples RS256, ES256
Typical Dependencies MetaMask, Redis, OpenSSL, JWT libraries
Original Content Popularity Approx. 306 reads, 4 likes, 7 bookmarks on CSDN

EIP-4361 Defines a Standard Login Message for Web3

EIP-4361, also known as Sign-In with Ethereum (SIWE), is built on a simple idea: users prove control of an address by signing with their wallet instead of submitting a password. It shifts authentication away from a platform-controlled database and toward a user-controlled private key.

This standard solves two key problems. First, it standardizes wallet signature prompts and reduces the risk of blind signing. Second, it uses fields such as domain, nonce, chain-id, and issued-at to mitigate phishing and replay attacks.

A Standard SIWE Message Must Include Verifiable Context

A typical login message includes the domain, address, URI, chain ID, nonce, and issuance time. What the backend actually verifies is not whether the user clicked confirm, but whether the address signed a complete, context-bound message.

example.com wants you to sign in with your Ethereum account:
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2

I accept the Terms of Service: https://example.com/tos

URI: https://example.com/login
Version: 1
Chain ID: 1
Nonce: 32891756
Issued At: 2021-09-30T16:25:24Z

This message binds the login action to a specific site, a specific address, a specific time window, and a specific chain environment.

Backend Implementations Must Center on Nonce and Domain Validation

A secure implementation usually starts with the server generating a nonce. The server then stores the nonce together with the address or session in Redis with a short expiration time. Next, the frontend requests a wallet signature and sends both the message and signature back to the backend.

@PostMapping("/api/auth/login")
public TokenResponse login(@RequestBody LoginRequest req) {
    // 1. Parse the SIWE message and extract fields such as domain, nonce, and address
    SiweMessage msg = siweParser.parse(req.getMessage());

    // 2. Validate the domain and nonce to prevent phishing and replay attacks
    nonceService.assertValid(msg.getAddress(), msg.getNonce());
    domainService.assertAllowed(msg.getDomain());

    // 3. Recover the address with ECDSA and compare it with the declared address
    String recovered = ethSignService.recoverAddress(req.getMessage(), req.getSignature());
    if (!recovered.equalsIgnoreCase(msg.getAddress())) {
        throw new SecurityException("Signature address mismatch");
    }

    // 4. Issue a JWT after successful verification
    return jwtService.issueToken(msg.getAddress());
}

This code shows the minimum closed-loop backend flow for Web3 login: validate the message, validate the signature, validate the context, and issue a token.

RSA Remains a Reliable Choice for Server-Side JWT Issuance

RSA is a classic asymmetric cryptosystem whose security relies on the difficulty of factoring large integers. Its typical role here is not wallet login signing, but JWT issuance by the authentication service so downstream services can verify tokens with the public key.

In a microservices architecture, RSA provides a practical advantage: centralized private key ownership and distributed public key verification. The authentication service keeps the private key, while business services only need the public key to validate tokens independently, without calling back to the auth service for every request.

RS256 Fits Centralized Token Issuance and Distributed Verification

# Generate a 2048-bit RSA private key
openssl genrsa -out private.pem 2048

# Export the public key from the private key
openssl rsa -in private.pem -pubout -out public.pem

These commands generate the RSA key pair required for JWT issuance: the private key signs, and the public key verifies.

RSA Trades Off Longer Keys and Heavier Computation

RSA offers maturity, strong compatibility, and a stable ecosystem. Its downside is that it requires longer keys and produces larger signatures at the same security level. In practice, RS256 is common for JWTs, but blockchain account systems do not use RSA.

ECC and ECDSA Form the Mathematical Foundation of Ethereum Account Security

ECC stands for Elliptic Curve Cryptography, and ECDSA is a digital signature algorithm built on elliptic curves. Ethereum accounts are based on the secp256k1 curve, so wallet signature verification is fundamentally an ECDSA verification and address recovery process.

The core advantage of ECC is that it provides stronger efficiency with shorter keys. A common comparison is that 256-bit ECC offers roughly comparable security to 3072-bit RSA, while keeping signatures smaller and computation lighter.

Elliptic Curve Systems Rely on One-Way Scalar Multiplication

A simplified way to understand ECC is this: multiply the private key k by the base point P to obtain the public key Q. Forward computation is easy, but reversing Q back to k is computationally infeasible. That asymmetry is the foundation of the system.

Q = k × P

This equation captures the core of ECC: keep the private key secret, publish the public key, and rely on the practical infeasibility of reverse computation.

Ethereum Signature Verification Relies on Recovering the Address from the Signature

An Ethereum signature usually includes three values: r, s, and v. After receiving the message and signature, the backend can hash the message with Keccak-256, recover the public key using r, s, and v, derive the address, and compare it with the address declared in the message.

from eth_account.messages import encode_defunct
from eth_account import Account

message = "example.com wants you to sign in with your Ethereum account..."
signature = "0x..."  # Signature returned by the user's wallet
expected = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"

# Encode the raw text as an Ethereum-signable message
signable = encode_defunct(text=message)

# Recover the address from the message and signature
recovered = Account.recover_message(signable, signature=signature)

# Compare addresses to confirm that the signer matches the claimed identity
assert recovered.lower() == expected.lower()

This code recovers an Ethereum address from a wallet signature and completes the core verification step of Web3 login.

JWT Converts a One-Time Wallet Login into a Persistent Session Capability

A wallet signature is ideal for proving, “I control this address,” but it is not suitable for triggering wallet interaction on every API request. For that reason, after successful SIWE verification, the backend typically issues a JWT as a session token.

A JWT consists of three parts: Header, Payload, and Signature. The Header declares the algorithm, the Payload stores claims such as the address, expiration time, and permissions, and the Signature is generated with the server’s private key to ensure the token cannot be tampered with.

JWT Structure and Verification Diagram AI Visual Insight: This diagram illustrates the three-part JWT structure and its verification flow in an authentication pipeline. It highlights the layered responsibilities of the Header, Payload, and Signature, as well as the stateless authentication model in which the server signs with a private key and downstream services verify with a public key.

The Recommended Authentication Flow Places SIWE Verification First and JWT Session Handling Second

  1. The frontend requests the server to generate a nonce and an EIP-4361 message.
  2. The user completes personal_sign in the wallet.
  3. The frontend submits the message and signature.
  4. The backend recovers the address and validates the domain, nonce, chain-id, and time window.
  5. After successful authentication, the backend issues an RS256 JWT.
  6. Subsequent business requests carry the JWT, which is verified by the gateway or microservices.
{
  "alg": "RS256",
  "sub": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
  "iat": 1710000000,
  "exp": 1710003600
}

This payload example shows that JWTs often use the on-chain address as the subject identity and include explicit issuance and expiration timestamps.

In Engineering Practice, You Must Clearly Separate the Roles of Common Algorithms

Different Algorithms Solve Different Layers of Security Problems

  • EIP-4361 defines a login message format. It is not an encryption algorithm.
  • ECDSA proves wallet signature ownership and address control.
  • ECC provides the elliptic curve cryptographic foundation behind ECDSA.
  • RSA is commonly used for JWTs, certificates, and software signing.
  • HS256 uses symmetric-key signing. It works well within a single service boundary, but introduces greater risk when secrets must be distributed across services.
  • RS256 uses asymmetric signing and is better suited to centralized authentication and multi-service verification scenarios.

A Quick Fact Checklist Helps You Troubleshoot Faster

  • Ethereum commonly uses Keccak-256 for hashing.
  • Ethereum uses the secp256k1 curve.
  • ETH address generation can be understood as: public key → Keccak-256 → last 20 bytes.
  • “Sign with the private key, verify with the public key” describes digital signatures.
  • “Encrypt with the public key, decrypt with the private key” describes confidentiality, which is not the same as signing.

FAQ

FAQ 1: Why Does Web3 Login Still Need JWT?

Because wallet signatures are good for one-time identity confirmation, but not for high-frequency API access. JWT converts a one-time signature verification result into a short-lived session credential, reduces interaction overhead, and supports unified authorization across gateways and microservices.

FAQ 2: Can EIP-4361 Prevent Replay Attacks on Its Own?

It can reduce the risk, but only if the server correctly validates the nonce, domain, chain-id, issued-at, and expiration-time. If you verify only the signature and ignore the surrounding context, replay attacks are still possible.

FAQ 3: How Should You Choose Between RS256 and ES256?

If you need compatibility with traditional authentication infrastructure, certificate systems, and public-key distribution in microservices, RS256 is the safer default. If you want shorter signatures and better performance, ES256 is worth considering, but you should evaluate the maturity of your language ecosystem and operational tooling first.

Core Summary: This article systematically reconstructs how EIP-4361 (SIWE), JWT, RSA, ECC, and ECDSA work together. It explains the complete flow of wallet-based login, backend signature verification, JWT issuance, and microservice authorization, and it provides key fields, algorithm differences, implementation steps, and answers to common developer questions.