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