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