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::{fields::PrimeField, BigInteger, Fp256};
  5use ark_std::{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
 37#[allow(clippy::many_single_char_names)]
 38impl KeyPair {
 39    pub fn key_image(&self) -> EdwardsProjective {
 40        hash_to_point(self.pk).mul(self.sk.into_repr())
 41    }
 42
 43    pub fn sign(&self, ring: Vec<PublicKey>, m: Vec<u8>) -> Result<Signature, String> {
 44        let ring_size = ring.len();
 45        // determine pi (the position of signer's public key in R
 46        let mut pi = 0;
 47        let mut found = false;
 48        // for i in 0..ring_size {
 49        for (i, ring_key) in ring.iter().enumerate() {
 50            if &self.pk == ring_key {
 51                pi = i;
 52                found = true;
 53                break;
 54            }
 55        }
 56        if !found {
 57            return Err("key not found in the ring".to_string());
 58        }
 59
 60        let mut rng = ark_std::rand::thread_rng();
 61        let a: Fr = Fr::rand(&mut rng);
 62        let mut r: Vec<Fr> = vec![Fr::zero(); ring_size];
 63
 64        // for i \in {1, 2, ..., n} \ {i=pi}
 65        #[allow(clippy::needless_range_loop)]
 66        for i in 0..ring_size {
 67            if i == pi {
 68                continue;
 69            }
 70            r[i] = Fr::rand(&mut rng);
 71        }
 72
 73        let mut c: Vec<Fr> = vec![Fr::zero(); ring_size];
 74        // c_{pi+1}
 75        let pi1 = (pi + 1) % ring_size;
 76        c[pi1] = hash(
 77            &ring,
 78            &m,
 79            G.mul(a.into_repr()),
 80            hash_to_point(ring[pi]).mul(a.into_repr()),
 81        );
 82
 83        let key_image = self.key_image();
 84        // do c_{i+1} from i=pi+1 to pi-1:
 85        for j in 0..(ring_size - 1) {
 86            let i = (pi1 + j) % ring_size;
 87            let i1 = (pi1 + j + 1) % ring_size;
 88            c[i1] = hash(
 89                &ring,
 90                &m,
 91                G.mul(r[i].into_repr()) + ring[i].mul(c[i].into_repr()),
 92                hash_to_point(ring[i]).mul(r[i].into_repr()) + key_image.mul(c[i].into_repr()),
 93            );
 94            println!("i {:?}, {:?}", i, c[i1]);
 95        }
 96
 97        // compute r_pi
 98        r[pi] = a - c[pi] * self.sk;
 99        Ok((c[0], r))
100    }
101}
102
103pub fn verify(
104    ring: Vec<PublicKey>,
105    m: Vec<u8>,
106    key_image: EdwardsProjective,
107    sig: Signature,
108) -> bool {
109    let ring_size = ring.len();
110
111    let c1 = sig.0;
112    let r = sig.1;
113    if ring_size != r.len() {
114        return false;
115    }
116    // TODO check that key_image \in G (EC), by l * key_image == 0
117
118    let mut c: Vec<Fr> = vec![Fr::zero(); ring_size];
119    c[0] = c1;
120    for j in 0..ring_size {
121        let i = j % ring_size;
122        let i1 = (j + 1) % ring_size;
123        c[i1] = hash(
124            &ring,
125            &m,
126            G.mul(r[i].into_repr()) + ring[i].mul(c[i].into_repr()),
127            hash_to_point(ring[i]).mul(r[i].into_repr()) + key_image.mul(c[i].into_repr()),
128        );
129    }
130
131    println!("c {:?}\n{:?}", c1, c[0]);
132
133    if c1 == c[0] {
134        return true;
135    }
136    false
137}
138
139fn hash_to_point(a: EdwardsProjective) -> EdwardsProjective {
140    // TODO use a proper hash_to_point method
141    let mut v: Vec<u8> = Vec::new();
142    v.append(&mut a.into_affine().x.into_repr().to_bytes_le());
143    v.append(&mut a.into_affine().y.into_repr().to_bytes_le());
144    let mut hasher = Sha256::new();
145    hasher.update(v);
146    let h = hasher.finalize();
147    let v = Fr::from_le_bytes_mod_order(&h[..]);
148
149    G.mul(v.into_repr())
150}
151
152fn hash(ring: &[PublicKey], m: &[u8], a: EdwardsProjective, b: EdwardsProjective) -> Fr {
153    let mut v: Vec<u8> = Vec::new();
154
155    for ring_key in ring.iter() {
156        v.append(&mut ring_key.into_affine().x.into_repr().to_bytes_le());
157        v.append(&mut ring_key.into_affine().y.into_repr().to_bytes_le());
158    }
159    v.append(&mut m.to_vec());
160    v.append(&mut a.into_affine().x.into_repr().to_bytes_le());
161    v.append(&mut a.into_affine().y.into_repr().to_bytes_le());
162    v.append(&mut b.into_affine().x.into_repr().to_bytes_le());
163    v.append(&mut b.into_affine().y.into_repr().to_bytes_le());
164
165    Fr::from_le_bytes_mod_order(&Sha256::new().chain_update(v).finalize())
166}
167
168#[cfg(test)]
169mod tests {
170    use super::*;
171
172    #[test]
173    #[allow(non_snake_case)]
174    fn test_bLSAG() {
175        let n = 5; // ring size
176        let pi = 3; // position of prover key in the ring
177
178        let k_pi = new_key();
179        println!("{:?}", k_pi);
180
181        // generate other n public keys
182        let mut ring: Vec<PublicKey> = vec![G.clone(); n];
183        for i in 0..n {
184            let k = new_key();
185            ring[i] = k.pk;
186        }
187        // set K_pi
188        ring[pi] = k_pi.pk;
189
190        let m: Vec<u8> = vec![1, 2, 3, 4];
191        let sig = k_pi.sign(ring.clone(), m.clone()).unwrap();
192        println!("sig {:?}", sig);
193
194        let key_image = k_pi.key_image();
195
196        let v = verify(ring.clone(), m.clone(), key_image, sig.clone());
197        println!("v {:?}", v);
198        assert!(v);
199
200        let m: Vec<u8> = vec![1, 2, 3, 3];
201        let v = verify(ring, m, key_image, sig);
202        assert!(!v);
203    }
204}