# Crate dalek_rangeproofs [−] [src]

A pure-Rust implementation of the Back-Maxwell rangeproof scheme defined in
*Confidential Assets* (2017) by Poelstra, Back, Friedenbach, Maxwell,
Wuille.

The scheme is instantiated using the Decaf group on Curve25519, as
implemented in
`curve25519-dalek`

.
Note that since the Decaf implementation in `curve25519-dalek`

is
currently **UNFINISHED, UNREVIEWED, AND EXPERIMENTAL**, so is this
library.

This implementation hardcodes the ring size `m = 3`

, as this is
the most efficient choice. The number of rings `n`

determines the
range `[0,3^n]`

, as well as the size and speed of the proof.

# Examples

Suppose we want to prove that `134492616741`

is within `[0,3^40]`

.
Since 3^{40} ≅ 0.66 (2^{64} ), this is just slightly narrower than the
range of a `u64`

.

To construct a proof that `134492616741`

is within `[0,3^40]`

,
first choose orthogonal basepoints. Usually the basepoints would
be set or distributed as system-wide parameters. Here we choose
`G`

to be the Decaf coset containing the ed25519 basepoint and
generate the second basepoint as `H = Hash(G)`

. (Technically, `G`

is actually a `DecafBasepointTable`

, which implements
`Mul<&Scalar>`

using a precomputed table).

use sha2::Sha256; use curve25519_dalek::constants as dalek_constants; use curve25519_dalek::decaf::{DecafBasepointTable, DecafPoint}; use curve25519_dalek::scalar::Scalar; let G = &dalek_constants::DECAF_ED25519_BASEPOINT_TABLE; let H = DecafPoint::hash_from_bytes::<Sha256>(G.basepoint().compress().as_bytes());

You'll also need your value and a CSPRNG:

use rand::OsRng; let mut csprng = OsRng::new().unwrap(); let value = 134492616741;

We can now create the rangeproof, like so:

use dalek_rangeproofs::RangeProof; let (proof, commitment, blinding) = RangeProof::create(40, value, G, &H, &mut csprng).unwrap();

The output is the proof `proof`

, as well as `commitment = blinding*G + value*H`

.

We can serialize the proof using Serde. Here, we use CBOR.

extern crate serde_cbor; let proof_bytes: Vec<u8> = serde_cbor::ser::to_vec_packed(&proof).unwrap(); assert_eq!(proof_bytes.len(), 4125);

In this case, the `serde_cbor`

-encoded proof statement is
approximately 6.5% larger than the optimal 3872 = 32(1+3*40)
bytes. Another party can verify the proof statement from
`proof_bytes`

by doing:

extern crate serde_cbor; use dalek_rangeproofs::RangeProof; let proof: RangeProof = serde_cbor::from_slice(&proof_bytes).unwrap(); let C_option = proof.verify(40, G, &H); assert!(C_option.is_some()); let C = C_option.unwrap();

If the proof is well-formed, `verify`

returns the commitment to
the value. Since the commitment is the output of the
verification, the verifier is assured it opens to a value in the
range `[0,3^n]`

. However, without knowing both `blinding`

and the
actual `value`

, the verifier cannot open this commitment, because
Pedersen commitments are computationally binding and perfectly
hiding (in addition to being additively homomorphic, a feature
used within this scheme).

Later, to open this commitment, the prover could reveal the value
and the blinding, allowing others to check that `commitment = blinding*G + value*H`

.

let C_hat = &(G * &blinding) + &(&H * &Scalar::from_u64(value)); assert_eq!(C_hat, C);

## Structs

RangeProof |
A Back-Maxwell rangeproof, which proves in zero knowledge that a
number is in a range |

## Constants

RANGEPROOF_MAX_N |
The maximum allowed bound for the rangeproof. Currently this is
set to 41, because we only implement conversion to base 3 digits
for |