circomlib/src/eddsa.js
src/eddsa.jsRaw
1const createBlakeHash = require("blake-hash");
2const Scalar = require("ffjavascript").Scalar;
3const F1Field = require("ffjavascript").F1Field;
4const babyJub = require("./babyjub");
5const utils = require("ffjavascript").utils;
6const pedersenHash = require("./pedersenHash").hash;
7const mimc7 = require("./mimc7");
8const poseidon = require("./poseidon.js");
9const mimcsponge = require("./mimcsponge");
10
11
12exports.prv2pub= prv2pub;
13exports.sign = sign;
14exports.signMiMC = signMiMC;
15exports.signPoseidon = signPoseidon;
16exports.signMiMCSponge = signMiMCSponge;
17exports.verify = verify;
18exports.verifyMiMC = verifyMiMC;
19exports.verifyPoseidon = verifyPoseidon;
20exports.verifyMiMCSponge = verifyMiMCSponge;
21exports.packSignature = packSignature;
22exports.unpackSignature = unpackSignature;
23exports.pruneBuffer = pruneBuffer;
24
25
26function pruneBuffer(_buff) {
27 const buff = Buffer.from(_buff);
28 buff[0] = buff[0] & 0xF8;
29 buff[31] = buff[31] & 0x7F;
30 buff[31] = buff[31] | 0x40;
31 return buff;
32}
33
34function prv2pub(prv) {
35 const sBuff = pruneBuffer(createBlakeHash("blake512").update(prv).digest().slice(0,32));
36 let s = utils.leBuff2int(sBuff);
37 const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s,3));
38 return A;
39}
40
41function sign(prv, msg) {
42 const h1 = createBlakeHash("blake512").update(prv).digest();
43 const sBuff = pruneBuffer(h1.slice(0,32));
44 const s = utils.leBuff2int(sBuff);
45 const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s, 3));
46
47 const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msg])).digest();
48 let r = utils.leBuff2int(rBuff);
49 const Fr = new F1Field(babyJub.subOrder);
50 r = Fr.e(r);
51 const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
52 const R8p = babyJub.packPoint(R8);
53 const Ap = babyJub.packPoint(A);
54 const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
55 const hm = utils.leBuff2int(hmBuff);
56 const S = Fr.add(r , Fr.mul(hm, s));
57 return {
58 R8: R8,
59 S: S
60 };
61}
62
63function signMiMC(prv, msg) {
64 const h1 = createBlakeHash("blake512").update(prv).digest();
65 const sBuff = pruneBuffer(h1.slice(0,32));
66 const s = utils.leBuff2int(sBuff);
67 const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s, 3));
68
69 const msgBuff = utils.leInt2Buff(msg, 32);
70 const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
71 let r = utils.leBuff2int(rBuff);
72 const Fr = new F1Field(babyJub.subOrder);
73 r = Fr.e(r);
74 const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
75 const hm = mimc7.multiHash([R8[0], R8[1], A[0], A[1], msg]);
76 const S = Fr.add(r , Fr.mul(hm, s));
77 return {
78 R8: R8,
79 S: S
80 };
81}
82
83function signMiMCSponge(prv, msg) {
84 const h1 = createBlakeHash("blake512").update(prv).digest();
85 const sBuff = pruneBuffer(h1.slice(0,32));
86 const s = utils.leBuff2int(sBuff);
87 const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s, 3));
88
89 const msgBuff = utils.leInt2Buff(msg, 32);
90 const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
91 let r = utils.leBuff2int(rBuff);
92 const Fr = new F1Field(babyJub.subOrder);
93 r = Fr.e(r);
94 const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
95 const hm = mimcsponge.multiHash([R8[0], R8[1], A[0], A[1], msg]);
96 const S = Fr.add(r , Fr.mul(hm, s));
97 return {
98 R8: R8,
99 S: S
100 };
101}
102
103function signPoseidon(prv, msg) {
104 const h1 = createBlakeHash("blake512").update(prv).digest();
105 const sBuff = pruneBuffer(h1.slice(0,32));
106 const s = utils.leBuff2int(sBuff);
107 const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s, 3));
108
109 const msgBuff = utils.leInt2Buff(msg, 32);
110 const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
111 let r = utils.leBuff2int(rBuff);
112 const Fr = new F1Field(babyJub.subOrder);
113 r = Fr.e(r);
114 const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
115 const hm = poseidon([R8[0], R8[1], A[0], A[1], msg]);
116 const S = Fr.add(r , Fr.mul(hm, s));
117 return {
118 R8: R8,
119 S: S
120 };
121}
122
123function verify(msg, sig, A) {
124 // Check parameters
125 if (typeof sig != "object") return false;
126 if (!Array.isArray(sig.R8)) return false;
127 if (sig.R8.length!= 2) return false;
128 if (!babyJub.inCurve(sig.R8)) return false;
129 if (!Array.isArray(A)) return false;
130 if (A.length!= 2) return false;
131 if (!babyJub.inCurve(A)) return false;
132 if (sig.S>= babyJub.subOrder) return false;
133
134 const R8p = babyJub.packPoint(sig.R8);
135 const Ap = babyJub.packPoint(A);
136 const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
137 const hm = utils.leBuff2int(hmBuff);
138
139 const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
140 let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm,8));
141 Pright = babyJub.addPoint(sig.R8, Pright);
142
143 if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
144 if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
145 return true;
146}
147
148function verifyMiMC(msg, sig, A) {
149 // Check parameters
150 if (typeof sig != "object") return false;
151 if (!Array.isArray(sig.R8)) return false;
152 if (sig.R8.length!= 2) return false;
153 if (!babyJub.inCurve(sig.R8)) return false;
154 if (!Array.isArray(A)) return false;
155 if (A.length!= 2) return false;
156 if (!babyJub.inCurve(A)) return false;
157 if (sig.S>= babyJub.subOrder) return false;
158
159 const hm = mimc7.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
160
161 const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
162 let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm, 8));
163 Pright = babyJub.addPoint(sig.R8, Pright);
164
165 if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
166 if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
167 return true;
168}
169
170
171function verifyPoseidon(msg, sig, A) {
172 // Check parameters
173 if (typeof sig != "object") return false;
174 if (!Array.isArray(sig.R8)) return false;
175 if (sig.R8.length!= 2) return false;
176 if (!babyJub.inCurve(sig.R8)) return false;
177 if (!Array.isArray(A)) return false;
178 if (A.length!= 2) return false;
179 if (!babyJub.inCurve(A)) return false;
180 if (sig.S>= babyJub.subOrder) return false;
181
182 const hm = poseidon([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
183
184 const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
185 let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm, 8));
186 Pright = babyJub.addPoint(sig.R8, Pright);
187
188 if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
189 if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
190 return true;
191}
192
193function verifyMiMCSponge(msg, sig, A) {
194 // Check parameters
195 if (typeof sig != "object") return false;
196 if (!Array.isArray(sig.R8)) return false;
197 if (sig.R8.length!= 2) return false;
198 if (!babyJub.inCurve(sig.R8)) return false;
199 if (!Array.isArray(A)) return false;
200 if (A.length!= 2) return false;
201 if (!babyJub.inCurve(A)) return false;
202 if (sig.S>= babyJub.subOrder) return false;
203
204 const hm = mimcsponge.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
205
206 const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
207 let Pright = babyJub.mulPointEscalar(A, hm.times(bigInt("8")));
208 Pright = babyJub.addPoint(sig.R8, Pright);
209
210 if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
211 if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
212 return true;
213}
214
215function packSignature(sig) {
216 const R8p = babyJub.packPoint(sig.R8);
217 const Sp = utils.leInt2Buff(sig.S, 32);
218 return Buffer.concat([R8p, Sp]);
219}
220
221function unpackSignature(sigBuff) {
222 return {
223 R8: babyJub.unpackPoint(sigBuff.slice(0,32)),
224 S: utils.leBuff2int(sigBuff.slice(32,64))
225 };
226}
227
228