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 hash = poseidon.createHash(6, 8, 57);
116    const hm = hash([R8[0], R8[1], A[0], A[1], msg]);
117    const S = Fr.add(r , Fr.mul(hm, s));
118    return {
119        R8: R8,
120        S: S
121    };
122}
123
124function verify(msg, sig, A) {
125    // Check parameters
126    if (typeof sig != "object") return false;
127    if (!Array.isArray(sig.R8)) return false;
128    if (sig.R8.length!= 2) return false;
129    if (!babyJub.inCurve(sig.R8)) return false;
130    if (!Array.isArray(A)) return false;
131    if (A.length!= 2) return false;
132    if (!babyJub.inCurve(A)) return false;
133    if (sig.S>= babyJub.subOrder) return false;
134
135    const R8p = babyJub.packPoint(sig.R8);
136    const Ap = babyJub.packPoint(A);
137    const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
138    const hm = utils.leBuff2int(hmBuff);
139
140    const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
141    let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm,8));
142    Pright = babyJub.addPoint(sig.R8, Pright);
143
144    if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
145    if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
146    return true;
147}
148
149function verifyMiMC(msg, sig, A) {
150    // Check parameters
151    if (typeof sig != "object") return false;
152    if (!Array.isArray(sig.R8)) return false;
153    if (sig.R8.length!= 2) return false;
154    if (!babyJub.inCurve(sig.R8)) return false;
155    if (!Array.isArray(A)) return false;
156    if (A.length!= 2) return false;
157    if (!babyJub.inCurve(A)) return false;
158    if (sig.S>= babyJub.subOrder) return false;
159
160    const hm = mimc7.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
161
162    const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
163    let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm, 8));
164    Pright = babyJub.addPoint(sig.R8, Pright);
165
166    if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
167    if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
168    return true;
169}
170
171
172function verifyPoseidon(msg, sig, A) {
173    // Check parameters
174    if (typeof sig != "object") return false;
175    if (!Array.isArray(sig.R8)) return false;
176    if (sig.R8.length!= 2) return false;
177    if (!babyJub.inCurve(sig.R8)) return false;
178    if (!Array.isArray(A)) return false;
179    if (A.length!= 2) return false;
180    if (!babyJub.inCurve(A)) return false;
181    if (sig.S>= babyJub.subOrder) return false;
182
183    const hash = poseidon.createHash(6, 8, 57);
184    const hm = hash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
185
186    const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
187    let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm, 8));
188    Pright = babyJub.addPoint(sig.R8, Pright);
189
190    if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
191    if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
192    return true;
193}
194
195function verifyMiMCSponge(msg, sig, A) {
196    // Check parameters
197    if (typeof sig != "object") return false;
198    if (!Array.isArray(sig.R8)) return false;
199    if (sig.R8.length!= 2) return false;
200    if (!babyJub.inCurve(sig.R8)) return false;
201    if (!Array.isArray(A)) return false;
202    if (A.length!= 2) return false;
203    if (!babyJub.inCurve(A)) return false;
204    if (sig.S>= babyJub.subOrder) return false;
205
206    const hm = mimcsponge.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
207
208    const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
209    let Pright = babyJub.mulPointEscalar(A, hm.times(bigInt("8")));
210    Pright = babyJub.addPoint(sig.R8, Pright);
211
212    if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
213    if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
214    return true;
215}
216
217function packSignature(sig) {
218    const R8p = babyJub.packPoint(sig.R8);
219    const Sp = utils.leInt2Buff(sig.S, 32);
220    return Buffer.concat([R8p, Sp]);
221}
222
223function unpackSignature(sigBuff) {
224    return {
225        R8: babyJub.unpackPoint(sigBuff.slice(0,32)),
226        S: utils.leBuff2int(sigBuff.slice(32,64))
227    };
228}
229
230