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");
  7
  8exports.prv2pub= prv2pub;
  9exports.sign = sign;
 10exports.signMiMC = signMiMC;
 11exports.signPoseidon = signPoseidon;
 12exports.verify = verify;
 13exports.verifyMiMC = verifyMiMC;
 14exports.verifyPoseidon = verifyPoseidon;
 15exports.packSignature = packSignature;
 16exports.unpackSignature = unpackSignature;
 17exports.pruneBuffer = pruneBuffer;
 18
 19
 20function pruneBuffer(_buff) {
 21    const buff = Buffer.from(_buff);
 22    buff[0] = buff[0] & 0xF8;
 23    buff[31] = buff[31] & 0x7F;
 24    buff[31] = buff[31] | 0x40;
 25    return buff;
 26}
 27
 28function prv2pub(prv) {
 29    const sBuff = pruneBuffer(createBlakeHash("blake512").update(prv).digest().slice(0,32));
 30    let s = bigInt.leBuff2int(sBuff);
 31    const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
 32    return A;
 33}
 34
 35function sign(prv, msg) {
 36    const h1 = createBlakeHash("blake512").update(prv).digest();
 37    const sBuff = pruneBuffer(h1.slice(0,32));
 38    const s = bigInt.leBuff2int(sBuff);
 39    const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
 40
 41    const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msg])).digest();
 42    let r = bigInt.leBuff2int(rBuff);
 43    r = r.mod(babyJub.subOrder);
 44    const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
 45    const R8p = babyJub.packPoint(R8);
 46    const Ap = babyJub.packPoint(A);
 47    const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
 48    const hm = bigInt.leBuff2int(hmBuff);
 49    const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
 50    return {
 51        R8: R8,
 52        S: S
 53    };
 54}
 55
 56function signMiMC(prv, msg) {
 57    const h1 = createBlakeHash("blake512").update(prv).digest();
 58    const sBuff = pruneBuffer(h1.slice(0,32));
 59    const s = bigInt.leBuff2int(sBuff);
 60    const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
 61
 62    const msgBuff = bigInt.leInt2Buff(msg, 32);
 63    const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
 64    let r = bigInt.leBuff2int(rBuff);
 65    r = r.mod(babyJub.subOrder);
 66    const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
 67    const hm = mimc7.multiHash([R8[0], R8[1], A[0], A[1], msg]);
 68    const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
 69    return {
 70        R8: R8,
 71        S: S
 72    };
 73}
 74
 75
 76function signPoseidon(prv, msg) {
 77    const h1 = createBlakeHash("blake512").update(prv).digest();
 78    const sBuff = pruneBuffer(h1.slice(0,32));
 79    const s = bigInt.leBuff2int(sBuff);
 80    const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
 81
 82    const msgBuff = bigInt.leInt2Buff(msg, 32);
 83    const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
 84    let r = bigInt.leBuff2int(rBuff);
 85    r = r.mod(babyJub.subOrder);
 86    const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
 87
 88    const hash = poseidon.createHash(6, 8, 57);
 89
 90    const hm = hash([R8[0], R8[1], A[0], A[1], msg]);
 91    const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
 92    return {
 93        R8: R8,
 94        S: S
 95    };
 96}
 97
 98function verify(msg, sig, A) {
 99    // Check parameters
100    if (typeof sig != "object") return false;
101    if (!Array.isArray(sig.R8)) return false;
102    if (sig.R8.length!= 2) return false;
103    if (!babyJub.inCurve(sig.R8)) return false;
104    if (!Array.isArray(A)) return false;
105    if (A.length!= 2) return false;
106    if (!babyJub.inCurve(A)) return false;
107    if (sig.S>= babyJub.subOrder) return false;
108
109    const R8p = babyJub.packPoint(sig.R8);
110    const Ap = babyJub.packPoint(A);
111    const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
112    const hm = bigInt.leBuff2int(hmBuff);
113
114    const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
115    let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
116    Pright = babyJub.addPoint(sig.R8, Pright);
117
118    if (!Pleft[0].equals(Pright[0])) return false;
119    if (!Pleft[1].equals(Pright[1])) return false;
120    return true;
121}
122
123function verifyMiMC(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 hm = mimc7.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
135
136    const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
137    let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
138    Pright = babyJub.addPoint(sig.R8, Pright);
139
140    if (!Pleft[0].equals(Pright[0])) return false;
141    if (!Pleft[1].equals(Pright[1])) return false;
142    return true;
143}
144
145
146function verifyPoseidon(msg, sig, A) {
147    // Check parameters
148    if (typeof sig != "object") return false;
149    if (!Array.isArray(sig.R8)) return false;
150    if (sig.R8.length!= 2) return false;
151    if (!babyJub.inCurve(sig.R8)) return false;
152    if (!Array.isArray(A)) return false;
153    if (A.length!= 2) return false;
154    if (!babyJub.inCurve(A)) return false;
155    if (sig.S>= babyJub.subOrder) return false;
156
157    const hash = poseidon.createHash(6, 8, 57);
158    const hm = hash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
159
160    const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
161    let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
162    Pright = babyJub.addPoint(sig.R8, Pright);
163
164    if (!Pleft[0].equals(Pright[0])) return false;
165    if (!Pleft[1].equals(Pright[1])) return false;
166    return true;
167}
168
169function packSignature(sig) {
170    const R8p = babyJub.packPoint(sig.R8);
171    const Sp = bigInt.leInt2Buff(sig.S, 32);
172    return Buffer.concat([R8p, Sp]);
173}
174
175function unpackSignature(sigBuff) {
176    return {
177        R8: babyJub.unpackPoint(sigBuff.slice(0,32)),
178        S: bigInt.leBuff2int(sigBuff.slice(32,64))
179    };
180}
181
182