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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use crate::constants::BASEPOINT;
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
use curve25519_dalek::scalar::Scalar;
use sha2::Sha512;
use std::collections::HashSet;
#[derive(Debug, Clone)]
pub struct PublicSet(pub Vec<RistrettoPoint>);
impl PublicSet {
pub fn len(&self) -> usize {
self.0.len()
}
pub fn duplicates_exist(&self) -> bool {
let compressed_points: Vec<CompressedRistretto> =
self.0.iter().map(|point| point.compress()).collect();
let hashable_slice: Vec<&[u8; 32]> =
compressed_points.iter().map(|cp| cp.as_bytes()).collect();
let uniques: HashSet<_> = hashable_slice.iter().collect();
self.0.len() != uniques.len()
}
pub fn compress(&self) -> Vec<CompressedRistretto> {
self.0.iter().map(|point| point.compress()).collect()
}
}
#[derive(Debug, Clone)]
pub struct PrivateSet(pub(crate) Vec<Scalar>);
impl PrivateSet {
pub fn new(scalars: Vec<Scalar>) -> Self {
PrivateSet(scalars)
}
pub fn to_public_set(&self) -> PublicSet {
let public_keys = self
.0
.iter()
.map(|&x| x * BASEPOINT)
.collect::<Vec<RistrettoPoint>>();
PublicSet(public_keys)
}
pub fn compute_key_images(&self, public_set: &PublicSet) -> Vec<RistrettoPoint> {
assert_eq!(self.len(), public_set.len());
let num_public_keys = public_set.len();
let mut key_images: Vec<RistrettoPoint> = Vec::with_capacity(num_public_keys);
for i in 0..num_public_keys {
let public_key_i = public_set.0[i].compress();
let private_key_i = self.0[i];
let hashed_public_key =
RistrettoPoint::hash_from_bytes::<Sha512>(public_key_i.as_bytes());
let key_image = private_key_i * hashed_public_key;
key_images.push(key_image);
}
key_images
}
pub fn len(&self) -> usize {
self.0.len()
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::tests_helper::*;
#[test]
fn private_set_to_public_set() {
let private_set = generate_private_set(10);
let public_set = private_set.to_public_set();
assert_eq!(private_set.len(), public_set.len());
for i in 0..private_set.len() {
match (private_set.0.get(i), public_set.0.get(i)) {
(Some(private_key), Some(expected_public_key)) => {
let public_key = private_key * &BASEPOINT;
assert_eq!(public_key, *expected_public_key);
}
_ => panic!("could not get the private/public key at index {} ", i),
}
}
}
#[test]
fn check_duplicates_exist() {
let private_set = generate_private_set(10);
let mut public_set = private_set.to_public_set();
let dup_exists = public_set.duplicates_exist();
assert!(!dup_exists);
let last_element = public_set.0.last().unwrap().clone();
public_set.0[0] = last_element;
let dup_exists = public_set.duplicates_exist();
assert!(dup_exists);
}
}