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 crypto = require("crypto");
 6
 7exports.cratePrvKey = cratePrvKey;
 8exports.prv2pub= prv2pub;
 9exports.sign = sign;
10exports.verify = verify;
11exports.packSignature = packSignature;
12exports.unpackSignature = unpackSignature;
13
14
15function cratePrvKey() {
16    return crypto.randomBytes(32);
17}
18
19function pruneBuffer(_buff) {
20    const buff = Buffer.from(_buff);
21    buff[0] = buff[0] & 0xF8;
22    buff[31] = buff[31] & 0x7F;
23    buff[31] = buff[31] | 0x40;
24    return buff;
25}
26
27function prv2pub(prv) {
28    const sBuff = pruneBuffer(createBlakeHash("blake512").update(prv).digest().slice(0,32));
29    let s = bigInt.leBuff2int(sBuff);
30    const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
31    return A;
32}
33
34function sign(prv, msg) {
35    const h1 = createBlakeHash("blake512").update(prv).digest();
36    const sBuff = pruneBuffer(h1.slice(0,32));
37    const s = bigInt.leBuff2int(sBuff);
38    const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
39
40    const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msg])).digest();
41    let r = bigInt.leBuff2int(rBuff);
42    r = r.mod(babyJub.subOrder);
43    const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
44    const R8p = babyJub.packPoint(R8);
45    const Ap = babyJub.packPoint(A);
46    const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
47    const hm = bigInt.leBuff2int(hmBuff);
48    const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
49    return {
50        R8: R8,
51        S: S
52    };
53}
54
55function verify(msg, sig, A) {
56    // Check parameters
57    if (typeof sig != "object") return false;
58    if (!Array.isArray(sig.R8)) return false;
59    if (sig.R8.length!= 2) return false;
60    if (!babyJub.inCurve(sig.R8)) return false;
61    if (!Array.isArray(A)) return false;
62    if (A.length!= 2) return false;
63    if (!babyJub.inCurve(A)) return false;
64    if (sig.S>= babyJub.subOrder) return false;
65
66    const R8p = babyJub.packPoint(sig.R8);
67    const Ap = babyJub.packPoint(A);
68    const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
69    const hm = bigInt.leBuff2int(hmBuff);
70
71    const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
72    let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
73    Pright = babyJub.addPoint(sig.R8, Pright);
74
75    if (!Pleft[0].equals(Pright[0])) return false;
76    if (!Pleft[1].equals(Pright[1])) return false;
77    return true;
78}
79
80function packSignature(sig) {
81    const R8p = babyJub.packPoint(sig.R8);
82    const Sp = bigInt.leInt2Buff(sig.S, 32);
83    return Buffer.concat([R8p, Sp]);
84}
85
86function unpackSignature(sigBuff) {
87    return {
88        R8: babyJub.unpackPoint(sigBuff.slice(0,32)),
89        S: bigInt.leBuff2int(sigBuff.slice(32,64))
90    };
91}
92
93