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