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;
16exports.pruneBuffer = pruneBuffer;
17
18
19function cratePrvKey() {
20 return crypto.randomBytes(32);
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 verify(msg, sig, A) {
79 // Check parameters
80 if (typeof sig != "object") return false;
81 if (!Array.isArray(sig.R8)) return false;
82 if (sig.R8.length!= 2) return false;
83 if (!babyJub.inCurve(sig.R8)) return false;
84 if (!Array.isArray(A)) return false;
85 if (A.length!= 2) return false;
86 if (!babyJub.inCurve(A)) return false;
87 if (sig.S>= babyJub.subOrder) return false;
88
89 const R8p = babyJub.packPoint(sig.R8);
90 const Ap = babyJub.packPoint(A);
91 const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
92 const hm = bigInt.leBuff2int(hmBuff);
93
94 const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
95 let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
96 Pright = babyJub.addPoint(sig.R8, Pright);
97
98 if (!Pleft[0].equals(Pright[0])) return false;
99 if (!Pleft[1].equals(Pright[1])) return false;
100 return true;
101}
102
103function verifyMiMC(msg, sig, A) {
104 // Check parameters
105 if (typeof sig != "object") return false;
106 if (!Array.isArray(sig.R8)) return false;
107 if (sig.R8.length!= 2) return false;
108 if (!babyJub.inCurve(sig.R8)) return false;
109 if (!Array.isArray(A)) return false;
110 if (A.length!= 2) return false;
111 if (!babyJub.inCurve(A)) return false;
112 if (sig.S>= babyJub.subOrder) return false;
113
114 const hm = mimc7.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
115
116 const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
117 let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
118 Pright = babyJub.addPoint(sig.R8, Pright);
119
120 if (!Pleft[0].equals(Pright[0])) return false;
121 if (!Pleft[1].equals(Pright[1])) return false;
122 return true;
123}
124
125function packSignature(sig) {
126 const R8p = babyJub.packPoint(sig.R8);
127 const Sp = bigInt.leInt2Buff(sig.S, 32);
128 return Buffer.concat([R8p, Sp]);
129}
130
131function unpackSignature(sigBuff) {
132 return {
133 R8: babyJub.unpackPoint(sigBuff.slice(0,32)),
134 S: bigInt.leBuff2int(sigBuff.slice(32,64))
135 };
136}
137
138