arctic.rs 7.4 KB

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