1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use std_shims::{
  io::{self, *},
  vec::Vec,
};

use zeroize::Zeroize;

use curve25519_dalek::{EdwardsPoint, Scalar};

use monero_generators::hash_to_point;

use crate::{serialize::*, hash_to_scalar};

#[derive(Clone, PartialEq, Eq, Debug, Zeroize)]
pub struct Signature {
  c: Scalar,
  r: Scalar,
}

impl Signature {
  pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
    write_scalar(&self.c, w)?;
    write_scalar(&self.r, w)?;
    Ok(())
  }

  pub fn read<R: Read>(r: &mut R) -> io::Result<Signature> {
    Ok(Signature { c: read_scalar(r)?, r: read_scalar(r)? })
  }
}

#[derive(Clone, PartialEq, Eq, Debug, Zeroize)]
pub struct RingSignature {
  sigs: Vec<Signature>,
}

impl RingSignature {
  pub fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
    for sig in &self.sigs {
      sig.write(w)?;
    }
    Ok(())
  }

  pub fn read<R: Read>(members: usize, r: &mut R) -> io::Result<RingSignature> {
    Ok(RingSignature { sigs: read_raw_vec(Signature::read, members, r)? })
  }

  pub fn verify(&self, msg: &[u8; 32], ring: &[EdwardsPoint], key_image: &EdwardsPoint) -> bool {
    if ring.len() != self.sigs.len() {
      return false;
    }

    let mut buf = Vec::with_capacity(32 + (32 * 2 * ring.len()));
    buf.extend_from_slice(msg);

    let mut sum = Scalar::ZERO;

    for (ring_member, sig) in ring.iter().zip(&self.sigs) {
      #[allow(non_snake_case)]
      let Li = EdwardsPoint::vartime_double_scalar_mul_basepoint(&sig.c, ring_member, &sig.r);
      buf.extend_from_slice(Li.compress().as_bytes());
      #[allow(non_snake_case)]
      let Ri = (sig.r * hash_to_point(ring_member.compress().to_bytes())) + (sig.c * key_image);
      buf.extend_from_slice(Ri.compress().as_bytes());

      sum += sig.c;
    }

    sum == hash_to_scalar(&buf)
  }
}