UNPKG

crypto-conditions

Version:

Implementation of crypto-conditions in JavaScript

295 lines (247 loc) 11.5 kB
"use strict"; var _Reflect$construct = require("@babel/runtime-corejs3/core-js-stable/reflect/construct"); var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property"); var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault"); _Object$defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _set = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/set")); var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/concat")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/toConsumableArray")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/createClass")); var _inherits2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/inherits")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/getPrototypeOf")); var _condition = _interopRequireDefault(require("../lib/condition")); var _fulfillment = _interopRequireDefault(require("../lib/fulfillment")); var _baseSha = _interopRequireDefault(require("./base-sha256")); var _missingDataError = _interopRequireDefault(require("../errors/missing-data-error")); var _isInteger = _interopRequireDefault(require("../util/is-integer")); var _fingerprint = require("../schemas/fingerprint"); function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = _Reflect$construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !_Reflect$construct) return false; if (_Reflect$construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } /** * PREFIX-SHA-256: Prefix condition using SHA-256. * * A prefix condition will prepend a static prefix to the message before passing * the prefixed message on to a single subcondition. * * You can use prefix conditions to effectively narrow the scope of a public key * or set of public keys. Simply take the condition representing the public key * and place it as a subcondition in a prefix condition. Now any message passed * to the subcondition will be prepended with a prefix. * * Prefix conditions are especially useful in conjunction with threshold * conditions. You could have a group of signers, each using a different prefix * to sign a common message. * * PREFIX-SHA-256 is assigned the type ID 1. It relies on the SHA-256 and PREFIX * feature suites which corresponds to a feature bitmask of 0x05. */ var PrefixSha256 = /*#__PURE__*/function (_BaseSha) { (0, _inherits2.default)(PrefixSha256, _BaseSha); var _super = _createSuper(PrefixSha256); function PrefixSha256() { var _this; (0, _classCallCheck2.default)(this, PrefixSha256); _this = _super.call(this); _this.prefix = Buffer.alloc(0); _this.subcondition = null; _this.maxMessageLength = 16384; return _this; } /** * Set the (unfulfilled) subcondition. * * Each prefix condition builds on an existing condition which is provided via * this method. * * @param {Condition|String} subcondition Condition object or URI string * representing the condition that will receive the prefixed message. */ (0, _createClass2.default)(PrefixSha256, [{ key: "setSubcondition", value: function setSubcondition(subcondition) { if (typeof subcondition === 'string') { subcondition = _condition.default.fromUri(subcondition); } else if (!(subcondition instanceof _condition.default)) { throw new Error('Subconditions must be URIs or objects of type Condition'); } this.subcondition = subcondition; } /** * Set the (fulfilled) subcondition. * * When constructing a prefix fulfillment, this method allows you to pass in * a fulfillment for the condition that will receive the prefixed message. * * Note that you only have to add either the subcondition or a subfulfillment, * but not both. * * @param {Fulfillment|String} fulfillment Fulfillment object or URI string * representing the fulfillment to use as the subcondition. */ }, { key: "setSubfulfillment", value: function setSubfulfillment(subfulfillment) { if (typeof subfulfillment === 'string') { subfulfillment = _fulfillment.default.fromUri(subfulfillment); } else if (!(subfulfillment instanceof _fulfillment.default)) { throw new Error('Subfulfillments must be objects of type Fulfillment'); } this.subcondition = subfulfillment; } /** * Set the prefix. * * The prefix will be prepended to the message during validation before the * message is passed on to the subcondition. * * @param {Buffer} prefix Prefix to apply to the message. */ }, { key: "setPrefix", value: function setPrefix(prefix) { if (!Buffer.isBuffer(prefix)) { throw new TypeError('Prefix must be a Buffer, was: ' + prefix); } this.prefix = prefix; } /** * Set the threshold. * * Determines the threshold that is used to consider this condition fulfilled. * If the number of valid subfulfillments is greater or equal to this number, * the threshold condition is considered to be fulfilled. * * @param {Number} maxMessageLength Integer threshold */ }, { key: "setMaxMessageLength", value: function setMaxMessageLength(maxMessageLength) { if (!(0, _isInteger.default)(maxMessageLength) || maxMessageLength < 0) { throw new TypeError('Max message length must be an integer greater than or equal to zero, was: ' + maxMessageLength); } this.maxMessageLength = maxMessageLength; } /** * Get types used in this condition. * * This is a type of condition that contains a subcondition. A complete * set of subtypes must contain the set of types that must be supported in * order to validate this fulfillment. Therefore, we need to join the type of * this condition to the types used in the subcondition. * * @return {Set<String>} Complete type names for this fulfillment. */ }, { key: "getSubtypes", value: function getSubtypes() { var _context; var subtypes = new _set.default((0, _concat.default)(_context = []).call(_context, (0, _toConsumableArray2.default)(this.subcondition.getSubtypes()), [this.subcondition.getTypeName()])); // Never include our own type as a subtype. The reason is that we already // know that the validating implementation knows how to interpret this type, // otherwise it wouldn't be able to verify this fulfillment to begin with. subtypes.delete(this.constructor.TYPE_NAME); return subtypes; } /** * Produce the contents of the condition hash. * * This function is called internally by the `getCondition` method. * * @return {Buffer} Encoded contents of fingerprint hash. * * @private */ }, { key: "getFingerprintContents", value: function getFingerprintContents() { if (!this.subcondition) { throw new _missingDataError.default('Requires subcondition'); } return _fingerprint.PrefixFingerprintContents.encode({ prefix: this.prefix, maxMessageLength: this.maxMessageLength, subcondition: this.subcondition instanceof _condition.default ? this.subcondition.getAsn1Json() : this.subcondition.getCondition().getAsn1Json() }); } }, { key: "getAsn1JsonPayload", value: function getAsn1JsonPayload() { return { prefix: this.prefix, maxMessageLength: this.maxMessageLength, subfulfillment: this.subcondition.getAsn1Json() }; } }, { key: "parseJson", value: function parseJson(json) { this.setPrefix(Buffer.from(json.prefix, 'base64')); this.setMaxMessageLength(json.maxMessageLength); this.setSubfulfillment(_fulfillment.default.fromJson(json.subfulfillment)); } }, { key: "parseAsn1JsonPayload", value: function parseAsn1JsonPayload(json) { this.setPrefix(Buffer.from(json.prefix, 'base64')); this.setMaxMessageLength(json.maxMessageLength.toNumber()); this.setSubfulfillment(_fulfillment.default.fromAsn1Json(json.subfulfillment)); } /** * Calculate the cost of fulfilling this condition. * * The cost of the prefix condition equals (1 + l/256) * (16384 + s) where l * is the prefix length in bytes and s is the subcondition cost. * * @return {Number} Expected maximum cost to fulfill this condition * @private */ }, { key: "calculateCost", value: function calculateCost() { if (!this.prefix) { throw new _missingDataError.default('Prefix must be specified'); } if (!this.subcondition) { throw new _missingDataError.default('Subcondition must be specified'); } var subconditionCost = this.subcondition instanceof _condition.default ? this.subcondition.getCost() : this.subcondition.getCondition().getCost(); return Number(this.prefix.length) + this.maxMessageLength + subconditionCost + 1024; } /** * Check whether this fulfillment meets all validation criteria. * * This will validate the subfulfillment. The message will be prepended with * the prefix before being passed to the subfulfillment's validation routine. * * @param {Buffer} message Message to validate against. * @return {Boolean} Whether this fulfillment is valid. */ }, { key: "validate", value: function validate(message) { if (!(this.subcondition instanceof _fulfillment.default)) { throw new Error('Subcondition is not a fulfillment'); } if (!Buffer.isBuffer(message)) { throw new Error('Message must be provided as a Buffer, was: ' + message); } // Ensure the subfulfillment is valid return this.subcondition.validate((0, _concat.default)(Buffer).call(Buffer, [this.prefix, message])); } }]); return PrefixSha256; }(_baseSha.default); PrefixSha256.TYPE_ID = 1; PrefixSha256.TYPE_NAME = 'prefix-sha-256'; PrefixSha256.TYPE_ASN1_CONDITION = 'prefixSha256Condition'; PrefixSha256.TYPE_ASN1_FULFILLMENT = 'prefixSha256Fulfillment'; PrefixSha256.TYPE_CATEGORY = 'compound'; PrefixSha256.CONSTANT_BASE_COST = 16384; PrefixSha256.CONSTANT_COST_DIVISOR = 256; // DEPRECATED PrefixSha256.prototype.setSubconditionUri = PrefixSha256.prototype.setSubcondition; PrefixSha256.prototype.setSubfulfillmentUri = PrefixSha256.prototype.setSubfulfillment; var _default = PrefixSha256; exports.default = _default;