akosba / jsnark

A Java library for zk-SNARK circuits
MIT License
207 stars 85 forks source link

Computing scalar multiplication using a negated scalar, on the Elliptic Curve #22

Closed hasinitg closed 4 years ago

hasinitg commented 4 years ago

Hi @akosba,

I am using the arithmetic operations on the elliptic curve provided in the ECDHKeyExchange gadget in jsnark, in order to implement a circuit which computes some linear operations on Elgamal encryption in the exponent, carried out in the elliptic curve domain.

Out of the three basic arithmetic operations on elliptic curves (i.e. addition of two points, multiplication of a point by a scalar and negation of a point), ECDHKeyExchange gadget only uses the first two operations. In my circuit, given a positive scalar 'a' (which is a secret input to the circuit) and a point 'P' (which is a public input to the circuit), I need to compute (-a).P inside the circuit (i.e. the result of multiplying 'P' by negated 'a').

Could you please advice what is the recommended way to do this in jsnark? Is it fine to first compute the scalar multiplication a.P and then negate the resulting point? Or, should I first negate the scalar, and then perform scalar multiplication? I followed the first approach, by introducing a 'negateAffinePoint' function as below, because I am not sure how to do it using the latter approach in jsnark. I would appreciate a lot your insight on this.

AffinePoint negateAffinePoint(AffinePoint p){ return new AffinePoint(p.getX(), p.getY().mul(-1)); }

Thank you very much.

akosba commented 4 years ago

Hi @hasinitg,

Could you please advice what is the recommended way to do this in jsnark? Is it fine to first compute the scalar multiplication a.P and then negate the resulting point? Or, should I first negate the scalar, and then perform scalar multiplication? I followed the first approach, by introducing a 'negateAffinePoint' function as below, because I am not sure how to do it using the latter approach in jsnark. I would appreciate a lot your insight on this.

For the second method, negating the scalar using the same way in your first method won't work as expected, i.e., if you use .mul(-1), it won't work correctly for the second case.) In the second case, you have to subtract the scalar from the order of the curve (or the order of the subgroup, but in this type of curves, I recall that the scalar or the secret keys in general are selected to be higher than the subgroup order, so the order of the curve should work). You will find these constants documented in the ECDHKeyExchange gadget. You have to be sure though before doing the subtraction that a is smaller. 

In terms of efficiency, the first method seems to be a better candidate, because if you already have the bits of a, you can reuse them directly. However, if you use the second, you will have to subtract and then extract the bits, which will add ~250 constraints.

By the way, as a suggestion, there are also other SNARK friendly curves that were proposed by others after the one I had in jsnark, e.g., https://z.cash/technology/jubjub/. You could also look into those, as they will be more optimized and possibly implemented for other functionalities other than key exchange.

hasinitg commented 4 years ago

Hi @akosba

Thank you very much for your reply. I appreciate it a lot (I am sorry about the delay in reply, as I was going through a transition period). Thank you for clarifying the pros and cons of the two approaches for obtaining the negation of a scalar multiplication. I also implemented approach 1, as approach 2 involves more constraints, as you have pointed out as well.

Thank you for pointing out jubjub. I would prefer to continue using jsnark, as I have been using it for implementation of the other circuits as well.

Thank you.