UNPKG

@ellcrys/spell

Version:

The official JavaScript library for Ellcrys

478 lines 24.5 kB
"use strict"; /** * @module Key */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var crypto = require("crypto"); var SHA3 = require("sha3").SHA3; var RIPEMD160 = require("ripemd160"); var b58 = require("bs58check"); var create_hmac_1 = __importDefault(require("create-hmac")); var tweetnacl_1 = __importDefault(require("tweetnacl")); var errors_1 = __importDefault(require("./errors")); exports.AddressVersion = Buffer.from([92]); exports.PublicKeyVersion = Buffer.from([93]); exports.PrivateKeyVersion = Buffer.from([94]); var HARDENED_OFFSET = 0x80000000; var ED25519_CURVE = "ed25519 seed"; var pathRegex = new RegExp("^m(\\/[0-9]+')+$"); var replaceDerive = function (val) { return val.replace("'", ""); }; /** * PrivateKey represents an Ed25519 * key use for constructing an Ellcrys * address, signing and verifying a * signed messages. * * @export * @class PrivateKey */ var PrivateKey = /** @class */ (function () { /** * Creates an instance of PrivateKey. * @param {Buffer} seed 32-byte seed used to create the key * @memberof PrivateKey */ function PrivateKey(seed) { // If seed is not provided, we go // on to generate a random seed if (!seed || seed.length === 0) { seed = crypto.randomBytes(32); } var keypair = tweetnacl_1.default.sign.keyPair.fromSeed(seed); this.keypair = { privateKey: Buffer.from(keypair.secretKey), publicKey: Buffer.from(keypair.publicKey), }; } /** * Instantiate a PrivateKey from a base58 * encoded private key string * * @static * @param {string} str The base58 encoded private keys * @returns {PrivateKey} * @throws InvalidPrivateKeyChecksum|InvalidPrivateKeyVersion|InvalidPrivateKeySize * @memberof PrivateKey */ PrivateKey.from = function (str) { var decoded; try { decoded = b58.decode(str); } catch (e) { throw errors_1.default.InvalidPrivateKeyChecksum; } if (decoded[0] !== exports.PrivateKeyVersion[0]) { throw errors_1.default.InvalidPrivateKeyVersion; } if (decoded.length !== 65) { throw errors_1.default.InvalidPrivateKeySize; } var pk = decoded.slice(33); var o = new PrivateKey(); o.keypair.privateKey.set(decoded.slice(1)); o.keypair.publicKey.set(pk); return o; }; /** * Instantiate a PrivateKey from a buffer. * The buffer's 0th index must contain the * private key version. * * @static * @param {Buffer} buf * @returns {PrivateKey} * @memberof PrivateKey */ PrivateKey.fromBuffer = function (buf) { if (buf[0] !== exports.PrivateKeyVersion[0]) { throw errors_1.default.InvalidPrivateKeyVersion; } if (buf.length !== 65) { throw errors_1.default.InvalidPrivateKeySize; } var pk = buf.slice(33); var o = new PrivateKey(); o.keypair.privateKey.set(buf.slice(1)); o.keypair.publicKey.set(pk); return o; }; /** * Sign a message * * @param {Buffer} data The message * @returns {Buffer} * @memberof PrivateKey */ PrivateKey.prototype.sign = function (data) { return Buffer.from(tweetnacl_1.default.sign.detached(data, this.keypair.privateKey)); }; /** * Returns an address derived from * the private key * * @returns {Address} * @memberof PrivateKey */ PrivateKey.prototype.toAddress = function () { return this.publicKey().toAddress(); }; /** * Returns the public key. * * @returns {PublicKey} * @memberof PrivateKey */ PrivateKey.prototype.publicKey = function () { return PublicKey.fromBuffer(Buffer.concat([exports.PublicKeyVersion, this.keypair.publicKey])); }; /** * Returns base58 encode string of the private key * * @returns {string} * @memberof PrivateKey */ PrivateKey.prototype.toBase58 = function () { return b58.encode(Buffer.concat([exports.PrivateKeyVersion, this.keypair.privateKey])); }; /** * Returns the private key as a buffer. * The base58 version is added as the 0th * byte in the returned buffer * * @returns {Buffer} * @memberof PrivateKey */ PrivateKey.prototype.toBuffer = function () { return Buffer.concat([exports.PrivateKeyVersion, this.keypair.privateKey]); }; return PrivateKey; }()); exports.PrivateKey = PrivateKey; /** * PublicKey represents an ED25519 * public key * * @export * @class PublicKey */ // tslint:disable-next-line:max-classes-per-file var PublicKey = /** @class */ (function () { function PublicKey() { } /** * Instantiate a PublicKey from a buffer. * The buffer's 0th index must contain the * public key version. * * @static * @param {Buffer} buf * @returns {PublicKey} * @memberof PublicKey */ PublicKey.fromBuffer = function (buf) { if (buf[0] !== exports.PublicKeyVersion[0]) { throw errors_1.default.InvalidPublicKeyVersion; } if (buf.length !== 33) { throw errors_1.default.InvalidPublicKeySize; } var o = new PublicKey(); o.pk = buf.slice(1); return o; }; /** * Instantiate a PublicKey from a base58 * encoded public key string * * @static * @param {string} str * @returns {PublicKey} * @throws InvalidPublicKeyChecksum|InvalidPublicKeyVersion|InvalidPublicKeySize * @memberof PublicKey */ PublicKey.from = function (str) { var decoded; try { decoded = b58.decode(str); } catch (e) { throw errors_1.default.InvalidPublicKeyChecksum; } if (decoded[0] !== exports.PublicKeyVersion[0]) { throw errors_1.default.InvalidPublicKeyVersion; } if (decoded.length !== 33) { throw errors_1.default.InvalidPublicKeySize; } var o = new PublicKey(); o.pk = decoded.slice(1); return o; }; /** * Returns base58 encode string of the public key * * @returns {string} * @memberof PublicKey */ PublicKey.prototype.toBase58 = function () { return b58.encode(Buffer.concat([exports.PublicKeyVersion, this.pk])); }; /** * Returns the public key as a buffer. * The public key version is added as the 0th * byte in the returned buffer * * @returns {Buffer} * @memberof PublicKey */ PublicKey.prototype.toBuffer = function () { return Buffer.concat([exports.PublicKeyVersion, this.pk]); }; /** * Returns an address derived from * the public key * * @returns {Address} * @memberof PublicKey */ PublicKey.prototype.toAddress = function () { var hash = new SHA3(256); hash.update(this.pk); var ripHash = new RIPEMD160().update(hash.digest()).digest(); var addr = b58.encode(Buffer.concat([exports.AddressVersion, ripHash])); return Address.from(addr); }; /** * Verify a signature * * @param {Buffer} msg The message that was signed * @param {Buffer} sig The message's signature * @returns {boolean} * @memberof PublicKey */ PublicKey.prototype.verify = function (msg, sig) { return tweetnacl_1.default.sign.detached.verify(msg, sig, this.pk); }; return PublicKey; }()); exports.PublicKey = PublicKey; /** * Address represents a compressed * equivalent of a public key used * as an address for transacting. * * @class Address */ // tslint:disable-next-line:max-classes-per-file var Address = /** @class */ (function () { function Address() { var _this = this; /** * Return a string format of the address * * @memberof Address */ this.toString = function () { return _this.address; }; } /** * Check whether an address is valid * * @static * @param {string} address The address to check * @returns {boolean} * @memberof Address */ Address.isValid = function (address) { try { var decoded = b58.decode(address); if (decoded[0] !== exports.AddressVersion[0] || decoded.length !== 21) { return false; } return true; } catch (error) { return false; } }; /** * Check whether a given address is valid. * If not valid, the specific validation error * is returned. It returns null if the address * is valid. * * @static * @param {string} address The address to check * @returns {(null | Error)} InvalidAddressVersion | * InvalidAddressSize }| InvalidAddressFormat * @memberof Address */ Address.getValidationError = function (address) { try { var decoded = b58.decode(address); if (decoded[0] !== exports.AddressVersion[0]) { return errors_1.default.InvalidAddressVersion; } if (decoded.length !== 21) { return errors_1.default.InvalidAddressSize; } return null; } catch (error) { return errors_1.default.InvalidAddressFormat; } }; /** * Instantiate an Address instance from * a given address string * * @static * @param {string} address * @returns {Address} * @throws InvalidAddress * @memberof Address */ Address.from = function (address) { if (!this.isValid(address)) { throw errors_1.default.InvalidAddress; } var addr = new Address(); addr.address = address; return addr; }; return Address; }()); exports.Address = Address; /** * Checks whether an HDKey path is * valid * * @export * @param {string} path The path to check * @returns {boolean} */ function isValidPath(path) { if (!pathRegex.test(path)) { return false; } return !path .split("/") .slice(1) .map(replaceDerive) .some(isNaN); } exports.isValidPath = isValidPath; /** * HDKey provides the ability to create * hierarchical deterministic keys. * * @export * @class HDKey */ // tslint:disable-next-line:max-classes-per-file var HDKey = /** @class */ (function () { /** * Creates an instance of HDKey. * @param {Buffer} key Left half of the hmac digest * @param {Buffer} chainCode Right half of the hmac digest * @memberof HDKey */ function HDKey(key, chainCode) { this.mKey = key; this.mChainCode = chainCode; } /** * Create an HDKey from a seed. * * @static * @param {Buffer} seed * @returns {Node} * @memberof HDKey */ HDKey.fromMasterSeed = function (seed) { var hmac = create_hmac_1.default("sha512", ED25519_CURVE); var I = hmac.update(seed).digest(); var IL = I.slice(0, 32); var IR = I.slice(32); hmac.end(); return new HDKey(IL, IR); }; /** * Return the derived key * * @returns {Buffer} * @memberof HDKey */ HDKey.prototype.key = function () { return this.mKey; }; /** * Return the derived chain code * * @returns {Buffer} * @memberof HDKey */ HDKey.prototype.chainCode = function () { return this.mChainCode; }; /** * Child key derivation function * * @param {Buffer} key The parent key * @param {Buffer} chainCode The parent chain code * @param {number} index The key index * @returns {HDKey} * @memberof HDKey */ HDKey.prototype.ckd = function (key, chainCode, index) { var indexBuffer = Buffer.allocUnsafe(4); indexBuffer.writeUInt32BE(index, 0); var data = Buffer.concat([Buffer.alloc(1, 0), key, indexBuffer]); var I = create_hmac_1.default("sha512", chainCode) .update(data) .digest(); var IL = I.slice(0, 32); var IR = I.slice(32); return new HDKey(IL, IR); }; /** * Given a path, derive a child key. Path * must contain only hardened indices * * @param {string} path The derivation path * @returns {HDKey} * @memberof HDKey */ HDKey.prototype.derive = function (path) { var _this = this; if (!isValidPath(path)) { throw new Error("Invalid derivation path"); } var segments = path .split("/") .slice(1) .map(replaceDerive) .map(function (el) { return parseInt(el, 10); }); return segments.reduce(function (parentKey, segment) { return _this.ckd(parentKey.mKey, parentKey.mChainCode, segment + HARDENED_OFFSET); }, this); }; /** * Get the private key created using the * derived key * * @returns {PrivateKey} * @memberof HDKey */ HDKey.prototype.privateKey = function () { return new PrivateKey(this.mKey); }; return HDKey; }()); exports.HDKey = HDKey; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2xpYi9rZXkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOztHQUVHOzs7OztBQUVILCtCQUFrQztBQUMxQixJQUFBLDJCQUFJLENBQXFCO0FBQ2pDLElBQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUN2QyxJQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7QUFDakMsNERBQXFDO0FBQ3JDLHdEQUE2QjtBQUU3QixvREFBOEI7QUFFakIsUUFBQSxjQUFjLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDbkMsUUFBQSxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUNyQyxRQUFBLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBRW5ELElBQU0sZUFBZSxHQUFHLFVBQVUsQ0FBQztBQUNuQyxJQUFNLGFBQWEsR0FBRyxjQUFjLENBQUM7QUFDckMsSUFBTSxTQUFTLEdBQUcsSUFBSSxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUNqRCxJQUFNLGFBQWEsR0FBRyxVQUFDLEdBQVcsSUFBYSxPQUFBLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxFQUFwQixDQUFvQixDQUFDO0FBRXBFOzs7Ozs7OztHQVFHO0FBQ0g7SUF1RUM7Ozs7T0FJRztJQUNILG9CQUFZLElBQWE7UUFDeEIsaUNBQWlDO1FBQ2pDLCtCQUErQjtRQUMvQixJQUFJLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1lBQy9CLElBQUksR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQzlCO1FBRUQsSUFBTSxP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