UNPKG

@woleet/woleet-weblibs

Version:
1,685 lines (1,374 loc) 575 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.woleet = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ "use strict"; function getJSON(url) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return new Promise(function (resolve, reject) { var req = new XMLHttpRequest(); req.onload = function () { switch (req.status) { case 200: case 201: resolve(req.response); break; default: reject({ code: req.status }); break; } }; req.onerror = function () { reject({ code: 0 }); }; req.open(options.method || "GET", url, true); if (options.token) req.setRequestHeader("Authorization", 'Bearer ' + options.token); if (options.method === 'POST') req.setRequestHeader('Content-Type', 'application/json'); req.setRequestHeader('Accept', 'application/json'); req.responseType = 'json'; req.json = 'json'; req.send(JSON.stringify(options.data)); }); } module.exports = getJSON; },{}],2:[function(require,module,exports){ 'use strict'; if (typeof window === 'undefined') { throw new Error('This module is not meant to be used by node'); } var getJSON = require('./get-json'); var woleet = require('../common/woleet-api')(getJSON); woleet.crypto = require('./woleet-crypto'); woleet.file = require('./woleet-hashfile'); woleet.receipt.validate = require('../common/woleet-chainpoint')(woleet.crypto); woleet.signature = require('../common/woleet-signature')(woleet.identity.get); woleet.verify = require('../common/woleet-verify')(woleet); module.exports = woleet; },{"../common/woleet-api":5,"../common/woleet-chainpoint":6,"../common/woleet-signature":7,"../common/woleet-verify":8,"./get-json":1,"./woleet-crypto":3,"./woleet-hashfile":4}],3:[function(require,module,exports){ (function (Buffer){(function (){ 'use strict'; if (typeof _in_worker === 'undefined' && typeof window === 'undefined') { throw new Error('This module is not meant to be used by node'); } var CryptoJS = function (factory) { return factory(require("crypto-js/core"), require("crypto-js/sha224"), require("crypto-js/sha256"), require("crypto-js/sha384"), require("crypto-js/sha512"), require("crypto-js/lib-typedarrays")); }(function (CryptoJS) { return CryptoJS; }); var WordArray = CryptoJS.lib.WordArray; function createSha(alg) { var hash = CryptoJS.algo[alg].create(); var o = {}; o.update = function (data, inputEncoding) { var _data = void 0; if (data instanceof Uint8Array) { _data = WordArray.create(data); } else if (WordArray.isPrototypeOf(data)) { _data = data; } else if (inputEncoding) { switch (inputEncoding) { case 'binary': var len = data.length; var arr = new Uint8Array(len); for (var i = 0; i < len; i++) { arr[i] = data.charCodeAt(i); }_data = WordArray.create(arr); break; case 'hex': _data = CryptoJS.enc.Hex.parse(data); break; case 'utf8': _data = data; break; case 'base64': default: _data = WordArray.create(new Buffer(data, inputEncoding)); } } else if (!data) { _data = WordArray.create(); } else if (typeof data === 'string') { _data = data; } else { throw new TypeError(); } hash.update(_data); return o; }; o.digest = function (encoding) { var hex = CryptoJS.enc.Hex.stringify(hash.finalize()); if (encoding && encoding === 'hex') { return hex; } else { var bin = new Buffer(hex, 'hex'); return encoding ? bin.toString(encoding) : bin; } }; return o; } function createHash(algorithm) { switch (algorithm) { case 'sha224': return createSha('SHA224'); case 'sha256': return createSha('SHA256'); case 'sha384': return createSha('SHA384'); case 'sha512': return createSha('SHA512'); default: throw new Error('Hash algorithm not supported'); } } module.exports = { createHash: createHash, CryptoJS: CryptoJS, Buffer: Buffer, sha256: function sha256() { return createHash('sha256'); }, sha224: function sha224() { return createHash('sha224'); }, sha384: function sha384() { return createHash('sha384'); }, sha512: function sha512() { return createHash('sha512'); } }; }).call(this)}).call(this,require("buffer").Buffer) },{"buffer":20,"crypto-js/core":24,"crypto-js/lib-typedarrays":25,"crypto-js/sha224":26,"crypto-js/sha256":27,"crypto-js/sha384":28,"crypto-js/sha512":29}],4:[function(require,module,exports){ 'use strict'; if (typeof window === 'undefined') { throw new Error('This module is not meant to be used by node'); } var isSHA256 = function isSHA256(hash) { return (/^[a-f0-9]{64}$/i.test(hash) ); }; var crypto = require('./woleet-crypto'); var root = window; var isNativeCryptoSupported = root.crypto && root.crypto.subtle && root.crypto.subtle.digest; var defaultWorkerScriptPath = function () { var DEFAULT_WORKER_SCRIPT = "woleet-hashfile-worker.min.js"; var scripts = document.getElementsByTagName('script'); var scriptPath = scripts[scripts.length - 1].src.split('?')[0]; var basePath = scriptPath.split('/').slice(0, -1).join('/') + '/'; var wsp = root.woleet && root.woleet.workerScriptPath ? root.woleet.workerScriptPath : basePath ? basePath + DEFAULT_WORKER_SCRIPT : null; if (!wsp) { console.error('Cannot find Woleet WebLibs\' default worker script ' + DEFAULT_WORKER_SCRIPT); return null; } console.log('Woleet WebLibs\' default worker script will be loaded from: ', wsp); return wsp; }(); function isFileReachable(url) { var req = new XMLHttpRequest(); return new Promise(function (resolve) { req.onload = function () { return resolve(req.status === 200); }; req.onerror = function () { return resolve(false); }; req.open("GET", url, true); req.send(); }).catch(function () { return false; }); } function Hasher(wsp) { if (!wsp) wsp = defaultWorkerScriptPath; var ready = true; var cancel = null; var skip = null; var _events = {}; var EVT_START = 'start', EVT_PROGRESS = 'progress', EVT_ERROR = 'error', EVT_RESULT = 'result', EVT_CANCEL = 'cancel', EVT_SKIP = 'skip'; var emit = function emit(event, data) { return _events[event] && _events[event](data); }; var emittable = function emittable(event) { return _events[event]; }; var _onCancel = function _onCancel(cb) { return cancel = cb; }; var _onSkip = function _onSkip(cb) { return skip = cb; }; var CANCEL_EXCEPTION = '__cancel__'; var SKIP_EXCEPTION = '__skip__'; var HASH_LOCAL_LIMIT = 134217728; var HASH_NATIVE_LIMIT = 1073741824; function HashWorker(wsp) { var worker = new Worker(wsp); this.hash = function (file) { return new Promise(function (next, reject) { var cancelled = false; var skipped = false; var reader = new FileReader(); _onCancel(function () { cancelled = true; worker.terminate(); reader.abort(); worker = null; emit(EVT_CANCEL, { file: file }); reject(CANCEL_EXCEPTION); }); _onSkip(function () { skipped = true; reader.abort(); worker.postMessage({ action: 'reset' }); }); var min = function min(a, b) { return a > b ? b : a; }; var bufferSize = 0xfffff, fileSize = file.size; var start = 0, stop = 0; worker.onmessage = function (event) { if (cancelled) { return; } else if (event.data.reset) { emit(EVT_SKIP, { file: file }); reject(SKIP_EXCEPTION); return; } else if (skipped) { return; } else if (event.data.result) { emit(EVT_RESULT, { result: event.data.result, file: file }); return next(); } else if (event.data.error) { var message = event.data.error; reader.abort(); if (emittable(EVT_ERROR)) emit(EVT_ERROR, { error: new Error(message), file: file });else return reject(new Error(message)); } else if (event.data.start) { emit(EVT_START, { start: event.data.start, file: file }); } else if (event.data.progress) { emit(EVT_PROGRESS, { progress: stop / fileSize, file: file }); } else { console.trace("Unexpected worker message: ", event); } if (stop !== fileSize) { start = stop; stop = min(stop + bufferSize, fileSize); reader.readAsArrayBuffer(file.slice(start, stop)); } else { worker.postMessage({ action: 'finalize' }); } }; reader.onload = function (event) { worker.postMessage({ chunk: event.target.result, action: 'update' }); }; worker.postMessage({ action: 'start' }); }); }; this.worker = worker; } function checkFileSize(file, limit, reject) { if (file.size > limit) { ready = true; var error = new Error("file_too_big_to_be_hashed_without_worker"); if (emittable(EVT_ERROR)) return emit(EVT_ERROR, { error: error, file: file });else reject(error); return false; } return true; } function hashLocal(file) { return new Promise(function (next, reject) { if (!checkFileSize(file, HASH_LOCAL_LIMIT, reject)) return; var prev = 0; var cancelled = false; var skipped = false; var report_update = false; var sha256 = crypto.sha256(); var reader = new FileReader(); function update(buffer, loaded) { var blob = buffer.slice(prev, loaded); var chunkUint8 = new Uint8Array(blob); sha256.update(chunkUint8); prev = loaded; } _onCancel(function () { cancelled = true; reader.abort(); emit(EVT_CANCEL, { file: file }); }); _onSkip(function () { skipped = true; reader.abort(); emit(EVT_SKIP, { file: file }); }); reader.onloadstart = function () { if (cancelled || skipped) return; emit(EVT_START, { start: true, file: file }); }; reader.onload = function (event) { if (cancelled || skipped) return; if (report_update) { update(event.target.result, event.loaded, event.total); } var result = sha256.digest('hex'); emit(EVT_RESULT, { result: result, file: file }); next(); }; reader.onprogress = function (event) { if (cancelled || skipped) return; var data = event.target.result; emit(EVT_PROGRESS, { progress: event.loaded / event.total, file: file }); if (!data) return report_update = true; update(data, event.loaded, event.total); }; reader.onabort = function () { if (cancelled) { reject(CANCEL_EXCEPTION); } else if (skipped) { reject(SKIP_EXCEPTION); } else { reject(new Error('Unhandled abort exception')); } }; reader.readAsArrayBuffer(file); }); } function hashLocalWithNativeAPI(file) { return new Promise(function (resolve, reject) { if (!checkFileSize(file, HASH_NATIVE_LIMIT, reject)) return; var alg = "SHA-256"; var cancelled = false; var skipped = false; var reader = new FileReader(); _onCancel(function () { cancelled = true; reader.abort(); emit(EVT_CANCEL, { file: file }); }); _onSkip(function () { skipped = true; reader.abort(); emit(EVT_SKIP, { file: file }); }); reader.onloadstart = function () { if (cancelled || skipped) return; emit(EVT_START, { start: true, file: file }); }; reader.onprogress = function (event) { if (cancelled || skipped) return; emit(EVT_PROGRESS, { progress: event.loaded / event.total, file: file }); }; reader.onload = function (event) { if (cancelled || skipped) return; var data = event.target.result; root.crypto.subtle.digest(alg, data).then(function (hash) { if (cancelled || skipped) return; var hashResult = new Uint8Array(hash); var result = hashResult.reduce(function (res, e) { return res + ('00' + e.toString(16)).slice(-2); }, ''); emit(EVT_RESULT, { result: result, file: file }); resolve(); }).catch(function (error) { return _events[EVT_ERROR] ? emit(EVT_ERROR, { error: error, file: file }) : reject(error); }); }; reader.onabort = function () { if (cancelled) { reject(CANCEL_EXCEPTION); } else if (skipped) { reject(SKIP_EXCEPTION); } else { reject(new Error('Unhandled abort exception')); } }; reader.readAsArrayBuffer(file); }); } this.on = function (event, callback) { switch (event) { case EVT_START: case EVT_PROGRESS: case EVT_ERROR: case EVT_RESULT: case EVT_SKIP: case EVT_CANCEL: _events[event] = callback; break; default: throw new Error('Invalid event name "' + event + '"'); } }; this.start = function (files) { var hashWorker = null; if (!ready) throw new Error("not_ready"); ready = false; if (!(files instanceof FileList || files instanceof File || Array.isArray(files) && files.every(function (file) { return file instanceof File; }))) throw new Error("invalid_parameter"); var isWorkerSupportedPromise = function () { if (!wsp) return Promise.resolve(false); var workerReachablePromise = isFileReachable(wsp); var cryptoReachablePromise = isFileReachable(wsp.split('/').slice(0, -1).join('/') + '/woleet-crypto.min.js'); function makeWorker(script) { var URL = root.URL || window.webkitURL; var Blob = root.Blob; var Worker = root.Worker; if (!URL || !Blob || !Worker || !script) return null; var blob = new Blob([script]); return new Worker(URL.createObjectURL(blob)); } var workerSupportedPromise = new Promise(function (resolve) { var syncDetectionScript = "onmessage = function(e) { postMessage(!!FileReaderSync); close() };"; try { var worker = makeWorker(syncDetectionScript); if (worker) { worker.onmessage = function (e) { worker.terminate(); worker = null; resolve(e.data); }; worker.postMessage({}); } else { resolve(false); } } catch (error) { resolve(false); } }); return Promise.all([workerReachablePromise, cryptoReachablePromise, workerSupportedPromise]).then(function (arr) { return arr.every(function (e) { return true === e; }); }); }().then(function (support) { if (!support) console.warn('Failed to load worker.'); return support; }); isWorkerSupportedPromise.then(function (workerSupported) { function iter(i, len, files) { if (i >= len) { ready = true; if (hashWorker && hashWorker.worker) { hashWorker.worker.terminate(); hashWorker.worker = null; } return Promise.resolve(); } else { var hashMethod = void 0; if (files[i].size === 0) { hashMethod = hashLocal; } else if (isNativeCryptoSupported && files[i].size <= HASH_NATIVE_LIMIT) { hashMethod = hashLocalWithNativeAPI; } else if (workerSupported && files[i].size > HASH_LOCAL_LIMIT) { if (!hashWorker) hashWorker = new HashWorker(wsp); hashMethod = hashWorker.hash; } else { hashMethod = hashLocal; } return hashMethod(files[i]).then(function () { return iter(i + 1, len, files); }).catch(function (error) { if (error === SKIP_EXCEPTION) return iter(i + 1, len, files); if (error !== CANCEL_EXCEPTION) throw error; }); } } if (files instanceof FileList) { return iter(0, files.length, files); } else if (files instanceof File) { return iter(0, 1, [files]); } else { return iter(0, files.length, files); } }); }; this.cancel = function () { if (cancel) { cancel(); cancel = null; ready = true; } }; this.skip = function () { if (cancel) { skip(); skip = null; } }; this.isReady = function () { return ready; }; } function hashFileOrCheckHash(file, progressCallback) { return new Promise(function (resolve, reject) { if (file instanceof File) { var hasher = new Hasher(); hasher.on('result', function (message, file) { resolve(message.result); if (progressCallback) progressCallback({ progress: 1.0, file: file }); }); if (progressCallback && typeof progressCallback === 'function') hasher.on('progress', progressCallback); hasher.on('error', reject); hasher.start(file); } else if (typeof file === 'string') { if (isSHA256(file)) resolve(file);else reject(new Error("parameter_string_not_a_sha256_hash")); } else reject(new Error("invalid_parameter")); }); } module.exports = { Hasher: Hasher, hashFileOrCheckHash: hashFileOrCheckHash }; },{"./woleet-crypto":3}],5:[function(require,module,exports){ 'use strict'; var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); module.exports = function (getJSON) { var woleet = { receipt: {}, identity: {} }; function dataToURI(data) { if (!data || Object.keys(data).length === 0) return ''; var _data = []; for (var prop in data) { if (data[prop]) _data.push([encodeURIComponent(prop), encodeURIComponent(data[prop])].join('=')); } return "?" + _data.join('&'); } function makeTransaction(txId, confirmations, timestamp, blockHash, opReturn) { if (timestamp.toString() === 'Invalid Date') timestamp = null; return { txId: txId, confirmations: confirmations, timestamp: timestamp, blockHash: blockHash, opReturn: opReturn }; } var DEFAULT_WOLEET_API_URL = "https://api.woleet.io/v1"; var woleetApiUrl = DEFAULT_WOLEET_API_URL; var DEFAULT_TRANSACTION_PROVIDER = 'woleet.io'; var transactionProvider = DEFAULT_TRANSACTION_PROVIDER; woleet.config = { setDefaultTransactionProvider: function setDefaultTransactionProvider(_transactionProvider) { switch (_transactionProvider) { case 'blockcypher.com': case 'blockstream.info': case 'woleet.io': transactionProvider = _transactionProvider; break; default: transactionProvider = DEFAULT_TRANSACTION_PROVIDER; break; } }, setDefaultWoleetApiUrl: function setDefaultWoleetApiUrl(_woleetApiUrl) { woleetApiUrl = _woleetApiUrl; } }; woleet.transaction = { get: function get(txId) { switch (transactionProvider) { case 'woleet.io': return getJSON(woleetApiUrl + '/bitcoin/transaction/' + txId).then(function (tx) { if (!tx.time || !tx.confirmations) { throw new Error('tx_not_confirmed'); } return makeTransaction(tx.txid, tx.confirmations, new Date(tx.time * 1000), tx.blockhash, function (output) { return output ? output.scriptPubKey.asm.split(' ')[1] : null; }((tx.vout || []).find(function (o) { return o.hasOwnProperty('scriptPubKey') && o.scriptPubKey.hasOwnProperty('asm') && o.scriptPubKey.asm.startsWith('OP_RETURN'); }))); }).catch(function () { throw new Error('tx_not_found'); }); case 'blockstream.info': return getJSON('https://blockstream.info/api/tx/' + txId).then(function (tx) { if (!tx.status.block_hash) { throw new Error('tx_not_confirmed'); } return getJSON('https://blockstream.info/api/blocks/tip/height').then(function (tipHeight) { return getJSON('https://blockstream.info/api/block/' + tx.status.block_hash).then(function (block) { return makeTransaction(txId, tipHeight - block.height, new Date(block.timestamp * 1000), block.id, function (output) { return output ? output.scriptpubkey_asm.split(' ')[2] : null; }((tx.vout || []).find(function (o) { return o.hasOwnProperty('scriptpubkey') && o.scriptpubkey_asm && o.scriptpubkey_asm.startsWith('OP_RETURN'); }))); }).catch(function (error) { throw new Error('Failed to get block'); }); }).catch(function (error) { throw new Error('Failed to get current block height'); }); }).catch(function (error) { throw new Error('tx_not_found'); }); case 'blockcypher.com': return getJSON('https://api.blockcypher.com/v1/btc/main/txs/' + txId).then(function (tx) { if (tx.error) { throw new Error('tx_not_found'); } if (!tx.confirmed || !tx.confirmations) { throw new Error('tx_not_confirmed'); } return makeTransaction(tx.hash, tx.confirmations, new Date(tx.confirmed), tx.block_hash, function (output) { return output ? output.data_hex : null; }((tx.outputs || []).find(function (o) { return o.hasOwnProperty('data_hex'); }))); }).catch(function () { throw new Error('tx_not_found'); }); } } }; var _types = { DATA: 1, SIGNATURE: 2, BOTH: 3 }; woleet.anchor = { types: _types, getAnchorIDs: function getAnchorIDs(hash, type, size) { switch (type) { case _types.SIGNATURE: return getJSON(woleetApiUrl + '/anchorids' + dataToURI({ signedHash: hash, size: size })).then(function (res) { return res.content || []; }).catch(function (error) { throw new Error('http_error'); }); case _types.DATA: return getJSON(woleetApiUrl + '/anchorids' + dataToURI({ hash: hash, size: size })).then(function (res) { return res.content || []; }).catch(function (error) { throw new Error('http_error'); }); case _types.BOTH: default: var a = woleet.anchor.getAnchorIDs(hash, _types.SIGNATURE, size); var b = woleet.anchor.getAnchorIDs(hash, _types.DATA, size); return Promise.all([a, b]).then(function (_ref) { var _ref2 = _slicedToArray(_ref, 2), a = _ref2[0], b = _ref2[1]; if (a instanceof Error || b instanceof Error) throw new Error('http_error'); return [].concat(a, b); }); } } }; woleet.receipt.get = function (anchorId) { return getJSON(woleetApiUrl + "/receipt/" + anchorId).catch(function (error) { if (error.code === 404) throw new Error('not_found');else throw new Error(error.code); }); }; woleet.identity.get = function (identityUrl, pubKey, signedIdentity, leftData) { return getJSON(identityUrl + dataToURI({ pubKey: pubKey, signedIdentity: signedIdentity, leftData: leftData })).catch(function (error) { if (error.code === 404) { throw new Error('key_not_found'); } else if (error.code === 400 || error.code === 0) { throw new Error('http_error'); } else { throw new Error(error.code); } }); }; woleet.isSHA256 = function (hash) { return (/^[a-f0-9]{64}$/i.test(hash) ); }; woleet.getJSON = getJSON; return woleet; }; },{}],6:[function(require,module,exports){ 'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; module.exports = function (crypto) { var INVALID_RECEIPT_FORMAT = 'invalid_receipt_format', INVALID_TARGET_PROOF = 'invalid_target_proof', INVALID_TYPE = 'invalid_type', NON_SHA256_TARGET_PROOF_ELEMENT = 'non_sha256_target_proof_element', MERKLE_ROOT_MISMATCH = 'merkle_root_mismatch', INVALID_PARENT_IN_PROOF_ELEMENT = 'invalid_parent_in_proof_element', UNSUPPORTED_ALGORITHM = 'unsupported_algorithm'; var isHex = function isHex(len) { var reg = new RegExp('^[a-f0-9]{' + len + '}$', 'i'); return function (hash) { return reg.test(hash); }; }; var isSHA256 = isHex(64); var sha224 = crypto.sha224; var sha256 = crypto.sha256; var sha384 = crypto.sha384; var sha512 = crypto.sha512; function MerkleProof(target) { var self = this; this.branches = []; this.target = target; this.add = function (branch) { self.branches.push(branch); }; this.is_valid = function (root) { var target = self.target; if (!self.branches.length) return false; for (var i = 0, branch; i < self.branches.length; i++) { branch = self.branches[i]; if (!(target === branch.left || target === branch.right)) { return false; } target = branch.parent; } return target.toLowerCase() === root.toLowerCase(); }; this.getJSON = function () { return self.branches.map(function (branch) { return branch.getJSON(); }); }; } function hasAllProperties(obj) { for (var _len = arguments.length, props = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { props[_key - 1] = arguments[_key]; } var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = props[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var prop = _step.value; if (prop instanceof Array) { if (!obj.hasOwnProperty(prop[0])) return false;else if (typeof prop[1] === 'string') { if (!(_typeof(obj[prop[0]]) === prop[1])) return false; } else { if (!(obj[prop[0]] instanceof prop[1])) return false; } } else { if (!obj.hasOwnProperty(prop) || typeof obj[prop] !== 'string') { return false; } } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return true; } function _validateChainpoint1Receipt(receipt) { if (!hasAllProperties(receipt, ['header', 'object'], ['target', 'object'])) throw new Error(INVALID_RECEIPT_FORMAT); if (!hasAllProperties(receipt.header, 'chainpoint_version', 'hash_type', 'merkle_root', 'tx_id', ['timestamp', 'number'])) throw new Error(INVALID_RECEIPT_FORMAT); if (!hasAllProperties(receipt.target, 'target_hash', ['target_proof', Array])) throw new Error(INVALID_RECEIPT_FORMAT); if (!receipt.target.target_proof.every(function (branch) { return hasAllProperties(branch, 'left', 'right', 'parent'); })) throw new Error(INVALID_TARGET_PROOF); if (!receipt.target.target_proof.every(function (branch) { return isSHA256(branch.left) && isSHA256(branch.right) && isSHA256(branch.parent); })) throw new Error(NON_SHA256_TARGET_PROOF_ELEMENT); if (receipt.target.target_proof.length === 0) { if (receipt.target.target_hash.toLowerCase() === receipt.header.merkle_root.toLowerCase()) return true;else throw new Error(MERKLE_ROOT_MISMATCH); } else { var proof = new MerkleProof(receipt.target.target_hash); receipt.target.target_proof.forEach(function (branch) { var parent = sha256().update(branch.left + branch.right, 'utf8').digest('hex'); if (parent !== branch.parent) { throw new Error(INVALID_PARENT_IN_PROOF_ELEMENT); } proof.add({ left: branch.left, right: branch.right, parent: parent }); }); if (proof.is_valid(receipt.header.merkle_root)) return true;else throw new Error(MERKLE_ROOT_MISMATCH); } } function _validateChainpoint2Receipt(receipt) { if (!hasAllProperties(receipt, 'targetHash', 'merkleRoot', ['proof', Array], ['anchors', Array])) { throw new Error(INVALID_RECEIPT_FORMAT); } if (!(receipt.hasOwnProperty('@context') || receipt.hasOwnProperty('context') && receipt.hasOwnProperty('@type') || receipt.hasOwnProperty('type'))) { throw new Error(INVALID_RECEIPT_FORMAT); } var type = receipt.type || receipt['@type']; if (typeof type !== 'string' || !/^ChainpointSHA([0-9]-)?[0-9]{3}v2$/.test(type)) { throw new Error(INVALID_RECEIPT_FORMAT); } var shaX = null; var validateHex = null; switch (type) { case "ChainpointSHA224v2": shaX = sha224; validateHex = isHex(56); break; case "ChainpointSHA256v2": shaX = sha256; validateHex = isHex(64); break; case "ChainpointSHA384v2": shaX = sha384; validateHex = isHex(96); break; case "ChainpointSHA512v2": shaX = sha512; validateHex = isHex(128); break; case "ChainpointSHA3-224v2": case "ChainpointSHA3-256v2": case "ChainpointSHA3-384v2": case "ChainpointSHA3-512v2": throw new Error(UNSUPPORTED_ALGORITHM); default: throw new Error(INVALID_TYPE); } var xor = function xor(a, b) { return a ? !b : b; }; if (!receipt.proof.every(function (branch) { return xor(branch.hasOwnProperty('left'), branch.hasOwnProperty('right')); })) throw new Error(INVALID_TARGET_PROOF); if (!receipt.proof.every(function (branch) { return validateHex(branch.left || branch.right); })) throw new Error(NON_SHA256_TARGET_PROOF_ELEMENT); if (receipt.proof.length === 0) { if (receipt.targetHash.toLowerCase() === receipt.merkleRoot.toLowerCase()) return true;else throw new Error(MERKLE_ROOT_MISMATCH); } else { var proof = new MerkleProof(receipt.targetHash); var target = receipt.targetHash; receipt.proof.forEach(function (branch) { var left = void 0, right = void 0; if (branch.left) { left = branch.left; right = target; } else { left = target; right = branch.right; } var parent = shaX().update(left + right, 'hex').digest('hex'); target = parent; proof.add({ left: left, right: right, parent: parent }); }); if (proof.is_valid(receipt.merkleRoot)) return true;else throw new Error(MERKLE_ROOT_MISMATCH); } } function validateReceipt(receipt) { if (!receipt || (typeof receipt === 'undefined' ? 'undefined' : _typeof(receipt)) !== 'object') throw new Error(INVALID_RECEIPT_FORMAT); if (receipt.hasOwnProperty('header')) { return _validateChainpoint1Receipt(receipt); } else { return _validateChainpoint2Receipt(receipt); } } return validateReceipt; }; },{}],7:[function(require,module,exports){ (function (Buffer){(function (){ 'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; module.exports = function (getIdentity) { var messagePrefix = '\x18Bitcoin Signed Message:\n'; var verify = require('bitcoinjs-message').verify; function checkIdentities(identity, signedIdentity) { if (!signedIdentity) return { valid: true, identity: identity }; signedIdentity = deserializeX500DN(signedIdentity); if (signedIdentity.commonName !== identity.commonName || signedIdentity.emailAddress && identity.emailAddress && signedIdentity.emailAddress !== identity.emailAddress) { return { valid: false, reason: "identity_mismatch" }; } return { valid: true, identity: identity, signedIdentity: signedIdentity }; } function deserializeX500DN(x500dn) { function splitUnescaped(delim, str) { var result = []; var previousChar = void 0; var start = 0; for (var i = 0; i < str.length; i++) { var currentChar = str.charAt(i); if (currentChar === delim && previousChar !== '\\') { result.push(str.slice(start, i)); i++; start = i; } if (i >= str.length - 1) { result.push(str.slice(start, i + 1)); } previousChar = currentChar; } return result; } var identity = {}; var attrs = splitUnescaped(',', x500dn); attrs.forEach(function (attr) { var keyValue = splitUnescaped('=', attr); var key = keyValue[0]; var value = keyValue[1].replace("\\ ", " ") .replace("\\=", "=") .replace("\\\"", "\"") .replace("\\,", ",") .replace("\\;", ";") .replace("\\+", "+"); switch (key.toUpperCase().trim()) { case 'CN': identity.commonName = value; break; case 'EMAILADDRESS': identity.emailAddress = value; break; case 'O': identity.organization = value; break; case 'OU': identity.organizationalUnit = value; break; case 'L': identity.locality = value; break; case 'C': identity.country = value; break; } }); return identity; } function randomString(len) { var l = 0; var a = []; while (l++ < len) { a.push(Math.floor(Math.random() * 0xff)); }return new Buffer(a).toString('hex'); } function validateIdentity(identityUrl, pubKey, signedIdentity, signedIssuerDomain) { if (!identityUrl) { if (!signedIdentity) { return Promise.resolve({ valid: false }); } return Promise.resolve({ valid: true, signedIdentity: deserializeX500DN(signedIdentity) }); } if (signedIssuerDomain && !new URL(identityUrl).hostname.includes(signedIssuerDomain)) { return Promise.resolve({ valid: false, reason: "identity_mismatch" }); } var leftData = randomString(16); return getIdentity(identityUrl, pubKey, signedIdentity, leftData).then(function (identity) { if (!identity || (typeof identity === 'undefined' ? 'undefined' : _typeof(identity)) != 'object') { return { valid: false, reason: "invalid response" }; } if (!identity.signature) { if (!identity.identity) { return { valid: false, reason: "'identity' should be provided'" }; } return checkIdentities(identity.identity, signedIdentity); } else { if (!identity.rightData.startsWith(identityUrl)) { return { valid: false, reason: '\'rightData\' should start with \'' + identityUrl + '\'' }; } return validateSignature(leftData + identity.rightData, pubKey, identity.signature).then(function (result) { if (!result.valid) { return result; } return checkIdentities(identity.identity, signedIdentity); }); } }) .catch(function (error) { if (error.message === 'key_not_found') { return { valid: false, reason: error.message }; } if (!signedIdentity) { return Promise.resolve({ valid: false, reason: error.message }); } return Promise.resolve({ valid: true, signedIdentity: deserializeX500DN(signedIdentity) }); }); } function validateSignature(message, address, signature) { try { return Promise.resolve({ valid: verify(message, address, signature, messagePrefix) }); } catch (error) { return Promise.resolve({ valid: false, reason: error.message }); } } return { validateSignature: validateSignature, validateIdentity: validateIdentity, deserializeX500DN: deserializeX500DN }; }; }).call(this)}).call(this,require("buffer").Buffer) },{"bitcoinjs-message":13,"buffer":20}],8:[function(require,module,exports){ "use strict"; module.exports = function (woleet) { function validateSignatureAndIdentity(verification) { return Promise.resolve(verification).then(function (verification) { var s = verification.receipt.signature; if (!s) { return verification; } if (!s.signature || !s.signedHash || !s.pubKey) { throw new Error('invalid_receipt_signature_format'); } var message = s.signedHash; if (s.signedIdentity || s.signedIssuerDomain) { message = woleet.crypto.sha256().update(s.signedHash + (s.signedIdentity || "") + (s.signedIssuerDomain || "")).digest('hex'); } return woleet.signature.validateSignature(message, s.pubKey, s.signature).then(function (res) { if (!res.valid) { throw new Error('invalid_receipt_signature'); } return woleet.signature.validateIdentity(s.identityURL, s.pubKey, s.signedIdentity, s.signedIssuerDomain).then(function (res) { if (!res.valid) { verification.identityVerificationStatus = { code: res.reason, identity: res.identity, signedIdentity: res.signedIdentity }; } else { verification.identityVerificationStatus = { code: 'verified', identity: res.identity, signedIdentity: res.signedIdentity }; } return verification; }).catch(function (error) { verification.identityVerificationStatus = { code: error.message }; return verification; }); }); }); } function validateTransaction(receipt) { var getReceiptTxId = function getReceiptTxId(receipt) { return receipt.header && receipt.header.tx_id || receipt.anchors && receipt.anchors.find(function (e) { return e.type === "BTCOpReturn"; }).sourceId; }; return woleet.transaction.get(getReceiptTxId(receipt)).then(function (tx) { if (tx.opReturn === (receipt.header && receipt.header.merkle_root || receipt.merkleRoot)) { return { receipt: receipt, confirmations: tx.confirmations, timestamp: tx.timestamp, code: 'verified' }; } else { throw new Error('op_return_mismatches_merkle_root'); } }); } function compareTargetHash(receipt, hash) { if (receipt.signature) { if (receipt.signature.signedHash !== hash) { throw new Error("target_hash_mismatch"); } } else { if ((receipt.target && receipt.target.target_hash || receipt.targetHash) !== hash) { throw new Error("target_hash_mismatch"); } } } function WoleetDAB(file, progressCallback) { return woleet.file.hashFileOrCheckHash(file, progressCallback) .then(function (hash) { return woleet.anchor.getAnchorIDs(hash, woleet.anchor.types.BOTH); }) .then(function (anchorIDArray) { var receiptArray = []; return anchorIDArray.reduce(function (chain, anchorId) { return chain.then(function () { return woleet.receipt.get(anchorId).then(function (receipt) { receiptArray.push(receipt); }).catch(function (error) { if (error.message !== '202') { throw error; } }); }); }, Promise.resolve()) .then(function () { if (anchorIDArray.length && !receiptArray.length) { throw new Error('file_matched_but_anchor_not_yet_processed'); } return receiptArray; }); }) .then(function (receiptArray) { var finalArray = []; return receiptArray.reduce(function (chain, receipt) { return chain.then(function () { return verifyReceipt(receipt).then(function (validation) { finalArray.push(validation); }).catch(function (error) { finalArray.push({ receipt: receipt, code: error.message }); }); }); }, Promise.resolve()) .then(function () { return finalArray.sort(function (a, b) { if (!a.timestamp) return 1; if (!b.timestamp) return -1; if (a.timestamp && b.timestamp) { return a.timestamp.getTime() - b.timestamp.getTime(); } return 0; }); }); }); } function DAB(file, receipt, progressCallback) { return woleet.file.hashFileOrCheckHash(file, progressCallback).then(function (hash) { return verifyReceipt(receipt, hash); }); } function verifyReceipt(receipt, hash) { return Promise.resolve().then(function () { return woleet.receipt.validate(receipt); }).then(function () { if (hash) compareTargetHash(receipt, hash); }).then(function () { return validateTransaction(receipt); }).then(validateSignatureAndIdentity).catch(function (error) { return { receipt: receipt, code: error.message }; }); } return { WoleetDAB: WoleetDAB, DAB: DAB, receipt: verifyReceipt }; }; },{}],9:[function(require,module,exports){ 'use strict' var _Buffer = require('safe-buffer').Buffer function base (ALPHABET) { if (ALPHABET.length >= 255) { throw new TypeError('Alphabet too long') } var BASE_MAP = new Uint8Array(256) for (var j = 0; j < BASE_MAP.length; j++) { BASE_MAP[j] = 255 } for (var i = 0; i < ALPHABET.length; i++) { var x = ALPHABET.charAt(i) var xc = x.charCodeAt(0) if (BASE_MAP[xc] !== 255) { throw new TypeError(x + ' is ambiguous') } BASE_MAP[xc] = i } var BASE = ALPHABET.length var LEADER = ALPHABET.charAt(0) var FACTOR = Math.log(BASE) / Math.log(256) var iFACTOR = Math.log(256) / Math.log(BASE) function encode (source) { if (Array.isArray(source) || source instanceof Uint8Array) { source = _Buffer.from(source) } if (!_Buffer.isBuffer(source)) { throw new TypeError('Expected Buffer') } if (source.length === 0) { return '' } var zeroes = 0 var length = 0 var pbegin = 0 var pend = source.length while (pbegin !== pend && source[pbegin] === 0) { pbegin++ zeroes++ } var size = ((pend - pbegin) * iFACTOR + 1) >>> 0 var b58 = new Uint8Array(size) while (pbegin !== pend) { var carry = source[pbegin] var i = 0 for (var it1 = size - 1; (carry !== 0 || i < length) && (it1 !== -1); it1--, i++) { carry += (256 * b58[it1]) >>> 0 b58[it1] = (carry % BASE) >>> 0 carry = (carry / BASE) >>> 0 } if (carry !== 0) { throw new Error('Non-zero carry') } length = i pbegin++ } var it2 = size - length while (it2 !== size && b58[it2] === 0) { it2++ } var str = LEADER.repeat(zeroes) for (; it2 < size; ++it2) { str += ALPHABET.charAt(b58[it2]) } return str } function decodeUnsafe (source) { if (typeof source !== 'string') { throw new TypeError('Expected String') } if (source.length === 0) { return _Buffer.alloc(0) } var psz = 0 var zeroes = 0 var length = 0 while (source[psz] === LEADER) { zeroes++ psz++ } var size = (((source.length - psz) * FACTOR) + 1) >>> 0 var b256 = new Uint8Array(size) while (source[psz]) { var carry = BASE_MAP[source.charCodeAt(psz)] if (carry === 255) { return } var i = 0 for (var it3 = size - 1; (carry !== 0 || i < length) && (it3 !== -1); it3--, i++) { carry += (BASE * b256[it3]) >>> 0 b256[it3] = (carry % 256) >>> 0 carry = (carry / 256) >>> 0 } if (carry !== 0) { throw new Error('Non-zero carry') } length = i psz++ } var it4 = size - length while (it4 !== size && b256[it4] === 0) { it4++ } var vch = _Buffer.allocUnsafe(zeroes + (size - it4)) vch.fill(0x00, 0, zeroes) var j = zeroes while (it4 !== size) { vch[j++] = b256[it4++] } return vch } function decode (string) { var buffer = decodeUnsafe(string) if (buffer) { return buffer } throw new Error('Non-base' + BASE + ' character') } return { encode: encode, decodeUnsafe: decodeUnsafe, decode: decode } } module.exports = base },{"safe-buffer":103}],10:[function(require,module,exports){ 'use strict' exports.byteLength = byteLength exports.toByteArray = toByteArray exports.fromByteArray = fromByteArray var lookup = [] var revLookup = [] var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' for (var i = 0, len = code.length; i < len; ++i) { lookup[i] = code[i] revLookup[code.charCodeAt(i)] = i } revLookup['-'.charCodeAt(0)] = 62 revLookup['_'.charCodeAt(0)] = 63 function getLens (b64) { var len = b64.length if (len % 4 > 0) { throw new Error('Invalid string. Length must be a multiple of 4') } var validLen = b64.indexOf('=') if (validLen === -1) validLen = len var placeHoldersLen = validLen === len ? 0 : 4 - (validLen % 4) return [validLen, placeHoldersLen] } function byteLength (b64) { var lens = getLens(b64) var validLen = lens[0] var placeHoldersLen = lens[1] return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen } function _byteLength (b64, validLen, placeHoldersLen) { return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen } function toByteArray (b64) { var tmp var lens = getLens(b64) var validLen = lens[0] var placeHoldersLen = lens[1] var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) var curByte = 0 var len = placeHoldersLen > 0 ? validLen - 4 : validLen var i for (i = 0; i < len; i += 4) { tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)] arr[curByte++] = (tmp >> 16) & 0xFF arr[curByte++] = (tmp >> 8) & 0xFF arr[curByte++] = tmp & 0xFF } if (placeHoldersLen === 2) { tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4) arr[curByte++] = tmp & 0xFF } if (placeHoldersLen === 1) { tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2) arr[curByte++] = (tmp >> 8) & 0xFF arr[curByte++] = tmp & 0xFF } return arr } function tripletToBase64 (num) { return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F] } function encodeChunk (uint8, start, end) { var tmp var output = [] for (var i = start; i < end; i += 3) { tmp = ((uint8[i] << 16) & 0xFF0000) + ((uint8[i + 1] << 8) & 0xFF00) + (uint8[i + 2] & 0xFF) output.push(tripletToBase64(tmp)) } return output.join('') } function fromByteArray