UNPKG

evtjs

Version:

Javascript API Bindings for the everiToken blockchain.

427 lines (340 loc) 14.9 kB
"use strict"; var _slicedToArray2 = require("babel-runtime/helpers/slicedToArray"); var _slicedToArray3 = _interopRequireDefault(_slicedToArray2); var _typeof2 = require("babel-runtime/helpers/typeof"); var _typeof3 = _interopRequireDefault(_typeof2); var _regenerator = require("babel-runtime/regenerator"); var _regenerator2 = _interopRequireDefault(_regenerator); var _asyncToGenerator2 = require("babel-runtime/helpers/asyncToGenerator"); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var ecdsa = require("./ecdsa"); var hash = require("./hash"); var curve = require("ecurve").getCurveByName("secp256k1"); var assert = require("assert"); var BigInteger = require("../bigi"); var keyUtils = require("./key_utils"); var PublicKey = require("./key_public"); var ECSignature = require("./ecsignature"); var PrivateKey = require("./key_private"); var secp256k1 = null; try { secp256k1 = require("secp256k1"); } catch (e) {/* Do nothing */} module.exports = Signature; function Signature(r, s, i) { assert.equal(r != null, true, "Missing parameter"); assert.equal(s != null, true, "Missing parameter"); assert.equal(i != null, true, "Missing parameter"); /** Verify signed data. @arg {String|Buffer} data - full data @arg {pubkey|PublicKey} pubkey - EOSKey.. @arg {String} [encoding = 'utf8'] - data encoding (if data is a string) @return {boolean} */ function verify(data, pubkey) { var encoding = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "utf8"; if (typeof data === "string") { data = Buffer.from(data, encoding); } assert(Buffer.isBuffer(data), "data is a required String or Buffer"); data = hash.sha256(data); return verifyHash(data, pubkey); } /** Verify a buffer of exactally 32 bytes in size (sha256(text)) @arg {String|Buffer} dataSha256 - 32 byte buffer or string @arg {String|PublicKey} pubkey - EOSKey.. @arg {String} [encoding = 'hex'] - dataSha256 encoding (if string) @return {boolean} */ function verifyHash(dataSha256, pubkey) { var encoding = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "hex"; if (typeof dataSha256 === "string") { dataSha256 = Buffer.from(dataSha256, encoding); } if (dataSha256.length !== 32 || !Buffer.isBuffer(dataSha256)) throw new Error("dataSha256: 32 bytes required"); var publicKey = PublicKey(pubkey); assert(publicKey, "pubkey required"); return ecdsa.verify(curve, dataSha256, { r: r, s: s }, publicKey.Q); } /** Recover the public key used to create this signature using full data. @arg {String|Buffer} data - full data @arg {String} [encoding = 'utf8'] - data encoding (if string) @return {PublicKey} */ function recover(data) { var encoding = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "utf8"; if (typeof data === "string") { data = Buffer.from(data, encoding); } assert(Buffer.isBuffer(data), "data is a required String or Buffer"); data = hash.sha256(data); return recoverHash(data); } /** @arg {String|Buffer} dataSha256 - sha256 hash 32 byte buffer or hex string @arg {String} [encoding = 'hex'] - dataSha256 encoding (if string) @return {PublicKey} */ function recoverHash(dataSha256) { var encoding = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "hex"; //let time = new Date().valueOf(); if (typeof dataSha256 === "string") { dataSha256 = Buffer.from(dataSha256, encoding); } if (dataSha256.length !== 32 || !Buffer.isBuffer(dataSha256)) { throw new Error("dataSha256: 32 byte String or buffer requred"); } // sign the message if (secp256k1 != null) { var buffer = toBuffer(); //console.log("[recoverHash] accelerating supported, length of sign: " + buffer.length); var ret = PublicKey.fromBuffer(secp256k1.recover(dataSha256, buffer.slice(1), buffer[0] - 4 - 27, true)); //time = (new Date().valueOf()) - time; //console.log("[+" + time + "ms] recoverHash (c binding)"); return ret; } else { //console.log("[recoverHash] accelerating not supported"); var e = BigInteger.fromBuffer(dataSha256); var i2 = i; i2 -= 27; i2 = i2 & 3; var Q = ecdsa.recoverPubKey(curve, e, { r: r, s: s, i: i }, i2); // time = (new Date().valueOf()) - time; //console.log("[+" + time + "ms] recoverHash"); return PublicKey.fromPoint(Q); } } function toBuffer() { var buf; buf = new Buffer(65); buf.writeUInt8(i, 0); r.toBuffer(32).copy(buf, 1); s.toBuffer(32).copy(buf, 33); return buf; } function toHex() { return toBuffer().toString("hex"); } var signatureCache = void 0; function toString() { if (signatureCache) { return signatureCache; } signatureCache = "SIG_K1_" + keyUtils.checkEncode(toBuffer(), "K1"); return signatureCache; } return { r: r, s: s, i: i, toBuffer: toBuffer, verify: verify, verifyHash: verifyHash, recover: recover, recoverHash: recoverHash, toHex: toHex, toString: toString }; } /** Hash and sign arbitrary data. @arg {string|Buffer} data - full data @arg {wif|PrivateKey} privateKey @arg {String} [encoding = 'utf8'] - data encoding (if string) @return {Signature} */ Signature.sign = function () { var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(data, privateKey) { var encoding = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "utf8"; return _regenerator2.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: if (typeof data === "string") { data = Buffer.from(data, encoding); } assert(Buffer.isBuffer(data), "data is a required String or Buffer"); data = hash.sha256(data); _context.next = 5; return Signature.signHash(data, privateKey); case 5: return _context.abrupt("return", _context.sent); case 6: case "end": return _context.stop(); } } }, _callee, this); })); return function (_x6, _x7) { return _ref.apply(this, arguments); }; }(); function toArrayBuffer(myBuf) { var myBuffer = new ArrayBuffer(myBuf.length); var res = new Uint8Array(myBuffer); for (var i = 0; i < myBuf.length; ++i) { res[i] = myBuf[i]; } return res; } /** Sign a buffer of exactally 32 bytes in size (sha256(text)) @arg {string|Buffer} dataSha256 - 32 byte buffer or string @arg {wif|PrivateKey} privateKey @arg {String} [encoding = 'hex'] - dataSha256 encoding (if string) @return {Signature} */ Signature.signHash = function () { var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(dataSha256, privateKey) { var encoding = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "hex"; var _ret, der, e, ecsignature, i, lenR, lenS, nonce; return _regenerator2.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: //let time = new Date().valueOf(); if (typeof dataSha256 === "string") { dataSha256 = Buffer.from(dataSha256, encoding); } if (!(dataSha256.length !== 32 || !Buffer.isBuffer(dataSha256))) { _context2.next = 3; break; } throw new Error("dataSha256: 32 byte buffer requred"); case 3: privateKey = PrivateKey(privateKey); assert(privateKey, "privateKey required"); // sign the message if (!(secp256k1 != null)) { _context2.next = 11; break; } _ret = function () { // console.log("[signHash] accelerating supported"); var nonce = 0, canonical = false, sigObj = void 0, sigDER = void 0; while (!canonical) { sigObj = secp256k1.sign(dataSha256, privateKey.toBuffer(), { noncefn: function noncefn(message, rivateKey, algo, data, attempt) { // console.log("[nonce] attempt:" + nonce); var ret = new Buffer(32); ret[31] = nonce++; return ret; } }); sigDER = secp256k1.signatureExport(sigObj.signature); var _lenR = sigDER[3]; var _lenS = sigDER[5 + _lenR]; canonical = _lenR === 32 && _lenS === 32; } var ecsig = ECSignature.fromDER(sigDER); //time = (new Date().valueOf()) - time; //console.log("[+" + time + "ms] signHash (c binding)"); return { v: Signature(ecsig.r, ecsig.s, sigObj.recovery + 4 + 27) }; }(); if (!((typeof _ret === "undefined" ? "undefined" : (0, _typeof3.default)(_ret)) === "object")) { _context2.next = 9; break; } return _context2.abrupt("return", _ret.v); case 9: _context2.next = 28; break; case 11: i = null; // console.log("[signHash] no accelerating supported"); nonce = 0; e = BigInteger.fromBuffer(dataSha256); case 14: if (!true) { _context2.next = 27; break; } ecsignature = ecdsa.sign(curve, dataSha256, privateKey.d, nonce++); der = ecsignature.toDER(); lenR = der[3]; lenS = der[5 + lenR]; if (!(lenR === 32 && lenS === 32)) { _context2.next = 24; break; } i = ecdsa.calcPubKeyRecoveryParam(curve, e, ecsignature, privateKey.toPublic().Q); i += 4; // compressed i += 27; // compact // 24 or 27 :( forcing odd-y 2nd key candidate) return _context2.abrupt("break", 27); case 24: if (nonce % 10 === 0) { console.log("WARN: " + nonce + " attempts to find canonical signature"); } _context2.next = 14; break; case 27: return _context2.abrupt("return", Signature(ecsignature.r, ecsignature.s, i)); case 28: case "end": return _context2.stop(); } } }, _callee2, this); })); return function (_x9, _x10) { return _ref2.apply(this, arguments); }; }(); Signature.fromBuffer = function (buf) { var i, r, s; assert(Buffer.isBuffer(buf), "Buffer is required"); assert.equal(buf.length, 65, "Invalid signature length"); i = buf.readUInt8(0); assert.equal(i - 27, i - 27 & 7, "Invalid signature parameter"); r = BigInteger.fromBuffer(buf.slice(1, 33)); s = BigInteger.fromBuffer(buf.slice(33)); return Signature(r, s, i); }; Signature.fromHex = function (hex) { return Signature.fromBuffer(Buffer.from(hex, "hex")); }; /** @arg {string} signature - like SIG_K1_base58signature.. @return {Signature} or `null` (invalid) */ Signature.fromString = function (signature) { try { return Signature.fromStringOrThrow(signature); } catch (e) { return null; } }; /** @arg {string} signature - like SIG_K1_base58signature.. @throws {Error} invalid @return {Signature} */ Signature.fromStringOrThrow = function (signature) { assert.equal(typeof signature === "undefined" ? "undefined" : (0, _typeof3.default)(signature), "string", "signature"); var match = signature.match(/^SIG_([A-Za-z0-9]+)_([A-Za-z0-9]+)$/); assert(match != null && match.length === 3, "Expecting signature like: SIG_K1_base58signature.."); var _match = (0, _slicedToArray3.default)(match, 3), keyType = _match[1], keyString = _match[2]; assert.equal(keyType, "K1", "K1 signature expected"); return Signature.fromBuffer(keyUtils.checkDecode(keyString, keyType)); }; /** @arg {String|Signature} o - hex string @return {Signature} */ Signature.from = function (o) { var signature = o ? o.r && o.s && o.i ? o : typeof o === "string" && o.length === 130 ? Signature.fromHex(o) : typeof o === "string" && o.length !== 130 ? Signature.fromStringOrThrow(o) : Buffer.isBuffer(o) ? Signature.fromBuffer(o) : null : o; /*null or undefined*/ if (!signature) { throw new TypeError("signature should be a hex string or buffer"); } return signature; };