arctic.rs 7.5 KB

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