arctic.rs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. use crate::lagrange::*;
  2. use crate::shine;
  3. use curve25519_dalek::ristretto::RistrettoPoint;
  4. use curve25519_dalek::scalar::Scalar;
  5. use sha2::Digest;
  6. use sha2::Sha256;
  7. pub use crate::lagrange::lagrange_polys;
  8. type PubKey = RistrettoPoint;
  9. pub struct SecKey {
  10. t: u32,
  11. k: u32,
  12. sk: Scalar,
  13. rk: shine::PreprocKey,
  14. pk: PubKey,
  15. }
  16. impl SecKey {
  17. pub fn delta(&self) -> usize {
  18. self.rk.delta()
  19. }
  20. }
  21. type Signature = (RistrettoPoint, Scalar);
  22. pub fn keygen(n: u32, t: u32) -> (PubKey, Vec<SecKey>) {
  23. assert!(t >= 1);
  24. assert!(n >= 2 * t - 1);
  25. let mut seckeys: Vec<SecKey> = Vec::new();
  26. // The Shine key shares
  27. let shinekeys = shine::Key::keygen(n, t);
  28. // The signature key shares
  29. let shamirpoly = ScalarPoly::rand((t as usize) - 1);
  30. let pubkey = shine::commit(&shamirpoly.coeffs[0]);
  31. for k in 1..=n {
  32. seckeys.push(SecKey {
  33. t,
  34. k,
  35. sk: shamirpoly.eval(&Scalar::from(k)),
  36. rk: shine::PreprocKey::preproc(&shinekeys[(k as usize) - 1]),
  37. pk: pubkey,
  38. });
  39. }
  40. (pubkey, seckeys)
  41. }
  42. fn hash2(pk: &PubKey, msg: &[u8]) -> [u8; 32] {
  43. let mut hash = Sha256::new();
  44. hash.update(pk.compress().as_bytes());
  45. hash.update(msg);
  46. hash.finalize().into()
  47. }
  48. fn hash3(combcomm: &RistrettoPoint, pk: &PubKey, msg: &[u8]) -> Scalar {
  49. let mut hash = Sha256::new();
  50. hash.update(combcomm.compress().as_bytes());
  51. hash.update(pk.compress().as_bytes());
  52. hash.update(msg);
  53. let mut hashval = [0u8; 32];
  54. hashval[0..32].copy_from_slice(&hash.finalize());
  55. Scalar::from_bytes_mod_order(hashval)
  56. }
  57. pub fn sign1(sk: &SecKey, coalition: &[u32], msg: &[u8]) -> RistrettoPoint {
  58. assert!(coalition.len() >= 2 * (sk.t as usize) - 1);
  59. let w = hash2(&sk.pk, msg);
  60. sk.rk.gen(&w).1
  61. }
  62. pub fn sign2_polys(
  63. pk: &PubKey,
  64. sk: &SecKey,
  65. coalition: &[u32],
  66. lag_polys: &[ScalarPoly],
  67. msg: &[u8],
  68. commitments: &[RistrettoPoint],
  69. ) -> Option<Scalar> {
  70. // If the inputs are _malformed_, abort
  71. assert!(coalition.len() == lag_polys.len());
  72. assert!(coalition.len() == commitments.len());
  73. assert!(coalition.len() >= 2 * (sk.t as usize) - 1);
  74. // Find my own entry in the coalition; abort if it's not there
  75. let kindex = coalition.iter().position(|&k| k == sk.k).unwrap();
  76. let w = hash2(pk, msg);
  77. let (my_eval, my_commit) = sk.rk.gen(&w);
  78. assert!(commitments[kindex] == my_commit);
  79. // If the inputs are just corrupt values from malicious other
  80. // parties, return None but don't crash
  81. let combcomm = shine::combinecomm_polys(sk.t, lag_polys, commitments)?;
  82. let c = hash3(&combcomm, pk, msg);
  83. Some(my_eval + c * sk.sk)
  84. }
  85. pub fn sign2(
  86. pk: &PubKey,
  87. sk: &SecKey,
  88. coalition: &[u32],
  89. msg: &[u8],
  90. commitments: &[RistrettoPoint],
  91. ) -> Option<Scalar> {
  92. let polys = lagrange_polys(coalition);
  93. sign2_polys(pk, sk, coalition, &polys, msg, commitments)
  94. }
  95. pub fn combine_polys(
  96. pk: &PubKey,
  97. t: u32,
  98. coalition: &[u32],
  99. lag_polys: &[ScalarPoly],
  100. msg: &[u8],
  101. commitments: &[RistrettoPoint],
  102. sigshares: &[Scalar],
  103. ) -> Option<Signature> {
  104. assert!(coalition.len() == lag_polys.len());
  105. assert!(coalition.len() == commitments.len());
  106. assert!(coalition.len() == sigshares.len());
  107. assert!(coalition.len() >= 2 * (t as usize) - 1);
  108. let z = interpolate_polys_0(lag_polys, sigshares);
  109. // Check the answer
  110. let combcomm = shine::agg_polys(t, lag_polys, commitments);
  111. let c = hash3(&combcomm, pk, msg);
  112. if shine::commit(&z) == combcomm + c * pk {
  113. return Some((combcomm, z));
  114. }
  115. None
  116. }
  117. pub fn combine(
  118. pk: &PubKey,
  119. t: u32,
  120. coalition: &[u32],
  121. msg: &[u8],
  122. commitments: &[RistrettoPoint],
  123. sigshares: &[Scalar],
  124. ) -> Option<Signature> {
  125. let polys = lagrange_polys(coalition);
  126. combine_polys(pk, t, coalition, &polys, msg, commitments, sigshares)
  127. }
  128. pub fn verify(pk: &PubKey, msg: &[u8], sig: &Signature) -> bool {
  129. let c = hash3(&sig.0, pk, msg);
  130. shine::commit(&sig.1) == sig.0 + c * pk
  131. }
  132. #[test]
  133. pub fn test_arctic_good() {
  134. let n = 7u32;
  135. let t = 4u32;
  136. let (pubkey, seckeys) = keygen(n, t);
  137. let coalition = (1..=n).collect::<Vec<u32>>();
  138. let msg = b"A message to be signed";
  139. let commits: Vec<RistrettoPoint> = seckeys
  140. .iter()
  141. .map(|key| sign1(key, &coalition, msg))
  142. .collect();
  143. let sigshares: Vec<Scalar> = seckeys
  144. .iter()
  145. .map(|key| sign2(&pubkey, key, &coalition, msg, &commits).unwrap())
  146. .collect();
  147. let sig = combine(&pubkey, t, &coalition, msg, &commits, &sigshares).unwrap();
  148. assert!(verify(&pubkey, msg, &sig));
  149. }
  150. #[test]
  151. #[should_panic]
  152. pub fn test_arctic_bad1() {
  153. let n = 7u32;
  154. let t = 4u32;
  155. let (pubkey, seckeys) = keygen(n, t);
  156. let coalition = (1..=n).collect::<Vec<u32>>();
  157. let msg = b"A message to be signed";
  158. let mut commits: Vec<RistrettoPoint> = seckeys
  159. .iter()
  160. .map(|key| sign1(key, &coalition, msg))
  161. .collect();
  162. // Modify player 1's commitment
  163. let v = commits[1];
  164. commits[0] += v;
  165. // Player 1 should abort because its own commit is no longer in the
  166. // list
  167. sign2(&pubkey, &seckeys[0], &coalition, msg, &commits);
  168. }
  169. #[test]
  170. pub fn test_arctic_bad2() {
  171. let n = 7u32;
  172. let t = 4u32;
  173. let (pubkey, seckeys) = keygen(n, t);
  174. let coalition = (1..=n).collect::<Vec<u32>>();
  175. let msg = b"A message to be signed";
  176. let mut commits: Vec<RistrettoPoint> = seckeys
  177. .iter()
  178. .map(|key| sign1(key, &coalition, msg))
  179. .collect();
  180. // Modify player 1's commitment
  181. let v = commits[1];
  182. commits[0] += v;
  183. // Player 2 should return None because the commitments are
  184. // inconsistent
  185. assert_eq!(sign2(&pubkey, &seckeys[1], &coalition, msg, &commits), None);
  186. }
  187. #[test]
  188. pub fn test_arctic_bad3() {
  189. let n = 7u32;
  190. let t = 4u32;
  191. let (pubkey, seckeys) = keygen(n, t);
  192. let coalition = (1..=n).collect::<Vec<u32>>();
  193. let msg = b"A message to be signed";
  194. let commits: Vec<RistrettoPoint> = seckeys
  195. .iter()
  196. .map(|key| sign1(key, &coalition, msg))
  197. .collect();
  198. let mut sigshares: Vec<Scalar> = seckeys
  199. .iter()
  200. .map(|key| sign2(&pubkey, key, &coalition, msg, &commits).unwrap())
  201. .collect();
  202. // Modify player 0's signature share
  203. sigshares[0] += Scalar::one();
  204. // Combine should return None because the shares don't combine to a
  205. // valid signature
  206. assert_eq!(
  207. combine(&pubkey, t, &coalition, msg, &commits, &sigshares),
  208. None
  209. );
  210. }
  211. #[test]
  212. pub fn test_arctic_bad4() {
  213. let n = 7u32;
  214. let t = 4u32;
  215. let (pubkey, seckeys) = keygen(n, t);
  216. let coalition = (1..=n).collect::<Vec<u32>>();
  217. let msg = b"A message to be signed";
  218. let commits: Vec<RistrettoPoint> = seckeys
  219. .iter()
  220. .map(|key| sign1(key, &coalition, msg))
  221. .collect();
  222. let sigshares: Vec<Scalar> = seckeys
  223. .iter()
  224. .map(|key| sign2(&pubkey, key, &coalition, msg, &commits).unwrap())
  225. .collect();
  226. // Modify the message
  227. let msg2 = b"A message to be signef";
  228. assert_eq!(
  229. combine(&pubkey, t, &coalition, msg2, &commits, &sigshares),
  230. None
  231. );
  232. }