arnaucube
arnaucube/circomlibPublic Self-hosted repository
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 poseidon = require("./poseidon.js");
  7const mimcsponge = require("./mimcsponge");
  8
  9exports.prv2pub= prv2pub;
 10exports.sign = sign;
 11exports.signMiMC = signMiMC;
 12exports.signPoseidon = signPoseidon;
 13exports.signMiMCSponge = signMiMCSponge;
 14exports.verify = verify;
 15exports.verifyMiMC = verifyMiMC;
 16exports.verifyPoseidon = verifyPoseidon;
 17exports.verifyMiMCSponge = verifyMiMCSponge;
 18exports.packSignature = packSignature;
 19exports.unpackSignature = unpackSignature;
 20exports.pruneBuffer = pruneBuffer;
 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 signMiMCSponge(prv, msg) {
 79    const h1 = createBlakeHash("blake512").update(prv).digest();
 80    const sBuff = pruneBuffer(h1.slice(0,32));
 81    const s = bigInt.leBuff2int(sBuff);
 82    const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
 83
 84    const msgBuff = bigInt.leInt2Buff(msg, 32);
 85    const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
 86    let r = bigInt.leBuff2int(rBuff);
 87    r = r.mod(babyJub.subOrder);
 88    const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
 89    const hm = mimcsponge.multiHash([R8[0], R8[1], A[0], A[1], msg]);
 90    const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
 91    return {
 92        R8: R8,
 93        S: S
 94    };
 95}
 96
 97function signPoseidon(prv, msg) {
 98    const h1 = createBlakeHash("blake512").update(prv).digest();
 99    const sBuff = pruneBuffer(h1.slice(0,32));
100    const s = bigInt.leBuff2int(sBuff);
101    const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
102
103    const msgBuff = bigInt.leInt2Buff(msg, 32);
104    const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
105    let r = bigInt.leBuff2int(rBuff);
106    r = r.mod(babyJub.subOrder);
107    const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
108    const hash = poseidon.createHash(6, 8, 57);
109    const hm = hash([R8[0], R8[1], A[0], A[1], msg]);
110    const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
111    return {
112        R8: R8,
113        S: S
114    };
115}
116
117function verify(msg, sig, A) {
118    // Check parameters
119    if (typeof sig != "object") return false;
120    if (!Array.isArray(sig.R8)) return false;
121    if (sig.R8.length!= 2) return false;
122    if (!babyJub.inCurve(sig.R8)) return false;
123    if (!Array.isArray(A)) return false;
124    if (A.length!= 2) return false;
125    if (!babyJub.inCurve(A)) return false;
126    if (sig.S>= babyJub.subOrder) return false;
127
128    const R8p = babyJub.packPoint(sig.R8);
129    const Ap = babyJub.packPoint(A);
130    const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
131    const hm = bigInt.leBuff2int(hmBuff);
132
133    const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
134    let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
135    Pright = babyJub.addPoint(sig.R8, Pright);
136
137    if (!Pleft[0].equals(Pright[0])) return false;
138    if (!Pleft[1].equals(Pright[1])) return false;
139    return true;
140}
141
142function verifyMiMC(msg, sig, A) {
143    // Check parameters
144    if (typeof sig != "object") return false;
145    if (!Array.isArray(sig.R8)) return false;
146    if (sig.R8.length!= 2) return false;
147    if (!babyJub.inCurve(sig.R8)) return false;
148    if (!Array.isArray(A)) return false;
149    if (A.length!= 2) return false;
150    if (!babyJub.inCurve(A)) return false;
151    if (sig.S>= babyJub.subOrder) return false;
152
153    const hm = mimc7.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
154
155    const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
156    let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
157    Pright = babyJub.addPoint(sig.R8, Pright);
158
159    if (!Pleft[0].equals(Pright[0])) return false;
160    if (!Pleft[1].equals(Pright[1])) return false;
161    return true;
162}
163
164
165function verifyPoseidon(msg, sig, A) {
166    // Check parameters
167    if (typeof sig != "object") return false;
168    if (!Array.isArray(sig.R8)) return false;
169    if (sig.R8.length!= 2) return false;
170    if (!babyJub.inCurve(sig.R8)) return false;
171    if (!Array.isArray(A)) return false;
172    if (A.length!= 2) return false;
173    if (!babyJub.inCurve(A)) return false;
174    if (sig.S>= babyJub.subOrder) return false;
175
176    const hash = poseidon.createHash(6, 8, 57);
177    const hm = hash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
178
179    const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
180    let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
181    Pright = babyJub.addPoint(sig.R8, Pright);
182
183    if (!Pleft[0].equals(Pright[0])) return false;
184    if (!Pleft[1].equals(Pright[1])) return false;
185    return true;
186}
187
188function verifyMiMCSponge(msg, sig, A) {
189    // Check parameters
190    if (typeof sig != "object") return false;
191    if (!Array.isArray(sig.R8)) return false;
192    if (sig.R8.length!= 2) return false;
193    if (!babyJub.inCurve(sig.R8)) return false;
194    if (!Array.isArray(A)) return false;
195    if (A.length!= 2) return false;
196    if (!babyJub.inCurve(A)) return false;
197    if (sig.S>= babyJub.subOrder) return false;
198
199    const hm = mimcsponge.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
200
201    const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
202    let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
203    Pright = babyJub.addPoint(sig.R8, Pright);
204
205    if (!Pleft[0].equals(Pright[0])) return false;
206    if (!Pleft[1].equals(Pright[1])) return false;
207    return true;
208}
209
210function packSignature(sig) {
211    const R8p = babyJub.packPoint(sig.R8);
212    const Sp = bigInt.leInt2Buff(sig.S, 32);
213    return Buffer.concat([R8p, Sp]);
214}
215
216function unpackSignature(sigBuff) {
217    return {
218        R8: babyJub.unpackPoint(sigBuff.slice(0,32)),
219        S: bigInt.leBuff2int(sigBuff.slice(32,64))
220    };
221}
222
223