Skip to Content

EC-VRF (Elliptic Curve Verifiable Random Function)

The EC-VRF mode uses the ECVRF-ED25519-SHA512-ELL2 suite defined in RFC 9381 . Unlike Classic RNG, it produces a cryptographic proof with every bet, allowing immediate per-bet verification without waiting for seed rotation.

How It Works

1. Key Generation

The server generates an Ed25519 key pair:

  • Private Key — 32 bytes, kept secret on the server
  • Public Key — 32 bytes, shown to the player

The public key serves as the commitment — it is mathematically linked to the private key but cannot be used to derive it.

Private Key: (hidden from player) Public Key: 3a7f1b... (shown to player)

2. VRF Input (Alpha)

For each bet, the VRF input (called alpha) is constructed from the player’s client seed and the nonce:

alpha = UTF-8("clientSeed:nonce")

For example, with client seed my-seed and nonce 42:

alpha = UTF-8("my-seed:42")

3. VRF Prove

The server uses its private key and the alpha to produce two outputs:

  • VRF Proof (80 bytes) — A cryptographic proof that the output was generated correctly
  • VRF Output (64 bytes) — A SHA-512 hash used as the random value
(proof, output) = ECVRF_prove(privateKey, alpha)

The proof consists of three components:

  • Gamma (32 bytes) — A curve point derived from the private key and alpha
  • c (16 bytes) — A Fiat-Shamir challenge
  • s (32 bytes) — A scalar response

The output is computed as:

output = SHA-512(suite_string || 0x03 || point_to_string(cofactor × Gamma) || 0x00)

4. Random Number Generation

The 64-byte VRF output is used as the source of randomness:

  • Bytes 0–31: First round of random bytes
  • Bytes 32–63: Second round of random bytes
  • Beyond 64 bytes: HMAC-SHA256 expansion keyed by the VRF output
Round 0: vrfOutput[0..31] Round 1: vrfOutput[32..63] Round 2+: HMAC-SHA256(key=vrfOutput, message="clientSeed:nonce:round")

The bytes are converted to floats in [0, 1) using the same method as Classic RNG:

float = byte[0] / 256 + byte[1] / 256² + byte[2] / 256³ + byte[3] / 256⁴

5. Verification (Immediate, Per-Bet)

After every bet, the player receives the VRF Proof and VRF Output. They can immediately verify:

  1. Run ECVRF_verify(publicKey, alpha, proof) → returns computed output or null
  2. Confirm the computed output matches the VRF Output provided with the bet
  3. If verification passes, the outcome is mathematically proven to be correct
alpha = UTF-8("clientSeed:nonce") computedOutput = ECVRF_verify(publicKey, alpha, proof) // Verification passes if: // - computedOutput is not null (proof is valid) // - computedOutput === vrfOutput (output matches)

Verification Steps

To verify a bet:

  1. Gather the data from the bet receipt:

    • VRF Public Key (64 hex chars)
    • Client Seed
    • Nonce
    • VRF Proof (160 hex chars)
    • VRF Output (128 hex chars)
  2. Build alpha: UTF-8("clientSeed:nonce")

  3. Run verification: ECVRF_verify(publicKey, alpha, proof)

  4. Compare: The returned output must match the VRF Output from the bet

You can use the verification tool at maktub.bet/ecvrf  to verify bets directly in your browser — no data is sent to any server.

Player-Visible Data

FieldWhen VisibleDescription
VRF Public KeyAlwaysServer’s Ed25519 public key (64 hex chars)
Client SeedAlwaysPlayer-chosen input
NonceAfter betBet counter for the current seed pair
VRF ProofAfter bet80-byte cryptographic proof (160 hex chars)
VRF OutputAfter bet64-byte SHA-512 hash (128 hex chars)
Next VRF Public KeyAlwaysPublic key for the next seed pair

Seed Rotation

When the player rotates their seeds:

  1. The current VRF Public Key remains visible (it was never hidden)
  2. The Next VRF Public Key becomes the active key
  3. A new Next VRF Public Key is generated
  4. The player can set a new client seed
  5. The nonce resets to 0

Since EC-VRF provides per-bet proofs, seed rotation is not required for verification — it simply refreshes the key pair.

Security Properties

  • Uniqueness: For any given public key and alpha, only one valid output exists
  • Unpredictable: Without the private key, the output cannot be predicted
  • Deterministic: The same private key and alpha always produce the same output and proof
  • Verifiable: Anyone with the public key can verify the proof without knowing the private key
  • Non-interactive: Verification requires only the public key, alpha, and proof — no server interaction needed
  • Per-bet proofs: Every single bet can be independently verified immediately
  • Player influence: The client seed ensures the player contributes to the randomness

Technical Details

Curve Parameters

ParameterValue
CurveEd25519 (Twisted Edwards)
HashSHA-512
SuiteECVRF-ED25519-SHA512-ELL2
Suite byte0x04
Cofactor8
Key size32 bytes (256 bits)
Proof size80 bytes (Gamma 32 + c 16 + s 32)
Output size64 bytes (SHA-512)

Hash-to-Curve

The implementation uses the try-and-increment method (RFC 9381 Section 5.4.1.1):

  1. Hash suite_string || 0x01 || publicKey || alpha || counter || 0x00 with SHA-512
  2. Take the first 32 bytes and attempt to decode as an Ed25519 point
  3. Multiply by cofactor (8) to ensure the point is in the prime-order subgroup
  4. Increment counter and retry if decoding fails (up to 256 attempts)

Challenge Generation

The Fiat-Shamir challenge c is computed as:

hash = SHA-512(suite_string || 0x02 || H || Gamma || U || V || 0x00) c = first 16 bytes of hash (little-endian integer)

Verify Algorithm

1. Decode proof: Gamma (32 bytes) + c (16 bytes) + s (32 bytes) 2. Y = decode(publicKey) as Ed25519 point 3. H = hash_to_curve(publicKey, alpha) 4. U = s × B - c × Y 5. V = s × H - c × Gamma 6. c' = challenge_generation(publicKey, H, Gamma, U, V) 7. If c == c': output = SHA-512(0x04 || 0x03 || 8 × Gamma || 0x00) 8. Else: verification failed

Advantages Over Classic RNG

AspectClassic RNGEC-VRF
When can players verify?After seed rotationImmediately, per bet
Proof per betNoneYes (VRF Proof)
Server secret exposureServer seed revealed on rotationPrivate key never revealed
Mathematical guaranteeHash commitmentFormal VRF security proof
Regulatory strengthIndustry standardRFC-standardized
Last updated on