// Implementation of CMZ14 credentials (GGM version, which is more // efficient, but makes a stronger security assumption): "Algebraic MACs // and Keyed-Verification Anonymous Credentials" (Chase, Meiklejohn, // and Zaverucha, CCS 2014) // The notation follows that of the paper "Hyphae: Social Secret // Sharing" (Lovecruft and de Valence, 2017), Section 4. #![allow(non_snake_case)] use sha2::Sha512; use curve25519_dalek::constants as dalek_constants; use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::ristretto::RistrettoBasepointTable; use curve25519_dalek::scalar::Scalar; use lazy_static::lazy_static; lazy_static! { pub static ref CMZ_A: RistrettoPoint = RistrettoPoint::hash_from_bytes::(b"CMZ Generator A"); pub static ref CMZ_B: RistrettoPoint = dalek_constants::RISTRETTO_BASEPOINT_POINT; pub static ref CMZ_A_TABLE: RistrettoBasepointTable = RistrettoBasepointTable::create(&CMZ_A); pub static ref CMZ_B_TABLE: RistrettoBasepointTable = dalek_constants::RISTRETTO_BASEPOINT_TABLE; } #[derive(Clone,Debug)] pub struct IssuerPrivKey { x0tilde: Scalar, x: Vec, } impl IssuerPrivKey { // Create an IssuerPrivKey for credentials with the given number of // attributes. pub fn new(n: u16) -> IssuerPrivKey { let mut rng: rand::rngs::ThreadRng = rand::thread_rng(); let x0tilde: Scalar = Scalar::random(&mut rng); let mut x: Vec = Vec::with_capacity((n+1) as usize); // Set x to a vector of n+1 random Scalars x.resize_with((n+1) as usize, || { Scalar::random(&mut rng) }); IssuerPrivKey { x0tilde, x } } } #[derive(Clone,Debug)] pub struct IssuerPubKey { X: Vec, } impl IssuerPubKey { // Create an IssuerPubKey from the corresponding IssuerPrivKey pub fn new(privkey: &IssuerPrivKey) -> IssuerPubKey { let Atable : &RistrettoBasepointTable = &CMZ_A_TABLE; let Btable : &RistrettoBasepointTable = &CMZ_B_TABLE; let n_plus_one: usize = privkey.x.len(); let mut X: Vec = Vec::with_capacity(n_plus_one); // The first element is a special case; it is // X[0] = x0tilde*A + x[0]*B X.push(&privkey.x0tilde * Atable + &privkey.x[0] * Btable); // The other elements (1 through n) are X[i] = x[i]*A for i in 1..n_plus_one { X.push(&privkey.x[i] * Atable); } IssuerPubKey { X } } } #[derive(Debug)] pub struct Issuer { privkey: IssuerPrivKey, pubkey: IssuerPubKey, } impl Issuer { // Create an issuer for credentials with the given number of // attributes pub fn new(n: u16) -> Issuer { let privkey = IssuerPrivKey::new(n); let pubkey = IssuerPubKey::new(&privkey); Issuer { privkey, pubkey } } }