arctic.rs 7.3 KB

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