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");
6
7exports.prv2pub= prv2pub;
8exports.sign = sign;
9exports.signMiMC = signMiMC;
10exports.verify = verify;
11exports.verifyMiMC = verifyMiMC;
12exports.packSignature = packSignature;
13exports.unpackSignature = unpackSignature;
14exports.pruneBuffer = pruneBuffer;
15
16
17function pruneBuffer(_buff) {
18 const buff = Buffer.from(_buff);
19 buff[0] = buff[0] & 0xF8;
20 buff[31] = buff[31] & 0x7F;
21 buff[31] = buff[31] | 0x40;
22 return buff;
23}
24
25function prv2pub(prv) {
26 const sBuff = pruneBuffer(createBlakeHash("blake512").update(prv).digest().slice(0,32));
27 let s = bigInt.leBuff2int(sBuff);
28 const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
29 return A;
30}
31
32function sign(prv, msg) {
33 const h1 = createBlakeHash("blake512").update(prv).digest();
34 const sBuff = pruneBuffer(h1.slice(0,32));
35 const s = bigInt.leBuff2int(sBuff);
36 const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
37
38 const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msg])).digest();
39 let r = bigInt.leBuff2int(rBuff);
40 r = r.mod(babyJub.subOrder);
41 const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
42 const R8p = babyJub.packPoint(R8);
43 const Ap = babyJub.packPoint(A);
44 const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
45 const hm = bigInt.leBuff2int(hmBuff);
46 const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
47 return {
48 R8: R8,
49 S: S
50 };
51}
52
53function signMiMC(prv, msg) {
54 const h1 = createBlakeHash("blake512").update(prv).digest();
55 const sBuff = pruneBuffer(h1.slice(0,32));
56 const s = bigInt.leBuff2int(sBuff);
57 const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
58
59 const msgBuff = bigInt.leInt2Buff(msg, 32);
60 const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
61 let r = bigInt.leBuff2int(rBuff);
62 r = r.mod(babyJub.subOrder);
63 const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
64 const hm = mimc7.multiHash([R8[0], R8[1], A[0], A[1], msg]);
65 const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
66 return {
67 R8: R8,
68 S: S
69 };
70}
71
72function verify(msg, sig, A) {
73 // Check parameters
74 if (typeof sig != "object") return false;
75 if (!Array.isArray(sig.R8)) return false;
76 if (sig.R8.length!= 2) return false;
77 if (!babyJub.inCurve(sig.R8)) return false;
78 if (!Array.isArray(A)) return false;
79 if (A.length!= 2) return false;
80 if (!babyJub.inCurve(A)) return false;
81 if (sig.S>= babyJub.subOrder) return false;
82
83 const R8p = babyJub.packPoint(sig.R8);
84 const Ap = babyJub.packPoint(A);
85 const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
86 const hm = bigInt.leBuff2int(hmBuff);
87
88 const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
89 let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
90 Pright = babyJub.addPoint(sig.R8, Pright);
91
92 if (!Pleft[0].equals(Pright[0])) return false;
93 if (!Pleft[1].equals(Pright[1])) return false;
94 return true;
95}
96
97function verifyMiMC(msg, sig, A) {
98 // Check parameters
99 if (typeof sig != "object") return false;
100 if (!Array.isArray(sig.R8)) return false;
101 if (sig.R8.length!= 2) return false;
102 if (!babyJub.inCurve(sig.R8)) return false;
103 if (!Array.isArray(A)) return false;
104 if (A.length!= 2) return false;
105 if (!babyJub.inCurve(A)) return false;
106 if (sig.S>= babyJub.subOrder) return false;
107
108 const hm = mimc7.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
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 packSignature(sig) {
120 const R8p = babyJub.packPoint(sig.R8);
121 const Sp = bigInt.leInt2Buff(sig.S, 32);
122 return Buffer.concat([R8p, Sp]);
123}
124
125function unpackSignature(sigBuff) {
126 return {
127 R8: babyJub.unpackPoint(sigBuff.slice(0,32)),
128 S: bigInt.leBuff2int(sigBuff.slice(32,64))
129 };
130}
131
132