VRF.py provides an implementation of a Verifiable Random Function (VRF) to ensure the randomness and fairness of a game. The script contains functions to generate seeds, proofs, and random values, and to verify the outcome of a game.
Screen.Recording.2023-09-17.at.10.15.27.AM.mov
Initialization of a game is achived with the new_game
function. Belows's a detailed breakdown of the new_game
function.
The generate_seed_salt_hash
function is a foundational step in the initialization process. It's responsible for creating a random seed and its corresponding hash. Here's a breakdown of its purpose and functionality:
-
Seed Generation: The function generates a random seed using Python's
secrets.token_hex(16)
. This seed acts as a unique identifier for each game, ensuring that every game has a distinct starting point. -
Salt Generation: A random salt (
salt
) is produced usingsecrets.token_hex(32)
. This salt is used in conjunction with the seed to derive the seed hash. The inclusion of a salt ensures that even if the same seed is used in multiple game rounds, the resulting seed hash will be different each time. -
Seed Hash Generation: The
seed
, combined with thesalt
, undergoes a hashing process using the PBKDF2 HMAC SHA-512 algorithm. This produces theseed_hash
, which is a deterministic yet unpredictable value based on the seed and salt.
seed, seed_hash, salt = generate_seed_salt_hash()
The generate_beta_and_proof
function is a pivotal component in the game's cryptographic operations, ensuring randomness, unpredictability, and verifiability of the game's outcome. Here's a detailed breakdown of its purpose and functionality:
-
Alpha: The function takes in an
alpha
value, which is a combination of game-specific parameters; timestamps and bets. -
Proof: Using a provided private key and the
alpha
value, a digital signature (proof
) is generated. Thisproof
acts as a cryptographic commitment, ensuring that the server cannot change the game's parameters without detection. -
Beta: The function calculates the
beta
value, which is derived by hashing a combination of theseed_hash
,salt
, andproof
. This value is deterministic, meaning for the same inputs, it will always produce the same output. However, due to the randomness introduced by theseed_hash
andsalt
, it remains unpredictable for each game round. -
Bullet Index: The
beta
value is then used to determine thebullet_index
. This index represents the starting position or the "loaded chamber" in the game, ensuring that the game's outcome is both random and verifiable.
beta, proof, bullet_index = generate_beta_and_proof(
private_key, alpha, seed_hash, salt, revolver_chambers
)
The concluding lines of the new_game
function solidify the game's cryptographic foundation, ensuring the game's integrity and verifiability. Here's a detailed breakdown of these operations:
-
Bullet Index Hash: This step involves hashing a combination of the
bullet_index
,salt
, andseed_hash
. The resulting hash, termedbullet_index_hash
, acts as a commitment to the initial state of the game. It ensures that the starting position of the bullet, along with the game's foundational parameters, remains tamper-proof. -
Public Key: The function extracts the public key from the provided private key. This public key, represented in PEM format as
public_key_pem
, will be used later for verification purposes. It ensures that any cryptographic proof provided by the server can be verified by the player.
bullet_index_hash = hashlib.pbkdf2_hmac(
ALGO,
(str(bullet_index) + salt + seed_hash).encode(),
salt.encode(),
ITERATIONS
).hex()
public_key_pem = private_key.verifying_key.to_pem()
The verify
function is responsible for ensuring the integrity and authenticity of the game's outcome. It does so by validating the cryptographic proofs and commitments provided during the game's initialization. Below is a detailed breakdown of the verify
function.
The first step in the verification process is to validate the digital signature (proof
) against the alpha
value using the provided public key
. This ensures that the game's parameters have not been tampered with after the game's initialization.
- Public Key Extraction: The function begins by extracting the verifying key (
vk
) from the provided public key in PEM format. - Signature Verification: Using the extracted verifying key, the function attempts to verify the proof against the alpha value. If the verification is successful, it confirms that the proof was indeed generated using the corresponding private key.
vk = ecdsa.VerifyingKey.from_pem(public_key)
vk.verify(proof, alpha, hashfunc=hashlib.sha256)
After successfully verifying the digital signature, the function proceeds to validate the bullet index hash that was provided during the game's initialization.
- Beta Calculation: The function recalculates the
beta
value by hashing a combination of the proof, salt, and seed_hash. - Bullet Index Determination: Using the recalculated beta value, the function derives the bullet_index. This index represents the starting position or the "loaded chamber" in the game.
- Bullet Index Hash Recalculation: The function then recalculates the hash of the bullet_index, combined with the salt and seed_hash. This derived hash should match the bullet_index_hash that was provided during the game's initialization
beta = generate_beta(proof, salt, seed_hash)
bullet_index = int(beta, 16) % revolver_chambers
derived_bullet_index_hash = hashlib.pbkdf2_hmac(
ALGO,
(str(bullet_index) + salt + seed_hash).encode(),
salt.encode(),
ITERATIONS
).hex()
The final step in the validation process is to compare the recalculated bullet_index_hash with the one that was provided during the game's initialization. If they match, it confirms that the game's outcome was determined randomly and has not been altered.
if derived_bullet_index_hash == bullet_index_hash:
return proof_validity, derived_bullet_index_hash
VRF Mechanism Breakdown:
Seed, Salt, and Seed Hash Generation:
- A random
seed
andsalt
are generated using the secrets module. - A
seed hash
is then generated using the PBKDF2 HMAC algorithm with the seed and salt as inputs.
Proof Generation:
- A
proof
is generated using the private key (sk) and an input message (alpha
). The input message is created by concatenating the current UNIX timestamp with the array of player bets. - The
proof
is signed using the ECDSA algorithm with the SHA-256 hash function.
Beta Generation:
Beta
is generated using the PBKDF2 HMAC algorithm with the seed hash, salt, and proof as inputs.
Bullet Index Determination:
- The
bullet index
is determined by taking the integer representation of beta and then computing its modulo with the revolver size.
Bullet Index Hash Generation:
- A
bullet index hash
of the bullet index is generated using the PBKDF2 HMAC algorithm with the bullet index, salt, and seed hash as inputs.
Verification:
- A
public key
is extracted from a private key. - A
proof
is verified using thepublic key
and an input message (alpha
). - A deterministic
beta
is generated using theproof, salt, and seed hash
. - The
bullet index
is derived from this beta. - A
derived bullet index hash
is generated using the derived bullet index, salt, and seed hash. - The derived bullet index hash is then compared with the bullet index hash generated during the game setup to verify the game's fairness.
coverage run -m pytest tests/
coverage report -m > coverage.txt
git clone [email protected]:0xlucyfer/vrf.git
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
- Uncomment functions
example_run
andmain
invrf_py/VRF.py
. python vrf_py/VRF.py
- https://pypi.org/project/vrf/1.0.4/
pip install vrf==1.0.4
from vrf_py import new_game, verify
pip install --upgrade twine
python setup.py sdist bdist_wheel
twine upload --repository pypi dist/*
- If prompted for token, input token from pypi found in
.pypirc
file.