arctic.rs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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 + 1 {
  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. }