mirror of
https://github.com/Instadapp/Swap-Aggregator-Subgraph.git
synced 2024-07-29 21:57:12 +00:00
264 lines
8.3 KiB
JavaScript
264 lines
8.3 KiB
JavaScript
'use strict'
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var createHash = require('create-hash')
|
|
var BN = require('bn.js')
|
|
var EC = require('elliptic').ec
|
|
|
|
var messages = require('../messages.json')
|
|
|
|
var ec = new EC('secp256k1')
|
|
var ecparams = ec.curve
|
|
|
|
function loadCompressedPublicKey (first, xBuffer) {
|
|
var x = new BN(xBuffer)
|
|
|
|
// overflow
|
|
if (x.cmp(ecparams.p) >= 0) return null
|
|
x = x.toRed(ecparams.red)
|
|
|
|
// compute corresponding Y
|
|
var y = x.redSqr().redIMul(x).redIAdd(ecparams.b).redSqrt()
|
|
if ((first === 0x03) !== y.isOdd()) y = y.redNeg()
|
|
|
|
return ec.keyPair({ pub: { x: x, y: y } })
|
|
}
|
|
|
|
function loadUncompressedPublicKey (first, xBuffer, yBuffer) {
|
|
var x = new BN(xBuffer)
|
|
var y = new BN(yBuffer)
|
|
|
|
// overflow
|
|
if (x.cmp(ecparams.p) >= 0 || y.cmp(ecparams.p) >= 0) return null
|
|
|
|
x = x.toRed(ecparams.red)
|
|
y = y.toRed(ecparams.red)
|
|
|
|
// is odd flag
|
|
if ((first === 0x06 || first === 0x07) && y.isOdd() !== (first === 0x07)) return null
|
|
|
|
// x*x*x + b = y*y
|
|
var x3 = x.redSqr().redIMul(x)
|
|
if (!y.redSqr().redISub(x3.redIAdd(ecparams.b)).isZero()) return null
|
|
|
|
return ec.keyPair({ pub: { x: x, y: y } })
|
|
}
|
|
|
|
function loadPublicKey (publicKey) {
|
|
var first = publicKey[0]
|
|
switch (first) {
|
|
case 0x02:
|
|
case 0x03:
|
|
if (publicKey.length !== 33) return null
|
|
return loadCompressedPublicKey(first, publicKey.slice(1, 33))
|
|
case 0x04:
|
|
case 0x06:
|
|
case 0x07:
|
|
if (publicKey.length !== 65) return null
|
|
return loadUncompressedPublicKey(first, publicKey.slice(1, 33), publicKey.slice(33, 65))
|
|
default:
|
|
return null
|
|
}
|
|
}
|
|
|
|
exports.privateKeyVerify = function (privateKey) {
|
|
var bn = new BN(privateKey)
|
|
return bn.cmp(ecparams.n) < 0 && !bn.isZero()
|
|
}
|
|
|
|
exports.privateKeyExport = function (privateKey, compressed) {
|
|
var d = new BN(privateKey)
|
|
if (d.cmp(ecparams.n) >= 0 || d.isZero()) throw new Error(messages.EC_PRIVATE_KEY_EXPORT_DER_FAIL)
|
|
|
|
return Buffer.from(ec.keyFromPrivate(privateKey).getPublic(compressed, true))
|
|
}
|
|
|
|
exports.privateKeyNegate = function (privateKey) {
|
|
var bn = new BN(privateKey)
|
|
return bn.isZero() ? Buffer.alloc(32) : ecparams.n.sub(bn).umod(ecparams.n).toArrayLike(Buffer, 'be', 32)
|
|
}
|
|
|
|
exports.privateKeyModInverse = function (privateKey) {
|
|
var bn = new BN(privateKey)
|
|
if (bn.cmp(ecparams.n) >= 0 || bn.isZero()) throw new Error(messages.EC_PRIVATE_KEY_RANGE_INVALID)
|
|
|
|
return bn.invm(ecparams.n).toArrayLike(Buffer, 'be', 32)
|
|
}
|
|
|
|
exports.privateKeyTweakAdd = function (privateKey, tweak) {
|
|
var bn = new BN(tweak)
|
|
if (bn.cmp(ecparams.n) >= 0) throw new Error(messages.EC_PRIVATE_KEY_TWEAK_ADD_FAIL)
|
|
|
|
bn.iadd(new BN(privateKey))
|
|
if (bn.cmp(ecparams.n) >= 0) bn.isub(ecparams.n)
|
|
if (bn.isZero()) throw new Error(messages.EC_PRIVATE_KEY_TWEAK_ADD_FAIL)
|
|
|
|
return bn.toArrayLike(Buffer, 'be', 32)
|
|
}
|
|
|
|
exports.privateKeyTweakMul = function (privateKey, tweak) {
|
|
var bn = new BN(tweak)
|
|
if (bn.cmp(ecparams.n) >= 0 || bn.isZero()) throw new Error(messages.EC_PRIVATE_KEY_TWEAK_MUL_FAIL)
|
|
|
|
bn.imul(new BN(privateKey))
|
|
if (bn.cmp(ecparams.n)) bn = bn.umod(ecparams.n)
|
|
|
|
return bn.toArrayLike(Buffer, 'be', 32)
|
|
}
|
|
|
|
exports.publicKeyCreate = function (privateKey, compressed) {
|
|
var d = new BN(privateKey)
|
|
if (d.cmp(ecparams.n) >= 0 || d.isZero()) throw new Error(messages.EC_PUBLIC_KEY_CREATE_FAIL)
|
|
|
|
return Buffer.from(ec.keyFromPrivate(privateKey).getPublic(compressed, true))
|
|
}
|
|
|
|
exports.publicKeyConvert = function (publicKey, compressed) {
|
|
var pair = loadPublicKey(publicKey)
|
|
if (pair === null) throw new Error(messages.EC_PUBLIC_KEY_PARSE_FAIL)
|
|
|
|
return Buffer.from(pair.getPublic(compressed, true))
|
|
}
|
|
|
|
exports.publicKeyVerify = function (publicKey) {
|
|
return loadPublicKey(publicKey) !== null
|
|
}
|
|
|
|
exports.publicKeyTweakAdd = function (publicKey, tweak, compressed) {
|
|
var pair = loadPublicKey(publicKey)
|
|
if (pair === null) throw new Error(messages.EC_PUBLIC_KEY_PARSE_FAIL)
|
|
|
|
tweak = new BN(tweak)
|
|
if (tweak.cmp(ecparams.n) >= 0) throw new Error(messages.EC_PUBLIC_KEY_TWEAK_ADD_FAIL)
|
|
|
|
var point = ecparams.g.mul(tweak).add(pair.pub)
|
|
if (point.isInfinity()) throw new Error(messages.EC_PUBLIC_KEY_TWEAK_ADD_FAIL)
|
|
|
|
return Buffer.from(point.encode(true, compressed))
|
|
}
|
|
|
|
exports.publicKeyTweakMul = function (publicKey, tweak, compressed) {
|
|
var pair = loadPublicKey(publicKey)
|
|
if (pair === null) throw new Error(messages.EC_PUBLIC_KEY_PARSE_FAIL)
|
|
|
|
tweak = new BN(tweak)
|
|
if (tweak.cmp(ecparams.n) >= 0 || tweak.isZero()) throw new Error(messages.EC_PUBLIC_KEY_TWEAK_MUL_FAIL)
|
|
|
|
return Buffer.from(pair.pub.mul(tweak).encode(true, compressed))
|
|
}
|
|
|
|
exports.publicKeyCombine = function (publicKeys, compressed) {
|
|
var pairs = new Array(publicKeys.length)
|
|
for (var i = 0; i < publicKeys.length; ++i) {
|
|
pairs[i] = loadPublicKey(publicKeys[i])
|
|
if (pairs[i] === null) throw new Error(messages.EC_PUBLIC_KEY_PARSE_FAIL)
|
|
}
|
|
|
|
var point = pairs[0].pub
|
|
for (var j = 1; j < pairs.length; ++j) point = point.add(pairs[j].pub)
|
|
if (point.isInfinity()) throw new Error(messages.EC_PUBLIC_KEY_COMBINE_FAIL)
|
|
|
|
return Buffer.from(point.encode(true, compressed))
|
|
}
|
|
|
|
exports.signatureNormalize = function (signature) {
|
|
var r = new BN(signature.slice(0, 32))
|
|
var s = new BN(signature.slice(32, 64))
|
|
if (r.cmp(ecparams.n) >= 0 || s.cmp(ecparams.n) >= 0) throw new Error(messages.ECDSA_SIGNATURE_PARSE_FAIL)
|
|
|
|
var result = Buffer.from(signature)
|
|
if (s.cmp(ec.nh) === 1) ecparams.n.sub(s).toArrayLike(Buffer, 'be', 32).copy(result, 32)
|
|
|
|
return result
|
|
}
|
|
|
|
exports.signatureExport = function (signature) {
|
|
var r = signature.slice(0, 32)
|
|
var s = signature.slice(32, 64)
|
|
if (new BN(r).cmp(ecparams.n) >= 0 || new BN(s).cmp(ecparams.n) >= 0) throw new Error(messages.ECDSA_SIGNATURE_PARSE_FAIL)
|
|
|
|
return { r: r, s: s }
|
|
}
|
|
|
|
exports.signatureImport = function (sigObj) {
|
|
var r = new BN(sigObj.r)
|
|
if (r.cmp(ecparams.n) >= 0) r = new BN(0)
|
|
|
|
var s = new BN(sigObj.s)
|
|
if (s.cmp(ecparams.n) >= 0) s = new BN(0)
|
|
|
|
return Buffer.concat([
|
|
r.toArrayLike(Buffer, 'be', 32),
|
|
s.toArrayLike(Buffer, 'be', 32)
|
|
])
|
|
}
|
|
|
|
exports.sign = function (message, privateKey, noncefn, data) {
|
|
if (typeof noncefn === 'function') {
|
|
var getNonce = noncefn
|
|
noncefn = function (counter) {
|
|
var nonce = getNonce(message, privateKey, null, data, counter)
|
|
if (!Buffer.isBuffer(nonce) || nonce.length !== 32) throw new Error(messages.ECDSA_SIGN_FAIL)
|
|
|
|
return new BN(nonce)
|
|
}
|
|
}
|
|
|
|
var d = new BN(privateKey)
|
|
if (d.cmp(ecparams.n) >= 0 || d.isZero()) throw new Error(messages.ECDSA_SIGN_FAIL)
|
|
|
|
var result = ec.sign(message, privateKey, { canonical: true, k: noncefn, pers: data })
|
|
return {
|
|
signature: Buffer.concat([
|
|
result.r.toArrayLike(Buffer, 'be', 32),
|
|
result.s.toArrayLike(Buffer, 'be', 32)
|
|
]),
|
|
recovery: result.recoveryParam
|
|
}
|
|
}
|
|
|
|
exports.verify = function (message, signature, publicKey) {
|
|
var sigObj = { r: signature.slice(0, 32), s: signature.slice(32, 64) }
|
|
|
|
var sigr = new BN(sigObj.r)
|
|
var sigs = new BN(sigObj.s)
|
|
if (sigr.cmp(ecparams.n) >= 0 || sigs.cmp(ecparams.n) >= 0) throw new Error(messages.ECDSA_SIGNATURE_PARSE_FAIL)
|
|
if (sigs.cmp(ec.nh) === 1 || sigr.isZero() || sigs.isZero()) return false
|
|
|
|
var pair = loadPublicKey(publicKey)
|
|
if (pair === null) throw new Error(messages.EC_PUBLIC_KEY_PARSE_FAIL)
|
|
|
|
return ec.verify(message, sigObj, { x: pair.pub.x, y: pair.pub.y })
|
|
}
|
|
|
|
exports.recover = function (message, signature, recovery, compressed) {
|
|
var sigObj = { r: signature.slice(0, 32), s: signature.slice(32, 64) }
|
|
|
|
var sigr = new BN(sigObj.r)
|
|
var sigs = new BN(sigObj.s)
|
|
if (sigr.cmp(ecparams.n) >= 0 || sigs.cmp(ecparams.n) >= 0) throw new Error(messages.ECDSA_SIGNATURE_PARSE_FAIL)
|
|
|
|
try {
|
|
if (sigr.isZero() || sigs.isZero()) throw new Error()
|
|
|
|
var point = ec.recoverPubKey(message, sigObj, recovery)
|
|
return Buffer.from(point.encode(true, compressed))
|
|
} catch (err) {
|
|
throw new Error(messages.ECDSA_RECOVER_FAIL)
|
|
}
|
|
}
|
|
|
|
exports.ecdh = function (publicKey, privateKey) {
|
|
var shared = exports.ecdhUnsafe(publicKey, privateKey, true)
|
|
return createHash('sha256').update(shared).digest()
|
|
}
|
|
|
|
exports.ecdhUnsafe = function (publicKey, privateKey, compressed) {
|
|
var pair = loadPublicKey(publicKey)
|
|
if (pair === null) throw new Error(messages.EC_PUBLIC_KEY_PARSE_FAIL)
|
|
|
|
var scalar = new BN(privateKey)
|
|
if (scalar.cmp(ecparams.n) >= 0 || scalar.isZero()) throw new Error(messages.ECDH_FAIL)
|
|
|
|
return Buffer.from(pair.pub.mul(scalar).encode(true, compressed))
|
|
}
|