shine.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. use crate::lagrange::*;
  2. use curve25519_dalek::constants as dalek_constants;
  3. use curve25519_dalek::ristretto::RistrettoPoint;
  4. use curve25519_dalek::ristretto::VartimeRistrettoPrecomputation;
  5. use curve25519_dalek::scalar::Scalar;
  6. use curve25519_dalek::traits::Identity;
  7. use curve25519_dalek::traits::VartimePrecomputedMultiscalarMul;
  8. use itertools::Itertools;
  9. use rand::RngCore;
  10. use rayon::prelude::*;
  11. use sha2::digest::FixedOutput;
  12. use sha2::Digest;
  13. use sha2::Sha256;
  14. // Compute (m choose k) when m^k < 2^64
  15. fn binom(m: u32, k: u32) -> u64 {
  16. let mut numer = 1u64;
  17. let mut denom = 1u64;
  18. for i in 0u64..(k as u64) {
  19. numer *= (m as u64) - i;
  20. denom *= i + 1;
  21. }
  22. numer / denom
  23. }
  24. // The hash function used to create the coefficients for the
  25. // pseudorandom secret sharing.
  26. fn hash1(phi: &[u8; 32], w: &[u8]) -> Scalar {
  27. let mut hash = Sha256::new();
  28. hash.update(phi);
  29. hash.update(w);
  30. let mut hashval = [0u8; 32];
  31. hash.finalize_into((&mut hashval).into());
  32. Scalar::from_bytes_mod_order(hashval)
  33. }
  34. // The key for player k will consist of a vector of (v, phi) tuples,
  35. // where the v values enumerate all lists of t-1 player numbers (from
  36. // 1 to n) that do _not_ include k
  37. #[derive(Debug)]
  38. pub struct Key {
  39. pub n: u32,
  40. pub t: u32,
  41. pub k: u32,
  42. pub secrets: Vec<(Vec<u32>, [u8; 32])>,
  43. }
  44. impl Key {
  45. pub fn keygen(n: u32, t: u32) -> Vec<Self> {
  46. let delta = binom(n - 1, t - 1);
  47. let mut rng = rand::thread_rng();
  48. let mut res: Vec<Self> = Vec::with_capacity(n as usize);
  49. for k in 1..=n {
  50. res.push(Self {
  51. n,
  52. t,
  53. k,
  54. secrets: Vec::with_capacity(delta as usize),
  55. });
  56. }
  57. let si = (1..=n).combinations((t - 1) as usize);
  58. for v in si {
  59. // For each subset of size t-1, pick a random secret, and
  60. // give it to all players _not_ in that subset
  61. let mut phi: [u8; 32] = [0; 32];
  62. rng.fill_bytes(&mut phi);
  63. let mut vnextind = 0usize;
  64. let mut vnext = v[0];
  65. for i in 1..=n {
  66. if i < vnext {
  67. res[(i - 1) as usize].secrets.push((v.clone(), phi));
  68. } else {
  69. vnextind += 1;
  70. vnext = if vnextind < ((t - 1) as usize) {
  71. v[vnextind]
  72. } else {
  73. n + 1
  74. };
  75. }
  76. }
  77. }
  78. res
  79. }
  80. }
  81. #[test]
  82. pub fn test_keygen() {
  83. let keys = Key::keygen(7, 4);
  84. println!("key for player 3: {:?}", keys[2]);
  85. println!("key for player 7: {:?}", keys[6]);
  86. }
  87. #[derive(Debug)]
  88. pub struct PreprocKey {
  89. pub n: u32,
  90. pub t: u32,
  91. pub k: u32,
  92. pub secrets: Vec<([u8; 32], Scalar)>,
  93. }
  94. impl PreprocKey {
  95. pub fn preproc(key: &Key) -> Self {
  96. Self {
  97. n: key.n,
  98. t: key.t,
  99. k: key.k,
  100. secrets: key
  101. .secrets
  102. .iter()
  103. .map(|(v, phi)| (*phi, lagrange(v, 0, key.k)))
  104. .collect(),
  105. }
  106. }
  107. pub fn rand(n: u32, t: u32) -> Self {
  108. let delta = binom(n - 1, t - 1);
  109. let mut secrets: Vec<([u8; 32], Scalar)> = Vec::new();
  110. let mut rng = rand::thread_rng();
  111. for _ in 0u64..delta {
  112. let mut phi = [0u8; 32];
  113. rng.fill_bytes(&mut phi);
  114. let lagrange: Scalar = Scalar::random(&mut rng);
  115. secrets.push((phi, lagrange));
  116. }
  117. Self {
  118. n,
  119. t,
  120. k: 1,
  121. secrets,
  122. }
  123. }
  124. pub fn gen(&self, w: &[u8]) -> (Scalar, RistrettoPoint) {
  125. let d = self
  126. .secrets
  127. .par_iter()
  128. .map(|(phi, lagrange)| hash1(phi, w) * lagrange)
  129. .sum();
  130. (d, &d * &dalek_constants::RISTRETTO_BASEPOINT_TABLE)
  131. }
  132. pub fn delta(&self) -> usize {
  133. self.secrets.len()
  134. }
  135. }
  136. pub fn commit(evaluation: &Scalar) -> RistrettoPoint {
  137. evaluation * &dalek_constants::RISTRETTO_BASEPOINT_TABLE
  138. }
  139. // Verify that a set of commitments are consistent with a given t, using
  140. // precomputed Lagrange polynomials. Return false if the commitments
  141. // are not consistent with the given t, or true if they are. You must
  142. // pass at least 2t-1 commitments, and the same number of lag_polys.
  143. pub fn verify_polys(t: u32, lag_polys: &[ScalarPoly], commitments: &[RistrettoPoint]) -> bool {
  144. // Check if the commitments are consistent: when interpolating the
  145. // polys in the exponent, the low t coefficients can be non-0 but
  146. // the ones above that must be 0
  147. let coalition_size = commitments.len();
  148. assert!(t >= 1);
  149. assert!(coalition_size >= 2 * (t as usize) - 1);
  150. assert!(coalition_size == lag_polys.len());
  151. assert!(coalition_size == lag_polys[0].coeffs.len());
  152. // Use this to compute the multiscalar multiplications
  153. let multiscalar = VartimeRistrettoPrecomputation::new(Vec::<RistrettoPoint>::new());
  154. // Compute the B_i for i from t to coalition_size-1. All of them
  155. // should be the identity; otherwise, the commitments are
  156. // inconsistent.
  157. ((t as usize)..coalition_size)
  158. .map(|i| {
  159. // B_i = \sum_j lag_polys[j].coeffs[i] * commitments[j]
  160. multiscalar.vartime_mixed_multiscalar_mul(
  161. &Vec::<Scalar>::new(),
  162. (0..coalition_size).map(|j| lag_polys[j].coeffs[i]),
  163. commitments,
  164. )
  165. })
  166. .all(|bi: RistrettoPoint| bi == RistrettoPoint::identity())
  167. }
  168. // Verify that a set of commitments are consistent with a given t.
  169. // Return false if the commitments are not consistent with the given t,
  170. // or true if they are. You must pass at least 2t-1 commitments, and the
  171. // same number of lag_polys.
  172. pub fn verify(t: u32, coalition: &[u32], commitments: &[RistrettoPoint]) -> bool {
  173. let polys = lagrange_polys(coalition);
  174. verify_polys(t, &polys, commitments)
  175. }
  176. // Combine already-verified commitments using precomputed Lagrange
  177. // polynomials. You must pass at least 2t-1 commitments, and the same
  178. // number of lag_polys.
  179. pub fn agg_polys(
  180. t: u32,
  181. lag_polys: &[ScalarPoly],
  182. commitments: &[RistrettoPoint],
  183. ) -> RistrettoPoint {
  184. let coalition_size = commitments.len();
  185. assert!(t >= 1);
  186. assert!(coalition_size >= 2 * (t as usize) - 1);
  187. assert!(coalition_size == lag_polys.len());
  188. assert!(coalition_size == lag_polys[0].coeffs.len());
  189. // Use this to compute the multiscalar multiplications
  190. let multiscalar = VartimeRistrettoPrecomputation::new(Vec::<RistrettoPoint>::new());
  191. // Compute B_0 (which is the combined commitment) and return it
  192. multiscalar.vartime_mixed_multiscalar_mul(
  193. &Vec::<Scalar>::new(),
  194. (0..coalition_size).map(|j| lag_polys[j].coeffs[0]),
  195. commitments,
  196. )
  197. }
  198. // Combine already-verified commitments. You must pass at least 2t-1
  199. // commitments, and the same number of lag_polys.
  200. pub fn agg(t: u32, coalition: &[u32], commitments: &[RistrettoPoint]) -> RistrettoPoint {
  201. let polys = lagrange_polys(coalition);
  202. agg_polys(t, &polys, commitments)
  203. }
  204. // Combine commitments using precomputed Lagrange polynomials. Return
  205. // None if the commitments are not consistent with the given t. You
  206. // must pass at least 2t-1 commitments, and the same number of
  207. // lag_polys. This function combines verify_polys and agg_polys into a
  208. // single call that returns Option<RistrettoPoint>.
  209. pub fn combinecomm_polys(
  210. t: u32,
  211. lag_polys: &[ScalarPoly],
  212. commitments: &[RistrettoPoint],
  213. ) -> Option<RistrettoPoint> {
  214. let coalition_size = commitments.len();
  215. assert!(t >= 1);
  216. assert!(coalition_size >= 2 * (t as usize) - 1);
  217. assert!(coalition_size == lag_polys.len());
  218. assert!(coalition_size == lag_polys[0].coeffs.len());
  219. // Check if the commitments are consistent: when interpolating the
  220. // polys in the exponent, the low t coefficients can be non-0 but
  221. // the ones above that must be 0
  222. if !verify_polys(t, lag_polys, commitments) {
  223. return None;
  224. }
  225. Some(agg_polys(t, lag_polys, commitments))
  226. }
  227. // Combine commitments. Return None if the commitments are not
  228. // consistent with the given t. You must pass at least 2t-1
  229. // commitments, and the same size of coalition. This function combines
  230. // verify and agg into a single call that returns
  231. // Option<RistrettoPoint>.
  232. pub fn combinecomm(
  233. t: u32,
  234. coalition: &[u32],
  235. commitments: &[RistrettoPoint],
  236. ) -> Option<RistrettoPoint> {
  237. let polys = lagrange_polys(coalition);
  238. combinecomm_polys(t, &polys, commitments)
  239. }
  240. #[test]
  241. pub fn test_preproc() {
  242. let keys = Key::keygen(7, 4);
  243. let ppkey3 = PreprocKey::preproc(&keys[2]);
  244. let ppkey7 = PreprocKey::preproc(&keys[6]);
  245. println!("preproc key for player 3: {:?}", ppkey3);
  246. println!("preproc key for player 7: {:?}", ppkey7);
  247. }
  248. #[test]
  249. pub fn test_gen() {
  250. let keys = Key::keygen(7, 3);
  251. let ppkeys: Vec<PreprocKey> = keys.iter().map(|x| PreprocKey::preproc(x)).collect();
  252. let mut rng = rand::thread_rng();
  253. let mut w = [0u8; 32];
  254. rng.fill_bytes(&mut w);
  255. let evals: Vec<Scalar> = ppkeys.iter().map(|k| k.gen(&w).0).collect();
  256. // Try interpolating different subsets and check that the answer is
  257. // the same
  258. let interp1 = interpolate(&vec![1, 2, 3, 4, 5], &evals[0..=4], 0);
  259. let interp2 = interpolate(&vec![3, 4, 5, 6, 7], &evals[2..=6], 0);
  260. println!("interp1 = {:?}", interp1);
  261. println!("interp2 = {:?}", interp2);
  262. assert!(interp1 == interp2);
  263. }
  264. #[test]
  265. pub fn test_combinecomm() {
  266. let keys = Key::keygen(7, 3);
  267. let ppkeys: Vec<PreprocKey> = keys.iter().map(|x| PreprocKey::preproc(x)).collect();
  268. let mut rng = rand::thread_rng();
  269. let mut w = [0u8; 32];
  270. rng.fill_bytes(&mut w);
  271. let commitments: Vec<RistrettoPoint> = ppkeys.iter().map(|k| k.gen(&w).1).collect();
  272. let comm1 = combinecomm(3, &vec![1, 2, 3, 4, 5], &commitments[0..=4]);
  273. let comm2 = combinecomm(3, &vec![3, 4, 5, 6, 7], &commitments[2..=6]);
  274. assert_ne!(comm1, None);
  275. assert_ne!(comm2, None);
  276. // Test a failure case
  277. let comm3 = combinecomm(3, &vec![1, 2, 3, 4, 6], &commitments[0..=4]);
  278. assert_eq!(comm3, None);
  279. }