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 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