arnaucube
arnaucube/ring-signatures-rsPublic Self-hosted repository
ring-signatures-rs/src/lib.rs
src/lib.rsRaw
  1extern crate ark_ed_on_bn254;
  2use ark_ec::{AffineCurve, ProjectiveCurve, TEModelParameters};
  3use ark_ed_on_bn254::{EdwardsAffine, EdwardsParameters, EdwardsProjective, FqParameters, Fr};
  4use ark_ff::{bytes::FromBytes, fields::PrimeField, BigInteger, Fp256};
  5use ark_std::{rand, UniformRand, Zero};
  6use sha2::{Digest, Sha256};
  7
  8const GX: Fp256<FqParameters> = <EdwardsParameters as TEModelParameters>::AFFINE_GENERATOR_COEFFS.0;
  9const GY: Fp256<FqParameters> = <EdwardsParameters as TEModelParameters>::AFFINE_GENERATOR_COEFFS.1;
 10
 11#[macro_use]
 12extern crate lazy_static;
 13
 14lazy_static! {
 15    static ref G_AFFINE: EdwardsAffine = EdwardsAffine::new(GX, GY);
 16    pub static ref G: EdwardsProjective = G_AFFINE.into_projective();
 17}
 18
 19pub type PublicKey = EdwardsProjective;
 20pub type Signature = (Fr, Vec<Fr>);
 21
 22#[derive(Debug, PartialEq)]
 23pub struct KeyPair {
 24    sk: Fr,
 25    pub pk: PublicKey,
 26}
 27
 28pub fn new_key() -> KeyPair {
 29    let mut rng = ark_std::rand::thread_rng();
 30    let sk: Fr = Fr::rand(&mut rng);
 31    // let sk: Fr = UniformRand::rand(&mut rng);
 32
 33    let pk = G.mul(sk.into_repr());
 34    KeyPair { sk, pk }
 35}
 36
 37impl KeyPair {
 38    pub fn key_image(&self) -> EdwardsProjective {
 39        hash_to_point(self.pk).mul(self.sk.into_repr())
 40    }
 41
 42    pub fn sign(&self, ring: Vec<PublicKey>, m: Vec<u8>) -> Signature {
 43        let ring_size = ring.len();
 44        // determine pi (the position of signer's public key in R
 45        let mut pi = 0;
 46        let mut found = false;
 47        for i in 0..ring_size {
 48            if self.pk == ring[i] {
 49                pi = i;
 50                found = true;
 51                break;
 52            }
 53        }
 54        if !found {
 55            // error
 56            println!("key not found in the ring");
 57        }
 58
 59        let mut rng = ark_std::rand::thread_rng();
 60        let a: Fr = Fr::rand(&mut rng);
 61        let mut r: Vec<Fr> = vec![Fr::zero(); ring_size];
 62
 63        // for i \in {1, 2, ..., n} \ {i=pi}
 64        for i in 0..ring_size {
 65            if i == pi {
 66                continue;
 67            }
 68            r[i] = Fr::rand(&mut rng);
 69        }
 70
 71        let mut c: Vec<Fr> = vec![Fr::zero(); ring_size];
 72        // c_{pi+1}
 73        let pi1 = (pi + 1) % ring_size;
 74        c[pi1] = hash(
 75            &ring,
 76            &m,
 77            G.mul(a.into_repr()),
 78            hash_to_point(ring[pi]).mul(a.into_repr()),
 79        );
 80
 81        let key_image = self.key_image();
 82        // do c_{i+1} from i=pi+1 to pi-1:
 83        for j in 0..(ring_size - 1) {
 84            let i = (pi1 + j) % ring_size;
 85            let i1 = (pi1 + j + 1) % ring_size;
 86            c[i1] = hash(
 87                &ring,
 88                &m,
 89                G.mul(r[i].into_repr()) + ring[i].mul(c[i].into_repr()),
 90                hash_to_point(ring[i]).mul(r[i].into_repr()) + key_image.mul(c[i].into_repr()),
 91            );
 92            println!("i {:?}, {:?}", i, c[i1]);
 93        }
 94
 95        // compute r_pi
 96        r[pi] = a - c[pi] * self.sk;
 97        (c[0], r)
 98    }
 99}
100
101pub fn verify(
102    ring: Vec<PublicKey>,
103    m: Vec<u8>,
104    key_image: EdwardsProjective,
105    sig: Signature,
106) -> bool {
107    let ring_size = ring.len();
108
109    let c1 = sig.0;
110    let r = sig.1;
111    if ring_size != r.len() {
112        println!("ERROR"); // TODO
113        return false;
114    }
115    // TODO check that key_image \in G (EC), by l * key_image == 0
116
117    let mut c: Vec<Fr> = vec![Fr::zero(); ring_size];
118    c[0] = c1;
119    for j in 0..ring_size {
120        let i = j % ring_size;
121        let i1 = (j + 1) % ring_size;
122        c[i1] = hash(
123            &ring,
124            &m,
125            G.mul(r[i].into_repr()) + ring[i].mul(c[i].into_repr()),
126            hash_to_point(ring[i]).mul(r[i].into_repr()) + key_image.mul(c[i].into_repr()),
127        );
128    }
129
130    println!("c {:?}\n{:?}", c1, c[0]);
131
132    if c1 == c[0] {
133        return true;
134    }
135    false
136}
137
138fn hash_to_point(a: EdwardsProjective) -> EdwardsProjective {
139    // TODO use a proper hash_to_point method
140    let mut v: Vec<u8> = Vec::new();
141    v.append(&mut a.into_affine().x.into_repr().to_bytes_le());
142    v.append(&mut a.into_affine().y.into_repr().to_bytes_le());
143    let mut hasher = Sha256::new();
144    hasher.update(v);
145    let h = hasher.finalize();
146    let v = Fr::from_le_bytes_mod_order(&h[..]);
147
148    G.mul(v.into_repr())
149}
150
151fn hash(ring: &Vec<PublicKey>, m: &Vec<u8>, a: EdwardsProjective, b: EdwardsProjective) -> Fr {
152    let mut v: Vec<u8> = Vec::new();
153
154    for i in 0..ring.len() {
155        v.append(&mut ring[i].into_affine().x.into_repr().to_bytes_le());
156        v.append(&mut ring[i].into_affine().y.into_repr().to_bytes_le());
157    }
158    v.append(&mut m.clone());
159    v.append(&mut a.into_affine().x.into_repr().to_bytes_le());
160    v.append(&mut a.into_affine().y.into_repr().to_bytes_le());
161    v.append(&mut b.into_affine().x.into_repr().to_bytes_le());
162    v.append(&mut b.into_affine().y.into_repr().to_bytes_le());
163
164    Fr::from_le_bytes_mod_order(&Sha256::new().chain_update(v).finalize())
165}
166
167#[cfg(test)]
168mod tests {
169    use super::*;
170
171    #[test]
172    #[allow(non_snake_case)]
173    fn test_bLSAG() {
174        let n = 5; // ring size
175        let pi = 3; // position of prover key in the ring
176
177        let k_pi = new_key();
178        println!("{:?}", k_pi);
179
180        // generate other n public keys
181        let mut ring: Vec<PublicKey> = vec![G.clone(); n];
182        for i in 0..n {
183            let k = new_key();
184            ring[i] = k.pk;
185        }
186        // set K_pi
187        ring[pi] = k_pi.pk;
188
189        let m: Vec<u8> = vec![1, 2, 3, 4];
190        let sig = k_pi.sign(ring.clone(), m.clone());
191        println!("sig {:?}", sig);
192
193        let key_image = k_pi.key_image();
194
195        let v = verify(ring.clone(), m.clone(), key_image, sig.clone());
196        println!("v {:?}", v);
197        assert!(v);
198
199        let m: Vec<u8> = vec![1, 2, 3, 3];
200        let v = verify(ring, m, key_image, sig);
201        assert!(!v);
202    }
203}