shine.rs 9.6 KB

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