arctic.rs 7.8 KB

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