crypto-conditions
Version:
Implementation of crypto-conditions in JavaScript
248 lines (199 loc) • 8.19 kB
JavaScript
;
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 _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 _tweetnacl = require("tweetnacl");
var _baseSha = _interopRequireDefault(require("./base-sha256"));
var _missingDataError = _interopRequireDefault(require("../errors/missing-data-error"));
var _validationError = _interopRequireDefault(require("../errors/validation-error"));
var _bufferToUintArray = _interopRequireDefault(require("../util/buffer-to-uint-array"));
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; } }
var ed25519;
try {
ed25519 = require('ed25519');
} catch (err) {}
/**
* ED25519: Ed25519 signature condition.
*
* This condition implements Ed25519 signatures.
*
* ED25519 is assigned the type ID 4. It relies only on the ED25519 feature
* suite which corresponds to a bitmask of 0x20.
*/
var Ed25519Sha256 = /*#__PURE__*/function (_BaseSha) {
(0, _inherits2.default)(Ed25519Sha256, _BaseSha);
var _super = _createSuper(Ed25519Sha256);
function Ed25519Sha256() {
var _this;
(0, _classCallCheck2.default)(this, Ed25519Sha256);
_this = _super.call(this);
_this.publicKey = null;
_this.signature = null;
return _this;
}
/**
* Set the public publicKey.
*
* This is the Ed25519 public key. It has to be provided as a buffer.
*
* @param {Buffer} publicKey Public Ed25519 publicKey
*/
(0, _createClass2.default)(Ed25519Sha256, [{
key: "setPublicKey",
value: function setPublicKey(publicKey) {
if (!Buffer.isBuffer(publicKey)) {
throw new TypeError('Public key must be a Buffer, was: ' + publicKey);
}
if (publicKey.length !== 32) {
throw new Error('Public key must be 32 bytes, was: ' + publicKey.length);
} // TODO Validate public key
this.publicKey = publicKey;
}
/**
* Set the signature.
*
* Instead of using the private key to sign using the sign() method, we can
* also generate the signature elsewhere and pass it in.
*
* @param {Buffer} signature 64-byte signature.
*/
}, {
key: "setSignature",
value: function setSignature(signature) {
if (!Buffer.isBuffer(signature)) {
throw new TypeError('Signature must be a Buffer, was: ' + signature);
}
if (signature.length !== 64) {
throw new Error('Signature must be 64 bytes, was: ' + signature.length);
}
this.signature = signature;
}
/**
* Sign a message.
*
* This method will take a message and an Ed25519 private key and store a
* corresponding signature in this fulfillment.
*
* @param {Buffer} message Message to sign.
* @param {Buffer} privateKey Ed25519 private key.
*/
}, {
key: "sign",
value: function sign(message, privateKey) {
if (!Buffer.isBuffer(message)) {
throw new _missingDataError.default('Message must be a Buffer');
}
if (!Buffer.isBuffer(privateKey)) {
throw new TypeError('Private key must be a Buffer, was: ' + privateKey);
}
if (privateKey.length !== 32) {
throw new Error('Private key must be 32 bytes, was: ' + privateKey.length);
} // This would be the Ed25519ph version:
// message = crypto.createHash('sha512')
// .update(message)
// .digest()
// Use native library if available (~65x faster)
if (ed25519) {
var keyPair = ed25519.MakeKeypair(privateKey);
this.setPublicKey(keyPair.publicKey);
this.signature = ed25519.Sign(message, keyPair);
} else {
var _keyPair = _tweetnacl.sign.keyPair.fromSeed((0, _bufferToUintArray.default)(privateKey));
this.setPublicKey(Buffer.from(_keyPair.publicKey));
this.signature = Buffer.from(_tweetnacl.sign.detached((0, _bufferToUintArray.default)(message), _keyPair.secretKey));
}
}
}, {
key: "parseJson",
value: function parseJson(json) {
this.setPublicKey(Buffer.from(json.publicKey, 'base64'));
this.setSignature(Buffer.from(json.signature, 'base64'));
}
/**
* 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.publicKey) {
throw new _missingDataError.default('Requires public key');
}
return _fingerprint.Ed25519FingerprintContents.encode({
publicKey: this.publicKey
});
}
}, {
key: "getAsn1JsonPayload",
value: function getAsn1JsonPayload() {
return {
publicKey: this.publicKey,
signature: this.signature
};
}
/**
* Calculate the cost of fulfilling this condition.
*
* The cost of the Ed25519 condition is 2^17 = 131072.
*
* @return {Number} Expected maximum cost to fulfill this condition
* @private
*/
}, {
key: "calculateCost",
value: function calculateCost() {
return Ed25519Sha256.CONSTANT_COST;
}
/**
* Verify the signature of this Ed25519 fulfillment.
*
* The signature of this Ed25519 fulfillment is verified against the provided
* message and public key.
*
* @param {Buffer} message Message to validate against.
* @return {Boolean} Whether this fulfillment is valid.
*/
}, {
key: "validate",
value: function validate(message) {
if (!Buffer.isBuffer(message)) {
throw new TypeError('Message must be a Buffer');
} // Use native library if available (~60x faster)
var result;
if (ed25519) {
result = ed25519.Verify(message, this.signature, this.publicKey);
} else {
result = _tweetnacl.sign.detached.verify((0, _bufferToUintArray.default)(message), (0, _bufferToUintArray.default)(this.signature), (0, _bufferToUintArray.default)(this.publicKey));
}
if (result !== true) {
throw new _validationError.default('Invalid ed25519 signature');
}
return true;
}
}]);
return Ed25519Sha256;
}(_baseSha.default);
Ed25519Sha256.TYPE_ID = 4;
Ed25519Sha256.TYPE_NAME = 'ed25519-sha-256';
Ed25519Sha256.TYPE_ASN1_CONDITION = 'ed25519Sha256Condition';
Ed25519Sha256.TYPE_ASN1_FULFILLMENT = 'ed25519Sha256Fulfillment';
Ed25519Sha256.TYPE_CATEGORY = 'simple';
Ed25519Sha256.CONSTANT_COST = 131072;
var _default = Ed25519Sha256;
exports.default = _default;