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 mimcsponge = require("./mimcsponge");
7
8exports.prv2pub= prv2pub;
9exports.sign = sign;
10exports.signMiMC = signMiMC;
11exports.signMiMCSponge = signMiMCSponge;
12exports.verify = verify;
13exports.verifyMiMC = verifyMiMC;
14exports.verifyMiMCSponge = verifyMiMCSponge;
15exports.packSignature = packSignature;
16exports.unpackSignature = unpackSignature;
17exports.pruneBuffer = pruneBuffer;
18
19
20function pruneBuffer(_buff) {
21 const buff = Buffer.from(_buff);
22 buff[0] = buff[0] & 0xF8;
23 buff[31] = buff[31] & 0x7F;
24 buff[31] = buff[31] | 0x40;
25 return buff;
26}
27
28function prv2pub(prv) {
29 const sBuff = pruneBuffer(createBlakeHash("blake512").update(prv).digest().slice(0,32));
30 let s = bigInt.leBuff2int(sBuff);
31 const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
32 return A;
33}
34
35function sign(prv, msg) {
36 const h1 = createBlakeHash("blake512").update(prv).digest();
37 const sBuff = pruneBuffer(h1.slice(0,32));
38 const s = bigInt.leBuff2int(sBuff);
39 const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
40
41 const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msg])).digest();
42 let r = bigInt.leBuff2int(rBuff);
43 r = r.mod(babyJub.subOrder);
44 const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
45 const R8p = babyJub.packPoint(R8);
46 const Ap = babyJub.packPoint(A);
47 const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
48 const hm = bigInt.leBuff2int(hmBuff);
49 const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
50 return {
51 R8: R8,
52 S: S
53 };
54}
55
56function signMiMC(prv, msg) {
57 const h1 = createBlakeHash("blake512").update(prv).digest();
58 const sBuff = pruneBuffer(h1.slice(0,32));
59 const s = bigInt.leBuff2int(sBuff);
60 const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
61
62 const msgBuff = bigInt.leInt2Buff(msg, 32);
63 const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
64 let r = bigInt.leBuff2int(rBuff);
65 r = r.mod(babyJub.subOrder);
66 const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
67 const hm = mimc7.multiHash([R8[0], R8[1], A[0], A[1], msg]);
68 const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
69 return {
70 R8: R8,
71 S: S
72 };
73}
74
75function signMiMCSponge(prv, msg) {
76 const h1 = createBlakeHash("blake512").update(prv).digest();
77 const sBuff = pruneBuffer(h1.slice(0,32));
78 const s = bigInt.leBuff2int(sBuff);
79 const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
80
81 const msgBuff = bigInt.leInt2Buff(msg, 32);
82 const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
83 let r = bigInt.leBuff2int(rBuff);
84 r = r.mod(babyJub.subOrder);
85 const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
86 const hm = mimcsponge.multiHash([R8[0], R8[1], A[0], A[1], msg]);
87 const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
88 return {
89 R8: R8,
90 S: S
91 };
92}
93
94function verify(msg, sig, A) {
95 // Check parameters
96 if (typeof sig != "object") return false;
97 if (!Array.isArray(sig.R8)) return false;
98 if (sig.R8.length!= 2) return false;
99 if (!babyJub.inCurve(sig.R8)) return false;
100 if (!Array.isArray(A)) return false;
101 if (A.length!= 2) return false;
102 if (!babyJub.inCurve(A)) return false;
103 if (sig.S>= babyJub.subOrder) return false;
104
105 const R8p = babyJub.packPoint(sig.R8);
106 const Ap = babyJub.packPoint(A);
107 const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
108 const hm = bigInt.leBuff2int(hmBuff);
109
110 const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
111 let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
112 Pright = babyJub.addPoint(sig.R8, Pright);
113
114 if (!Pleft[0].equals(Pright[0])) return false;
115 if (!Pleft[1].equals(Pright[1])) return false;
116 return true;
117}
118
119function verifyMiMC(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 hm = mimc7.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
131
132 const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
133 let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
134 Pright = babyJub.addPoint(sig.R8, Pright);
135
136 if (!Pleft[0].equals(Pright[0])) return false;
137 if (!Pleft[1].equals(Pright[1])) return false;
138 return true;
139}
140
141function verifyMiMCSponge(msg, sig, A) {
142 // Check parameters
143 if (typeof sig != "object") return false;
144 if (!Array.isArray(sig.R8)) return false;
145 if (sig.R8.length!= 2) return false;
146 if (!babyJub.inCurve(sig.R8)) return false;
147 if (!Array.isArray(A)) return false;
148 if (A.length!= 2) return false;
149 if (!babyJub.inCurve(A)) return false;
150 if (sig.S>= babyJub.subOrder) return false;
151
152 const hm = mimcsponge.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
153
154 const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
155 let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
156 Pright = babyJub.addPoint(sig.R8, Pright);
157
158 if (!Pleft[0].equals(Pright[0])) return false;
159 if (!Pleft[1].equals(Pright[1])) return false;
160 return true;
161}
162
163function packSignature(sig) {
164 const R8p = babyJub.packPoint(sig.R8);
165 const Sp = bigInt.leInt2Buff(sig.S, 32);
166 return Buffer.concat([R8p, Sp]);
167}
168
169function unpackSignature(sigBuff) {
170 return {
171 R8: babyJub.unpackPoint(sigBuff.slice(0,32)),
172 S: bigInt.leBuff2int(sigBuff.slice(32,64))
173 };
174}
175
176