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