Specification

The full SIWS message format specification, including field definitions, grammar, verification process, and security considerations.

Abstract

This specification defines a standardized message format and Ed25519 verification process that lets Solana wallet owners authenticate with off-chain services without on-chain transactions.

Motivation

Solana wallets are widely deployed, yet no standard exists for using them as authentication credentials. Ad-hoc implementations lead to:

  • Inconsistent user experiences
  • Security vulnerabilities
  • Lack of interoperability

This specification addresses these issues with a secure, human-readable message format and verification process.

Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

Additional terms:

  • Wallet: A cryptographic keypair capable of signing messages using Ed25519
  • Relying Party: The service requesting authentication
  • Message: The human-readable string presented to the user for signing

Message Format

A SIWS message MUST conform to the following structure:

${domain} wants you to sign in with your Solana account:
${address}
 
${statement}
 
URI: ${uri}
Version: ${version}
Nonce: ${nonce}
Issued At: ${issuedAt}
Expiration Time: ${expirationTime}
Not Before: ${notBefore}
Request ID: ${requestId}
Cluster: ${cluster}
Resources:
- ${resources[0]}
- ${resources[1]}
- ...

Required Fields

FieldDescriptionFormat
domainRFC 3986 authority requesting authenticationauthority per RFC 3986
addressSolana wallet addressBase58-encoded Ed25519 public key
uriRFC 3986 URI identifying the authentication targetURI per RFC 3986
versionSIWS specification version1
nonceRandomized token for replay protectionAlphanumeric, >=8 characters
issuedAtMessage creation timestampISO 8601 datetime
clusterSolana network identifiermainnet-beta | devnet | testnet

Optional Fields

FieldDescriptionFormat
statementHuman-readable purpose descriptionUTF-8 string, no \n
expirationTimeMessage expiration timestampISO 8601 datetime
notBeforeMessage validity start timestampISO 8601 datetime
requestIdApplication-specific request identifierString
resourcesResources being authorizedArray of RFC 3986 URIs

Field Definitions

domain

RFC 3986 authority matching the requesting origin. MUST NOT include a scheme or path. Relying parties MUST reject mismatched domains.

address

Base58-encoded Ed25519 public key (32 bytes, 43-44 characters). The signature MUST be verified against this key.

uri

Valid RFC 3986 URI. SHOULD match the endpoint receiving the authentication request.

version

MUST be 1 for this specification.

nonce

At least 8 alphanumeric characters from a CSPRNG. Relying parties MUST:

  1. Generate a unique nonce per authentication attempt
  2. Store nonces server-side with an expiration time
  3. Reject unknown, expired, or previously used nonces
  4. Invalidate nonces after successful verification

Recommendation: Use >=16 bytes of randomness, Base58 or hex encoded.

issuedAt

ISO 8601 datetime in UTC (Z suffix).

statement

OPTIONAL. MUST NOT contain newline characters. SHOULD describe the authentication purpose.

expirationTime

OPTIONAL. Relying parties MUST reject messages past this time.

Recommendation: 5-15 minutes from issuedAt.

notBefore

OPTIONAL. Relying parties MUST reject messages before this time.

cluster

REQUIRED. One of mainnet-beta, devnet, testnet. Relying parties MUST validate to prevent cross-cluster replay.

resources

OPTIONAL. Each resource MUST be a valid RFC 3986 URI.

Signature Verification

Solana uses Ed25519 for message signing. Verification MUST proceed as follows:

  1. Encode the message string as UTF-8 bytes
  2. Decode the signature from Base58 (64 bytes)
  3. Decode the public key from Base58 (32 bytes)
  4. Verify using Ed25519: ed25519.verify(signature, message, publicKey)

Message Grammar

The message format is defined using ABNF (RFC 5234):

siws-message    = domain-line LF address-line LF LF
                  [ statement-line LF LF ]
                  field-lines
 
domain-line     = domain " wants you to sign in with your Solana account:"
address-line    = address
statement-line  = statement
 
field-lines     = uri-field LF version-field LF nonce-field LF
                  issued-at-field LF
                  [ expiration-field LF ]
                  [ not-before-field LF ]
                  [ request-id-field LF ]
                  cluster-field LF
                  [ resources-field ]
 
uri-field       = "URI: " uri
version-field   = "Version: " version
nonce-field     = "Nonce: " nonce
issued-at-field = "Issued At: " iso8601-datetime
expiration-field = "Expiration Time: " iso8601-datetime
not-before-field = "Not Before: " iso8601-datetime
request-id-field = "Request ID: " request-id
cluster-field   = "Cluster: " cluster
resources-field = "Resources:" LF resource-list
resource-list   = 1*( "- " uri LF )
 
domain          = authority                    ; RFC 3986
address         = 43*44BASE58CHAR
uri             = URI                          ; RFC 3986
version         = "1"
nonce           = 8*ALPHANUM
statement       = 1*( %x20-7E )                ; printable ASCII, no newlines
request-id      = 1*( %x20-7E )
cluster         = "mainnet-beta" / "devnet" / "testnet"
iso8601-datetime = ; ISO 8601 datetime with Z suffix
 
ALPHANUM        = ALPHA / DIGIT
BASE58CHAR      = %x31-39 / %x41-48 / %x4A-4E / %x50-5A / %x61-6B / %x6D-7A
LF              = %x0A

Security Considerations

Replay Attacks

Captured signatures reused for unauthorized authentication. Single-use nonces MUST be enforced with expiration (RECOMMENDED: 5 minutes). expirationTime provides defense in depth.

Cross-Site Request Forgery

Signatures obtained from one site used on another. domain MUST be verified server-side and uri binds authentication to a specific endpoint. Relying parties MUST reject domain/URI mismatches.

Phishing

Users deceived into signing messages for malicious sites. Wallets SHOULD display the complete message before signing and warn on unfamiliar domains. domain and statement help users identify the requesting party.

Nonce Compromise

Leaked or predicted nonces enable replay attacks. Generate nonces using CSPRNG, store server-side only, bind to session or client identifiers, and enforce expiration.

Test Vectors

Vector 1: Minimal Message

example.com wants you to sign in with your Solana account:
7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU

Sign in to Example

URI: https://example.com/auth
Version: 1
Nonce: k8sj2n4b
Issued At: 2024-01-15T12:00:00Z
Cluster: mainnet-beta

Vector 2: Complete Message

app.example.com wants you to sign in with your Solana account:
7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU

Access your dashboard and manage settings.

URI: https://app.example.com/api/auth
Version: 1
Nonce: f7k2m9p4x1
Issued At: 2024-01-15T12:00:00.000Z
Expiration Time: 2024-01-15T12:10:00.000Z
Not Before: 2024-01-15T12:00:00.000Z
Request ID: req_abc123
Cluster: mainnet-beta
Resources:
- https://app.example.com/api/profile
- https://app.example.com/api/settings

References