Skip to content

Commit 30d612d

Browse files
authored
feat(stdlib): Implement elliptic curve primitives (#964)
Implement elliptic curve primitives
1 parent 70ede61 commit 30d612d

File tree

8 files changed

+1626
-0
lines changed

8 files changed

+1626
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "Baby Jubjub sanity checks"
3+
authors = [""]
4+
compiler_version = "0.1"
5+
6+
[dependencies]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
// Tests may be checked against https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve/tree/main/poc
2+
3+
use dep::std::ec::tecurve::affine::Curve as AffineCurve;
4+
use dep::std::ec::tecurve::affine::Point as Gaffine;
5+
use dep::std::ec::tecurve::curvegroup::Curve;
6+
use dep::std::ec::tecurve::curvegroup::Point as G;
7+
8+
use dep::std::ec::swcurve::affine::Point as SWGaffine;
9+
use dep::std::ec::swcurve::curvegroup::Point as SWG;
10+
11+
use dep::std::ec::montcurve::affine::Point as MGaffine;
12+
use dep::std::ec::montcurve::curvegroup::Point as MG;
13+
14+
fn main() {
15+
// This test only makes sense if Field is the right prime field.
16+
if 21888242871839275222246405745257275088548364400416034343698204186575808495617 == 0
17+
{
18+
// Define Baby Jubjub (ERC-2494) parameters in affine representation
19+
let bjj_affine = AffineCurve::new(168700, 168696, Gaffine::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905));
20+
21+
// Test addition
22+
let p1_affine = Gaffine::new(17777552123799933955779906779655732241715742912184938656739573121738514868268, 2626589144620713026669568689430873010625803728049924121243784502389097019475);
23+
let p2_affine = Gaffine::new(16540640123574156134436876038791482806971768689494387082833631921987005038935, 20819045374670962167435360035096875258406992893633759881276124905556507972311);
24+
25+
let p3_affine = bjj_affine.add(p1_affine, p2_affine);
26+
constrain p3_affine.eq(Gaffine::new(7916061937171219682591368294088513039687205273691143098332585753343424131937,
27+
14035240266687799601661095864649209771790948434046947201833777492504781204499));
28+
29+
// Test scalar multiplication
30+
let p4_affine = bjj_affine.mul(2, p1_affine);
31+
constrain p4_affine.eq(Gaffine::new(6890855772600357754907169075114257697580319025794532037257385534741338397365,
32+
4338620300185947561074059802482547481416142213883829469920100239455078257889));
33+
constrain p4_affine.eq(bjj_affine.bit_mul([0,1], p1_affine));
34+
35+
// Test subtraction
36+
let p5_affine = bjj_affine.subtract(p3_affine, p3_affine);
37+
constrain p5_affine.eq(Gaffine::zero());
38+
39+
// Check that these points are on the curve
40+
constrain bjj_affine.contains(bjj_affine.gen)
41+
& bjj_affine.contains(p1_affine)
42+
& bjj_affine.contains(p2_affine)
43+
& bjj_affine.contains(p3_affine)
44+
& bjj_affine.contains(p4_affine)
45+
& bjj_affine.contains(p5_affine);
46+
47+
// Test CurveGroup equivalents
48+
let bjj = bjj_affine.into_group(); // Baby Jubjub
49+
50+
let p1 = p1_affine.into_group();
51+
let p2 = p2_affine.into_group();
52+
let p3 = p3_affine.into_group();
53+
let p4 = p4_affine.into_group();
54+
let p5 = p5_affine.into_group();
55+
56+
// Test addition
57+
constrain p3.eq(bjj.add(p1, p2));
58+
59+
// Test scalar multiplication
60+
constrain p4.eq(bjj.mul(2, p1));
61+
constrain p4.eq(bjj.bit_mul([0,1], p1));
62+
63+
// Test subtraction
64+
constrain G::zero().eq(bjj.subtract(p3, p3));
65+
constrain p5.eq(G::zero());
66+
67+
// Check that these points are on the curve
68+
constrain bjj.contains(bjj.gen)
69+
& bjj.contains(p1)
70+
& bjj.contains(p2)
71+
& bjj.contains(p3)
72+
& bjj.contains(p4)
73+
& bjj.contains(p5);
74+
75+
// Test SWCurve equivalents of the above
76+
// First the affine representation
77+
let bjj_swcurve_affine = bjj_affine.into_swcurve();
78+
79+
let p1_swcurve_affine = bjj_affine.map_into_swcurve(p1_affine);
80+
let p2_swcurve_affine = bjj_affine.map_into_swcurve(p2_affine);
81+
let p3_swcurve_affine = bjj_affine.map_into_swcurve(p3_affine);
82+
let p4_swcurve_affine = bjj_affine.map_into_swcurve(p4_affine);
83+
let p5_swcurve_affine = bjj_affine.map_into_swcurve(p5_affine);
84+
85+
// Addition
86+
constrain p3_swcurve_affine.eq(
87+
bjj_swcurve_affine.add(
88+
p1_swcurve_affine,
89+
p2_swcurve_affine));
90+
91+
// Doubling
92+
constrain p4_swcurve_affine.eq(bjj_swcurve_affine.mul(2, p1_swcurve_affine));
93+
constrain p4_swcurve_affine.eq(bjj_swcurve_affine.bit_mul([0,1], p1_swcurve_affine));
94+
95+
// Subtraction
96+
constrain SWGaffine::zero().eq(bjj_swcurve_affine.subtract(p3_swcurve_affine, p3_swcurve_affine));
97+
constrain p5_swcurve_affine.eq(SWGaffine::zero());
98+
99+
// Check that these points are on the curve
100+
constrain bjj_swcurve_affine.contains(bjj_swcurve_affine.gen)
101+
& bjj_swcurve_affine.contains(p1_swcurve_affine)
102+
& bjj_swcurve_affine.contains(p2_swcurve_affine)
103+
& bjj_swcurve_affine.contains(p3_swcurve_affine)
104+
& bjj_swcurve_affine.contains(p4_swcurve_affine)
105+
& bjj_swcurve_affine.contains(p5_swcurve_affine);
106+
107+
// Then the CurveGroup representation
108+
let bjj_swcurve = bjj.into_swcurve();
109+
110+
let p1_swcurve = bjj.map_into_swcurve(p1);
111+
let p2_swcurve = bjj.map_into_swcurve(p2);
112+
let p3_swcurve = bjj.map_into_swcurve(p3);
113+
let p4_swcurve = bjj.map_into_swcurve(p4);
114+
let p5_swcurve = bjj.map_into_swcurve(p5);
115+
116+
// Addition
117+
constrain p3_swcurve.eq(
118+
bjj_swcurve.add(
119+
p1_swcurve,
120+
p2_swcurve));
121+
122+
// Doubling
123+
constrain p4_swcurve.eq(bjj_swcurve.mul(2, p1_swcurve));
124+
constrain p4_swcurve.eq(bjj_swcurve.bit_mul([0,1], p1_swcurve));
125+
126+
// Subtraction
127+
constrain SWG::zero().eq(bjj_swcurve.subtract(p3_swcurve, p3_swcurve));
128+
constrain p5_swcurve.eq(SWG::zero());
129+
130+
// Check that these points are on the curve
131+
constrain bjj_swcurve.contains(bjj_swcurve.gen)
132+
& bjj_swcurve.contains(p1_swcurve)
133+
& bjj_swcurve.contains(p2_swcurve)
134+
& bjj_swcurve.contains(p3_swcurve)
135+
& bjj_swcurve.contains(p4_swcurve)
136+
& bjj_swcurve.contains(p5_swcurve);
137+
138+
// Test MontCurve conversions
139+
// First the affine representation
140+
let bjj_montcurve_affine = bjj_affine.into_montcurve();
141+
142+
let p1_montcurve_affine = p1_affine.into_montcurve();
143+
let p2_montcurve_affine = p2_affine.into_montcurve();
144+
let p3_montcurve_affine = p3_affine.into_montcurve();
145+
let p4_montcurve_affine = p4_affine.into_montcurve();
146+
let p5_montcurve_affine = p5_affine.into_montcurve();
147+
148+
// Addition
149+
constrain p3_montcurve_affine.eq(
150+
bjj_montcurve_affine.add(
151+
p1_montcurve_affine,
152+
p2_montcurve_affine));
153+
154+
// Doubling
155+
constrain p4_montcurve_affine.eq(bjj_montcurve_affine.mul(2, p1_montcurve_affine));
156+
constrain p4_montcurve_affine.eq(bjj_montcurve_affine.bit_mul([0,1], p1_montcurve_affine));
157+
158+
// Subtraction
159+
constrain MGaffine::zero().eq(bjj_montcurve_affine.subtract(p3_montcurve_affine, p3_montcurve_affine));
160+
constrain p5_montcurve_affine.eq(MGaffine::zero());
161+
162+
// Check that these points are on the curve
163+
constrain bjj_montcurve_affine.contains(bjj_montcurve_affine.gen)
164+
& bjj_montcurve_affine.contains(p1_montcurve_affine)
165+
& bjj_montcurve_affine.contains(p2_montcurve_affine)
166+
& bjj_montcurve_affine.contains(p3_montcurve_affine)
167+
& bjj_montcurve_affine.contains(p4_montcurve_affine)
168+
& bjj_montcurve_affine.contains(p5_montcurve_affine);
169+
170+
// Then the CurveGroup representation
171+
let bjj_montcurve = bjj.into_montcurve();
172+
173+
let p1_montcurve = p1_montcurve_affine.into_group();
174+
let p2_montcurve = p2_montcurve_affine.into_group();
175+
let p3_montcurve = p3_montcurve_affine.into_group();
176+
let p4_montcurve = p4_montcurve_affine.into_group();
177+
let p5_montcurve = p5_montcurve_affine.into_group();
178+
179+
// Addition
180+
constrain p3_montcurve.eq(
181+
bjj_montcurve.add(
182+
p1_montcurve,
183+
p2_montcurve));
184+
185+
// Doubling
186+
constrain p4_montcurve.eq(bjj_montcurve.mul(2, p1_montcurve));
187+
constrain p4_montcurve.eq(bjj_montcurve.bit_mul([0,1], p1_montcurve));
188+
189+
// Subtraction
190+
constrain MG::zero().eq(bjj_montcurve.subtract(p3_montcurve, p3_montcurve));
191+
constrain p5_montcurve.eq(MG::zero());
192+
193+
// Check that these points are on the curve
194+
constrain bjj_montcurve.contains(bjj_montcurve.gen)
195+
& bjj_montcurve.contains(p1_montcurve)
196+
& bjj_montcurve.contains(p2_montcurve)
197+
& bjj_montcurve.contains(p3_montcurve)
198+
& bjj_montcurve.contains(p4_montcurve)
199+
& bjj_montcurve.contains(p5_montcurve);
200+
201+
// Elligator 2 map-to-curve
202+
let ell2_pt_map = bjj_affine.elligator2_map(27);
203+
204+
constrain ell2_pt_map.eq(MGaffine::new(7972459279704486422145701269802978968072470631857513331988813812334797879121, 8142420778878030219043334189293412482212146646099536952861607542822144507872).into_tecurve());
205+
206+
// SWU map-to-curve
207+
let swu_pt_map = bjj_affine.swu_map(5,27);
208+
209+
constrain swu_pt_map.eq(bjj_affine.map_from_swcurve(SWGaffine::new(2162719247815120009132293839392097468339661471129795280520343931405114293888, 5341392251743377373758788728206293080122949448990104760111875914082289313973)));
210+
}
211+
}

0 commit comments

Comments
 (0)