You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

291 lines
8.6 KiB

  1. //! Demonstrates how to use Nova to produce a recursive proof of an ECDSA signature.
  2. //! This example proves the knowledge of a sequence of ECDSA signatures with different public keys on different messages,
  3. //! but the example can be adapted to other settings (e.g., proving the validity of the certificate chain with a well-known root public key)
  4. //! Scheme borrowed from https://github.com/filecoin-project/bellperson-gadgets/blob/main/src/eddsa.rs
  5. //! Sign using G1 curve, and prove using G2 curve.
  6. use core::ops::{Add, AddAssign, Mul, MulAssign, Neg};
  7. use ff::{
  8. derive::byteorder::{ByteOrder, LittleEndian},
  9. Field, PrimeField, PrimeFieldBits,
  10. };
  11. use nova_snark::{
  12. traits::{circuit::TrivialTestCircuit, Group as Nova_Group},
  13. CompressedSNARK, PublicParams, RecursiveSNARK,
  14. };
  15. use num_bigint::BigUint;
  16. use pasta_curves::{
  17. arithmetic::CurveAffine,
  18. group::{Curve, Group},
  19. };
  20. use rand::{rngs::OsRng, RngCore};
  21. use sha3::{Digest, Sha3_512};
  22. use subtle::Choice;
  23. mod circuit;
  24. mod utils;
  25. use crate::circuit::{Coordinate, EcdsaCircuit, EcdsaSignature};
  26. use crate::utils::BitIterator;
  27. type G1 = pasta_curves::pallas::Point;
  28. type G2 = pasta_curves::vesta::Point;
  29. type S1 = nova_snark::spartan_with_ipa_pc::RelaxedR1CSSNARK<G2>;
  30. type S2 = nova_snark::spartan_with_ipa_pc::RelaxedR1CSSNARK<G1>;
  31. #[derive(Debug, Clone, Copy)]
  32. pub struct SecretKey(pub <G1 as Group>::Scalar);
  33. impl SecretKey {
  34. pub fn random(mut rng: impl RngCore) -> Self {
  35. let secret = <G1 as Group>::Scalar::random(&mut rng);
  36. Self(secret)
  37. }
  38. }
  39. #[derive(Debug, Clone, Copy)]
  40. pub struct PublicKey(pub G1);
  41. impl PublicKey {
  42. pub fn from_secret_key(s: &SecretKey) -> Self {
  43. let point = G1::generator() * s.0;
  44. Self(point)
  45. }
  46. }
  47. #[derive(Clone)]
  48. pub struct Signature {
  49. pub r: G1,
  50. pub s: <G1 as Group>::Scalar,
  51. }
  52. impl SecretKey {
  53. pub fn sign(self, c: <G1 as Group>::Scalar, mut rng: impl RngCore) -> Signature {
  54. // T
  55. let mut t = [0u8; 80];
  56. rng.fill_bytes(&mut t[..]);
  57. // h = H*(T || M)
  58. let h = Self::hash_to_scalar(b"Nova_Ecdsa_Hash", &t[..], &c.to_repr());
  59. // R = [h]G
  60. let r = G1::generator().mul(h);
  61. // s = h + c * sk
  62. let mut s = c;
  63. s.mul_assign(&self.0);
  64. s.add_assign(&h);
  65. Signature { r, s }
  66. }
  67. fn mul_bits<B: AsRef<[u64]>>(
  68. s: &<G1 as Group>::Scalar,
  69. bits: BitIterator<B>,
  70. ) -> <G1 as Group>::Scalar {
  71. let mut x = <G1 as Group>::Scalar::zero();
  72. for bit in bits {
  73. x.double();
  74. if bit {
  75. x.add_assign(s)
  76. }
  77. }
  78. x
  79. }
  80. fn to_uniform(digest: &[u8]) -> <G1 as Group>::Scalar {
  81. assert_eq!(digest.len(), 64);
  82. let mut bits: [u64; 8] = [0; 8];
  83. LittleEndian::read_u64_into(digest, &mut bits);
  84. Self::mul_bits(&<G1 as Group>::Scalar::one(), BitIterator::new(bits))
  85. }
  86. pub fn to_uniform_32(digest: &[u8]) -> <G1 as Group>::Scalar {
  87. assert_eq!(digest.len(), 32);
  88. let mut bits: [u64; 4] = [0; 4];
  89. LittleEndian::read_u64_into(digest, &mut bits);
  90. Self::mul_bits(&<G1 as Group>::Scalar::one(), BitIterator::new(bits))
  91. }
  92. pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> <G1 as Group>::Scalar {
  93. let mut hasher = Sha3_512::new();
  94. hasher.input(persona);
  95. hasher.input(a);
  96. hasher.input(b);
  97. let digest = hasher.result();
  98. Self::to_uniform(digest.as_ref())
  99. }
  100. }
  101. impl PublicKey {
  102. pub fn verify(&self, c: <G1 as Group>::Scalar, signature: &Signature) -> bool {
  103. let modulus = Self::modulus_as_scalar();
  104. let order_check_pk = self.0.mul(modulus);
  105. if !order_check_pk.eq(&G1::identity()) {
  106. return false;
  107. }
  108. let order_check_r = signature.r.mul(modulus);
  109. if !order_check_r.eq(&G1::identity()) {
  110. return false;
  111. }
  112. // 0 = [-s]G + R + [c]PK
  113. self
  114. .0
  115. .mul(c)
  116. .add(&signature.r)
  117. .add(G1::generator().mul(signature.s).neg())
  118. .eq(&G1::identity())
  119. }
  120. fn modulus_as_scalar() -> <G1 as Group>::Scalar {
  121. let mut bits = <G1 as Group>::Scalar::char_le_bits().to_bitvec();
  122. let mut acc = BigUint::new(Vec::<u32>::new());
  123. while let Some(b) = bits.pop() {
  124. acc <<= 1_i32;
  125. acc += b as u8;
  126. }
  127. let modulus = acc.to_str_radix(10);
  128. <G1 as Group>::Scalar::from_str_vartime(&modulus).unwrap()
  129. }
  130. }
  131. fn main() {
  132. // In a VERY LIMITED case of messages known to be unique due to application level
  133. // and being less than the group order when interpreted as integer, one can sign
  134. // the message directly without hashing
  135. pub const MAX_MESSAGE_LEN: usize = 16;
  136. assert!(MAX_MESSAGE_LEN * 8 <= <G1 as Group>::Scalar::CAPACITY as usize);
  137. // produce public parameters
  138. println!("Generating public parameters...");
  139. let circuit_primary = EcdsaCircuit::<<G2 as Nova_Group>::Scalar> {
  140. r: Coordinate::new(
  141. <G2 as Nova_Group>::Scalar::zero(),
  142. <G2 as Nova_Group>::Scalar::zero(),
  143. ),
  144. g: Coordinate::new(
  145. <G2 as Nova_Group>::Scalar::zero(),
  146. <G2 as Nova_Group>::Scalar::zero(),
  147. ),
  148. pk: Coordinate::new(
  149. <G2 as Nova_Group>::Scalar::zero(),
  150. <G2 as Nova_Group>::Scalar::zero(),
  151. ),
  152. c: <G2 as Nova_Group>::Scalar::zero(),
  153. s: <G2 as Nova_Group>::Scalar::zero(),
  154. c_bits: vec![Choice::from(0u8); 256],
  155. s_bits: vec![Choice::from(0u8); 256],
  156. };
  157. let circuit_secondary = TrivialTestCircuit::default();
  158. let pp = PublicParams::<
  159. G2,
  160. G1,
  161. EcdsaCircuit<<G2 as Group>::Scalar>,
  162. TrivialTestCircuit<<G1 as Group>::Scalar>,
  163. >::setup(circuit_primary, circuit_secondary.clone());
  164. // produce non-deterministic advice
  165. println!("Generating non-deterministic advice...");
  166. let num_steps = 3;
  167. let signatures = || {
  168. let mut signatures = Vec::new();
  169. for i in 0..num_steps {
  170. let sk = SecretKey::random(&mut OsRng);
  171. let pk = PublicKey::from_secret_key(&sk);
  172. let message = format!("MESSAGE{}", i).as_bytes().to_owned();
  173. assert!(message.len() <= MAX_MESSAGE_LEN);
  174. let mut digest: Vec<u8> = message.to_vec();
  175. for _ in 0..(32 - message.len() as u32) {
  176. digest.extend(&[0u8; 1]);
  177. }
  178. let c = SecretKey::to_uniform_32(digest.as_ref());
  179. let signature_primary = sk.sign(c, &mut OsRng);
  180. let result = pk.verify(c, &signature_primary);
  181. assert!(result);
  182. // Affine coordinates guaranteed to be on the curve
  183. let rxy = signature_primary.r.to_affine().coordinates().unwrap();
  184. let gxy = G1::generator().to_affine().coordinates().unwrap();
  185. let pkxy = pk.0.to_affine().coordinates().unwrap();
  186. let s = signature_primary.s;
  187. signatures.push(EcdsaSignature::<
  188. <G1 as Nova_Group>::Base,
  189. <G1 as Nova_Group>::Scalar,
  190. >::new(
  191. Coordinate::<<G1 as Nova_Group>::Base>::new(*pkxy.x(), *pkxy.y()),
  192. Coordinate::<<G1 as Nova_Group>::Base>::new(*rxy.x(), *rxy.y()),
  193. s,
  194. c,
  195. Coordinate::<<G1 as Nova_Group>::Base>::new(*gxy.x(), *gxy.y()),
  196. ));
  197. }
  198. signatures
  199. };
  200. let (z0_primary, circuits_primary) = EcdsaCircuit::<<G2 as Nova_Group>::Scalar>::new::<
  201. <G1 as Nova_Group>::Base,
  202. <G1 as Nova_Group>::Scalar,
  203. >(num_steps, &signatures());
  204. // Secondary circuit
  205. let z0_secondary = vec![<G1 as Group>::Scalar::zero()];
  206. // produce a recursive SNARK
  207. println!("Generating a RecursiveSNARK...");
  208. type C1 = EcdsaCircuit<<G2 as Nova_Group>::Scalar>;
  209. type C2 = TrivialTestCircuit<<G1 as Nova_Group>::Scalar>;
  210. let mut recursive_snark: Option<RecursiveSNARK<G2, G1, C1, C2>> = None;
  211. for (i, circuit_primary) in circuits_primary.iter().take(num_steps).enumerate() {
  212. let result = RecursiveSNARK::prove_step(
  213. &pp,
  214. recursive_snark,
  215. circuit_primary.clone(),
  216. circuit_secondary.clone(),
  217. z0_primary.clone(),
  218. z0_secondary.clone(),
  219. );
  220. assert!(result.is_ok());
  221. println!("RecursiveSNARK::prove_step {}: {:?}", i, result.is_ok());
  222. recursive_snark = Some(result.unwrap());
  223. }
  224. assert!(recursive_snark.is_some());
  225. let recursive_snark = recursive_snark.unwrap();
  226. // verify the recursive SNARK
  227. println!("Verifying the RecursiveSNARK...");
  228. let res = recursive_snark.verify(&pp, num_steps, z0_primary.clone(), z0_secondary.clone());
  229. println!("RecursiveSNARK::verify: {:?}", res.is_ok());
  230. assert!(res.is_ok());
  231. // produce a compressed SNARK
  232. println!("Generating a CompressedSNARK...");
  233. let res = CompressedSNARK::<_, _, _, _, S1, S2>::prove(&pp, &recursive_snark);
  234. println!("CompressedSNARK::prove: {:?}", res.is_ok());
  235. assert!(res.is_ok());
  236. let compressed_snark = res.unwrap();
  237. // verify the compressed SNARK
  238. println!("Verifying a CompressedSNARK...");
  239. let res = compressed_snark.verify(&pp, num_steps, z0_primary, z0_secondary);
  240. println!("CompressedSNARK::verify: {:?}", res.is_ok());
  241. assert!(res.is_ok());
  242. }