UNPKG

@blockcerts/hashlink-verifier

Version:
99 lines (98 loc) 4.57 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { Hashlink } from './hashlink/Hashlink'; import * as codecs from './hashlink/codecs'; export class HashlinkVerifier { constructor() { this.hashlinkTable = {}; // keep decoded hashlinks in memory this.hl = new Hashlink(); this.hl.use(new codecs.MultihashSha2256()); this.hl.use(new codecs.MultihashBlake2b64()); this.hl.use(new codecs.MultibaseBase58btc()); } /** * decode method, abstract wrapper over Hashlink class from digital bazaar hashlink package * * @param {string} hashlink: the hashlink to be decoded. In this instance it expects a url to be specified. * @param {function} onHashlinkUrlDecoded: a callback function called when the source url has been discovered to enable * early manipulation (ie: update image in DOM). */ decode(hashlink, onHashlinkUrlDecoded) { return __awaiter(this, void 0, void 0, function* () { var _a; const decodedHashlink = yield this.hl.decode({ hashlink }); // console.log('hashlink decoded', decodedHashlink); if (!decodedHashlink.meta && !((_a = decodedHashlink.meta.url) === null || _a === void 0 ? void 0 : _a.length)) { throw new Error('unparseable document, no url provided as meta data'); } this.hashlinkTable[hashlink] = decodedHashlink; const sourceUrl = decodedHashlink.meta.url[0]; onHashlinkUrlDecoded === null || onHashlinkUrlDecoded === void 0 ? void 0 : onHashlinkUrlDecoded(sourceUrl); return decodedHashlink; }); } verifyHashlinkTable() { return __awaiter(this, void 0, void 0, function* () { const hashlinks = Object.keys(this.hashlinkTable); for (let i = 0; i < hashlinks.length; i++) { yield this.verify(hashlinks[i]) .catch(error => console.log('caught an hashlink exception', error)); } return true; }); } /** * verify method, abstract wrapper over Hashlink class from digital bazaar hashlink package * * @param {string} hashlink: the hashlink to be decoded. It will lookup in the previously decoded hashlinks table. * if not found it will decode the hashlink before verification. */ verify(hashlink) { return __awaiter(this, void 0, void 0, function* () { const sourceUrl = yield this.getSourceUrlFromHashlink(hashlink); let imageData; yield fetch(sourceUrl) .then((response) => __awaiter(this, void 0, void 0, function* () { return yield response.text(); })) .then(data => { imageData = data; }); const textEncoder = new TextEncoder(); const verified = yield this.hl.verify({ data: textEncoder.encode(imageData), // needs an ArrayBuffer hashlink }); if (verified) { console.log(`hashlink ${hashlink} bound to ${sourceUrl} was successfully verified`); } else { throw new Error(`Hashlink ${hashlink} does not match data from url ${sourceUrl}`); } return verified; }); } hasHashlinksToVerify() { return Object.keys(this.hashlinkTable).length > 0; } getSourceUrlFromHashlink(hashlink) { return __awaiter(this, void 0, void 0, function* () { let decodedHashlink; if (this.hashlinkTable[hashlink]) { decodedHashlink = this.hashlinkTable[hashlink]; } else { decodedHashlink = yield this.decode(hashlink); } return this.getMetaUrl(decodedHashlink); }); } getMetaUrl(decodedHashlink) { return decodedHashlink.meta.url[0]; } }