Ristretto255 encodes group elements using 255 bits and provides a prime-order group of size \(2^{252}\), and implemented with Curve25519. We use a prime of \(2^{255}-19\). In this case, we will hash a string with SHA-512, and then map this to a point on the curve. This will be computed for Ristretto255 and an Edwards curve.
Ristretto255 in Rust |
Test vectors
A sample run is:
Message: "Hello" Ristretto Point: e03f49c02250e13d068472592edbb9517507b99e954cfca6b79c24311fb7bf6e Edwards Point: 945b37b5ce68fcbda2b8435029cc00a1012ac1e3c0ea5923c55d018faea8fda5
and:
Message: "Ristretto is traditionally a short shot of espresso coffee" Ristretto Point: 3066f82a1a747d45120d1740f14358531a8f04bbffe6a819f86dfe50f44a0a46 Edwards Point: 85b02d85ff8008a0f9be26b53ca94c10ddb56208ccdc94cfc2da9395364982b6
Some text vectors are given here [link]:
let labels = [ "Ristretto is traditionally a short shot of espresso coffee", "made with the normal amount of ground coffee but extracted with", "about half the amount of water in the same amount of time", "by using a finer grind.", "This produces a concentrated shot of coffee per volume.", "Just pulling a normal shot short will produce a weaker shot", "and is not a Ristretto as some believe.", ]; let encoded_hash_to_points = [ "3066f82a1a747d45120d1740f14358531a8f04bbffe6a819f86dfe50f44a0a46", "f26e5b6f7d362d2d2a94c5d0e7602cb4773c95a2e5c31a64f133189fa76ed61b", "006ccd2a9e6867e6a2c5cea83d3302cc9de128dd2a9a57dd8ee7b9d7ffe02826", "f8f0c87cf237953c5890aec3998169005dae3eca1fbb04548c635953c817f92a", "ae81e7dedf20a497e10c304a765c1767a42d6e06029758d2d7e8ef7cc4c41179", "e2705652ff9f5e44d3e841bf1c251cf7dddb77d140870d1ab2ed64f1a9ce8628", "80bd07262511cdde4863f8a7434cef696750681cb9510eea557088f76d9e5065", ];
and where "Ristretto is traditionally a short shot of espresso coffee" gives a point of "3066f82a1a747d45120d1740f14358531a8f04bbffe6a819f86dfe50f44a0a46".
Code
First we create the with:
cargo new ris
We then go into the ris folder, and add the following to the cargo.toml file:
[package] name = "ris" version = "0.1.0" edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] curve25519-dalek = "4.1.1" ed25519-dalek ="2.1.1" rand_core = { version = "0.6.4", features = ["std"] } hex="0.4.3" sha2="0.10.8"
Next we go into the src folder, and edit the main.rs file with:
use std::io::{stdout, Write}; use sha2::{Sha512}; use hex; use curve25519_dalek::{RistrettoPoint,EdwardsPoint}; use std::env; fn main() { let mut msg = "Ristretto is traditionally a short shot of espresso coffee"; let args: Vec <String>= env::args().collect(); if args.len() >1 { msg = args[1].as_str();} let P = RistrettoPoint::hash_from_bytes::(msg.as_bytes()); println!("Message: {:?}",msg); println!("\nRistretto Point: {}",hex::encode(P.compress().as_bytes())); let E = EdwardsPoint::nonspec_map_to_curve:: (msg.as_bytes()); println!("\nEdwards Point: {}",hex::encode(E.compress().as_bytes()));
Finally we simply build with:
cargo build