Browse Source

Be able to create Issuers and their private and public keys

Ian Goldberg 2 years ago
commit
c6f37a1833
4 changed files with 151 additions and 0 deletions
  1. 21 0
      Cargo.toml
  2. 92 0
      src/ggm.rs
  3. 4 0
      src/lib.rs
  4. 34 0
      tests/ggm.rs

+ 21 - 0
Cargo.toml

@@ -0,0 +1,21 @@
+[package]
+name = "cmz"
+version = "0.1.0"
+authors = ["Ian Goldberg <iang@uwaterloo.ca>"]
+edition = "2018"
+
+[dependencies]
+curve25519-dalek = { package = "curve25519-dalek-ng", version = "3", default-features = false, features = ["serde", "std"] }
+zkp = "0.8"
+bincode = "1"
+rand = "0.7"
+serde = "1"
+sha2 = "0.9"
+lazy_static = "1"
+hex_fmt = "0.3"
+
+[features]
+default = ["u64_backend"]
+u32_backend = ["curve25519-dalek/u32_backend"]
+u64_backend = ["curve25519-dalek/u64_backend"]
+simd_backend = ["curve25519-dalek/simd_backend"]

+ 92 - 0
src/ggm.rs

@@ -0,0 +1,92 @@
+// 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::<Sha512>(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<Scalar>,
+}
+
+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<Scalar> = 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<RistrettoPoint>,
+}
+
+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<RistrettoPoint> = 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 }
+    }
+}
+

+ 4 - 0
src/lib.rs

@@ -0,0 +1,4 @@
+#[macro_use]
+extern crate zkp;
+
+pub mod ggm;

+ 34 - 0
tests/ggm.rs

@@ -0,0 +1,34 @@
+#![allow(non_snake_case)]
+
+#[macro_use]
+extern crate zkp;
+
+use curve25519_dalek::ristretto::RistrettoPoint;
+use curve25519_dalek::scalar::Scalar;
+
+use cmz::ggm::CMZ_A;
+use cmz::ggm::CMZ_B;
+use cmz::ggm::Issuer;
+
+#[test]
+fn create_issuer() {
+    let i0 = Issuer::new(0);
+    println!("i0 = {:?}", i0);
+    let i1 = Issuer::new(1);
+    println!("i1 = {:?}", i1);
+}
+
+#[test]
+fn generator_test() {
+    use hex_fmt::HexFmt;
+
+    let A : &RistrettoPoint = &CMZ_A;
+    let B : &RistrettoPoint = &CMZ_B;
+    let two = Scalar::one() + Scalar::one();
+    println!("A = {}", HexFmt(A.compress().to_bytes()));
+    println!("B = {}", HexFmt(B.compress().to_bytes()));
+    println!("2*A = {}", HexFmt((two*A).compress().to_bytes()));
+    println!("2*A = {}", HexFmt((A+A).compress().to_bytes()));
+    println!("2*B = {}", HexFmt((two*B).compress().to_bytes()));
+    println!("2*B = {}", HexFmt((B+B).compress().to_bytes()));
+}