@okxweb3/crypto-lib
Version:
A base package for @okxweb3/coin-*
322 lines • 11 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const elliptic_1 = require("../elliptic");
const secp256k1 = new elliptic_1.ec("secp256k1");
const curve = secp256k1.curve;
const BN = require("bn.js/lib/bn");
function loadCompressedPublicKey(first, xbuf) {
let x = new BN(xbuf);
if (x.cmp(curve.p) >= 0)
return null;
x = x.toRed(curve.red);
let y = x.redSqr().redIMul(x).redIAdd(curve.b).redSqrt();
if ((first === 0x03) !== y.isOdd())
y = y.redNeg();
const x3 = x.redSqr().redIMul(x);
if (!y.redSqr().redISub(x3.redIAdd(curve.b)).isZero())
return null;
return secp256k1.keyPair({ pub: { x: x, y: y } });
}
function loadUncompressedPublicKey(first, xbuf, ybuf) {
let x = new BN(xbuf);
let y = new BN(ybuf);
if (x.cmp(curve.p) >= 0 || y.cmp(curve.p) >= 0)
return null;
x = x.toRed(curve.red);
y = y.toRed(curve.red);
if ((first === 0x06 || first === 0x07) && y.isOdd() !== (first === 0x07))
return null;
const x3 = x.redSqr().redIMul(x);
if (!y.redSqr().redISub(x3.redIAdd(curve.b)).isZero())
return null;
return secp256k1.keyPair({ pub: { x: x, y: y } });
}
function loadPublicKey(pubkey) {
const first = pubkey[0];
switch (first) {
case 0x02:
case 0x03:
if (pubkey.length !== 33)
return null;
return loadCompressedPublicKey(first, pubkey.subarray(1, 33));
case 0x04:
case 0x06:
case 0x07:
if (pubkey.length !== 65)
return null;
return loadUncompressedPublicKey(first, pubkey.subarray(1, 33), pubkey.subarray(33, 65));
default:
return null;
}
}
module.exports = {
contextRandomize() {
return 0;
},
privateKeyVerify(seckey) {
const bn = new BN(seckey);
return bn.cmp(curve.n) < 0 && !bn.isZero();
},
privateKeyNegate(seckey) {
const bn = new BN(seckey);
return Buffer.from(curve.n.sub(bn).umod(curve.n).toArray('be', 32));
},
privateKeyTweakAdd(seckey, tweak) {
const bn = new BN(tweak);
if (bn.cmp(curve.n) >= 0)
return null;
bn.iadd(new BN(seckey));
if (bn.cmp(curve.n) >= 0)
bn.isub(curve.n);
if (bn.isZero())
return null;
return Buffer.from(bn.toArray('be', 32));
},
privateKeyTweakMul(seckey, tweak) {
let bn = new BN(tweak);
if (bn.cmp(curve.n) >= 0 || bn.isZero())
return 1;
bn.imul(new BN(seckey));
if (bn.cmp(curve.n) >= 0)
bn = bn.umod(curve.n);
return Buffer.from(bn.toArray('be', 32));
},
publicKeyVerify(pubkey) {
const pair = loadPublicKey(pubkey);
if (pair == null) {
return null;
}
return pair.validate().result;
},
publicKeyCreate(seckey, compress) {
const bn = new BN(seckey);
if (bn.cmp(curve.n) >= 0 || bn.isZero())
return null;
const point = secp256k1.keyFromPrivate(seckey, null).getPublic();
return Buffer.from(point.encode(null, compress));
},
publicKeyConvert(pubKey, compress) {
const pair = loadPublicKey(pubKey);
const point = pair.getPublic();
return Buffer.from(point.encode(null, compress));
},
publicKeyNegate(pubKey, compress) {
const pair = loadPublicKey(pubKey);
if (pair === null)
return 1;
const point = pair.getPublic();
point.y = point.y.redNeg();
return Buffer.from(point.encode(null, compress));
},
publicKeyCombine(pubKeys, compress) {
const pairs = new Array(pubKeys.length);
for (let i = 0; i < pubKeys.length; ++i) {
pairs[i] = loadPublicKey(pubKeys[i]);
if (pairs[i] === null)
return null;
}
let point = pairs[0].getPublic();
for (let i = 1; i < pairs.length; ++i)
point = point.add(pairs[i].pub);
if (point.isInfinity())
return null;
return Buffer.from(point.encode(null, compress));
},
publicKeyTweakAdd(pubKeys, tweak, compress) {
const pair = loadPublicKey(pubKeys);
if (pair === null)
return null;
const t = new BN(tweak);
if (t.cmp(curve.n) >= 0)
return null;
const point = pair.getPublic().add(curve.g.mul(tweak));
if (point.isInfinity())
return null;
return Buffer.from(point.encode(null, compress));
},
publicKeyTweakMul(pubkey, tweak, compress) {
const pair = loadPublicKey(pubkey);
if (pair === null)
return null;
const t = new BN(tweak);
if (t.cmp(curve.n) >= 0 || t.isZero())
return null;
const point = pair.getPublic().mul(tweak);
return Buffer.from(point.encode(null, compress));
},
signatureNormalize(sig) {
const r = new BN(sig.subarray(0, 32));
const s = new BN(sig.subarray(32, 64));
if (r.cmp(curve.n) >= 0 || s.cmp(curve.n) >= 0)
return null;
if (s.cmp(secp256k1.nh) === 1) {
sig.set(curve.n.sub(s).toArrayLike(Uint8Array, 'be', 32), 32);
}
return 0;
},
signatureExport(obj, sig) {
const sigR = sig.subarray(0, 32);
const sigS = sig.subarray(32, 64);
if (new BN(sigR).cmp(curve.n) >= 0)
return 1;
if (new BN(sigS).cmp(curve.n) >= 0)
return 1;
const { output } = obj;
let r = output.subarray(4, 4 + 33);
r[0] = 0x00;
r.set(sigR, 1);
let lenR = 33;
let posR = 0;
for (; lenR > 1 && r[posR] === 0x00 && !(r[posR + 1] & 0x80); --lenR, ++posR)
;
r = r.subarray(posR);
if (r[0] & 0x80)
return 1;
if (lenR > 1 && (r[0] === 0x00) && !(r[1] & 0x80))
return 1;
let s = output.subarray(6 + 33, 6 + 33 + 33);
s[0] = 0x00;
s.set(sigS, 1);
let lenS = 33;
let posS = 0;
for (; lenS > 1 && s[posS] === 0x00 && !(s[posS + 1] & 0x80); --lenS, ++posS)
;
s = s.subarray(posS);
if (s[0] & 0x80)
return 1;
if (lenS > 1 && (s[0] === 0x00) && !(s[1] & 0x80))
return 1;
obj.outputlen = 6 + lenR + lenS;
output[0] = 0x30;
output[1] = obj.outputlen - 2;
output[2] = 0x02;
output[3] = r.length;
output.set(r, 4);
output[4 + lenR] = 0x02;
output[5 + lenR] = s.length;
output.set(s, 6 + lenR);
return 0;
},
signatureImport(output, sig) {
if (sig.length < 8)
return 1;
if (sig.length > 72)
return 1;
if (sig[0] !== 0x30)
return 1;
if (sig[1] !== sig.length - 2)
return 1;
if (sig[2] !== 0x02)
return 1;
const lenR = sig[3];
if (lenR === 0)
return 1;
if (5 + lenR >= sig.length)
return 1;
if (sig[4 + lenR] !== 0x02)
return 1;
const lenS = sig[5 + lenR];
if (lenS === 0)
return 1;
if ((6 + lenR + lenS) !== sig.length)
return 1;
if (sig[4] & 0x80)
return 1;
if (lenR > 1 && (sig[4] === 0x00) && !(sig[5] & 0x80))
return 1;
if (sig[lenR + 6] & 0x80)
return 1;
if (lenS > 1 && (sig[lenR + 6] === 0x00) && !(sig[lenR + 7] & 0x80))
return 1;
let sigR = sig.subarray(4, 4 + lenR);
if (sigR.length === 33 && sigR[0] === 0x00)
sigR = sigR.subarray(1);
if (sigR.length > 32)
return 1;
let sigS = sig.subarray(6 + lenR);
if (sigS.length === 33 && sigS[0] === 0x00)
sigS = sigS.slice(1);
if (sigS.length > 32)
throw new Error('S length is too long');
let r = new BN(sigR);
if (r.cmp(curve.n) >= 0)
r = new BN(0);
let s = new BN(sig.subarray(6 + lenR));
if (s.cmp(curve.n) >= 0)
s = new BN(0);
output.set(r.toArrayLike(Uint8Array, 'be', 32), 0);
output.set(s.toArrayLike(Uint8Array, 'be', 32), 32);
return 0;
},
ecdsaSign(message, seckey) {
const d = new BN(seckey);
if (d.cmp(curve.n) >= 0 || d.isZero())
return null;
return secp256k1.sign(message, seckey, { canonical: true }).toBytes();
},
ecdsaVerify(sig, msg32, pubkey) {
const sigObj = { r: sig.subarray(0, 32), s: sig.subarray(32, 64) };
const sigr = new BN(sigObj.r);
const sigs = new BN(sigObj.s);
if (sigr.cmp(curve.n) >= 0 || sigs.cmp(curve.n) >= 0)
return 1;
if (sigs.cmp(secp256k1.nh) === 1 || sigr.isZero() || sigs.isZero())
return 3;
const pair = loadPublicKey(pubkey);
if (pair === null)
return 2;
const point = pair.getPublic();
return secp256k1.verify(msg32, sigObj, point);
},
ecdsaRecover(sig, recid, msg32, compress) {
const sigObj = { r: sig.slice(0, 32), s: sig.slice(32, 64) };
const sigr = new BN(sigObj.r);
const sigs = new BN(sigObj.s);
if (sigr.cmp(curve.n) >= 0 || sigs.cmp(curve.n) >= 0)
return 1;
if (sigr.isZero() || sigs.isZero())
return 2;
let point;
try {
point = secp256k1.recoverPubKey(msg32, sigObj, recid, null);
}
catch (err) {
return 2;
}
return Buffer.from(point.encode(null, compress));
},
ecdh(output, pubKey, seckey, data, hashfn, xbuf, ybuf) {
const pair = loadPublicKey(pubKey);
if (pair === null)
return 1;
const scalar = new BN(seckey);
if (scalar.cmp(curve.n) >= 0 || scalar.isZero())
return 2;
const point = pair.getPublic().mul(scalar);
if (hashfn === undefined) {
const data = point.encode(null, true);
const sha256 = secp256k1.hash().update(data).digest();
for (let i = 0; i < 32; ++i)
output[i] = sha256[i];
}
else {
if (!xbuf)
xbuf = new Uint8Array(32);
const x = point.getX().toArray('be', 32);
for (let i = 0; i < 32; ++i)
xbuf[i] = x[i];
if (!ybuf)
ybuf = new Uint8Array(32);
const y = point.getY().toArray('be', 32);
for (let i = 0; i < 32; ++i)
ybuf[i] = y[i];
const hash = hashfn(xbuf, ybuf, data);
const isValid = hash instanceof Uint8Array && hash.length === output.length;
if (!isValid)
return 2;
output.set(hash);
}
return 0;
}
};
//# sourceMappingURL=api.js.map