shine.rs 8.4 KB

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