Skip to main content

Basic Concepts

Understanding the fundamentals of VRFs and cryptographic proofs.

What is a VRF?

A Verifiable Random Function (VRF) is a cryptographic primitive that produces:

  1. A pseudo-random output - Deterministic but unpredictable without the secret key
  2. A proof - Allows anyone to verify the output was correctly computed
VRF(secret_key, input) → (output, proof)

Key Properties

PropertyDescription
DeterministicSame input + key always produces same output
UnpredictableCannot guess output without the secret key
VerifiableAnyone can verify the output using the public key
UniqueOnly one valid output exists for each input

VRF Components

Secret Key

A 32-byte random value known only to the prover:

import secrets
secret_key = secrets.token_bytes(32)

Public Key

Derived from the secret key, can be shared publicly:

from dot_ring import Bandersnatch, IETF_VRF

public_key = IETF_VRF[Bandersnatch].get_public_key(secret_key)

Input (Alpha)

The data being signed. Can be any bytes:

alpha = b'block-123-slot-456'

Additional Data

Optional context data bound to the proof (VRF-AD):

additional_data = b'my-application-context'

Proof

The cryptographic proof that the output was correctly computed:

proof = IETF_VRF[Bandersnatch].prove(alpha, secret_key, additional_data)

Output Hash

The pseudo-random output derived from the proof:

output_hash = IETF_VRF[Bandersnatch].proof_to_hash(proof.output_point)  # 32 bytes

The Three VRF Schemes

IETF VRF

The standard VRF following RFC 9381:

  • ✅ Widely standardized
  • ✅ Simple to use
  • ❌ Public key is visible to verifier
from dot_ring import Bandersnatch, IETF_VRF

proof = IETF_VRF[Bandersnatch].prove(alpha, secret_key, additional_data)
is_valid = proof.verify(public_key, alpha, additional_data)

Pedersen VRF

Enhanced privacy using Pedersen commitments:

  • ✅ Public key is blinded in the proof
  • ✅ Verifier cannot link proofs to a specific key
  • ❌ Slightly larger proofs
from dot_ring import Bandersnatch, PedersenVRF

proof = PedersenVRF[Bandersnatch].prove(alpha, secret_key, additional_data)
is_valid = proof.verify(alpha, additional_data) # No public key needed!

Ring VRF

Full anonymity within a ring of public keys:

  • ✅ Proves membership in a set without revealing which member
  • ✅ Uses KZG polynomial commitments for efficiency
  • ❌ Requires pre-computed ring commitment
  • ❌ Currently only supports Bandersnatch curve
from dot_ring import Bandersnatch, RingVRF

# Build ring from list of public keys
ring_root = RingVRF[Bandersnatch].construct_ring_root(keys_list)

# Prove membership anonymously
proof = RingVRF[Bandersnatch].prove(alpha, ad, secret_key, my_public_key, keys_list)
is_valid = proof.verify(alpha, ad, ring_root)

Choosing a Scheme

Use CaseRecommended Scheme
Standard randomness beaconIETF VRF
Lottery / random selectionIETF VRF
Privacy-preserving authenticationPedersen VRF
Anonymous votingRing VRF
Blockchain validator selectionRing VRF

Elliptic Curves

DotRing supports 18 elliptic curves. The most commonly used:

CurveBest For
BandersnatchPolkadot ecosystem, Ring VRF
Ed25519General purpose, widely supported
secp256k1Bitcoin/Ethereum compatibility
BLS12-381Pairing-based cryptography

See the Curves Reference for the complete list.