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