UNPKG

@mdfriday/foundry

Version:

The core engine of MDFriday. Convert Markdown and shortcodes into fully themed static sites – Hugo-style, powered by TypeScript.

113 lines 4.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.IntegrityClient = void 0; const crypto_1 = require("crypto"); const resources_1 = require("../../../domain/resources"); const DEFAULT_HASH_ALGO = 'sha256'; /** * IntegrityClient provides fingerprinting and integrity generation for resources * This implements the Fingerprint operation */ class IntegrityClient { async fingerprint(resource, algo = DEFAULT_HASH_ALGO) { const transformation = new FingerprintTransformation(algo); return resource.transform(transformation); } generateIntegrity(content) { const hash = (0, crypto_1.createHash)('sha256').update(content, 'utf8').digest('base64'); return `sha256-${hash}`; } // Additional integrity methods generateSHA384(content) { const hash = (0, crypto_1.createHash)('sha384').update(content, 'utf8').digest('base64'); return `sha384-${hash}`; } generateSHA512(content) { const hash = (0, crypto_1.createHash)('sha512').update(content, 'utf8').digest('base64'); return `sha512-${hash}`; } // Verify integrity verifyIntegrity(content, integrity) { const [algorithm, expectedHash] = integrity.split('-', 2); let actualHash; switch (algorithm) { case 'sha256': actualHash = (0, crypto_1.createHash)('sha256').update(content, 'utf8').digest('base64'); break; case 'sha384': actualHash = (0, crypto_1.createHash)('sha384').update(content, 'utf8').digest('base64'); break; case 'sha512': actualHash = (0, crypto_1.createHash)('sha512').update(content, 'utf8').digest('base64'); break; default: return false; } return actualHash === expectedHash; } } exports.IntegrityClient = IntegrityClient; class FingerprintTransformation { constructor(algo) { this.algo = algo; } key() { return resources_1.ResourceTransformationKey.newResourceTransformationKey('fingerprint', this.algo); } async transform(ctx) { const hash = this.newHash(this.algo); // Read from source and calculate hash let content = ''; const chunks = []; ctx.source.from.on('data', (chunk) => { hash.update(chunk); chunks.push(chunk); content += chunk.toString(); }); await new Promise((resolve, reject) => { ctx.source.from.on('end', () => { try { const digest = hash.digest(); const hexDigest = digest.toString('hex'); // Set integrity data ctx.data['Integrity'] = this.integrity(this.algo, digest); // Add hash to filename using the standard mechanism // Use only first 12 characters for shorter filenames const shortHash = hexDigest.substring(0, 12); ctx.addOutPathIdentifier('.' + shortHash); // Write content to target for (const chunk of chunks) { ctx.target.to.write(chunk); } ctx.target.to.end(); resolve(); } catch (error) { reject(error); } }); ctx.source.from.on('error', reject); }); } newHash(algo) { switch (algo) { case 'md5': return (0, crypto_1.createHash)('md5'); case 'sha256': return (0, crypto_1.createHash)('sha256'); case 'sha384': return (0, crypto_1.createHash)('sha384'); case 'sha512': return (0, crypto_1.createHash)('sha512'); default: throw new Error(`Unsupported hash algorithm: "${algo}", use either md5, sha256, sha384 or sha512`); } } // Create integrity string for Subresource Integrity // See https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity integrity(algo, digest) { const encoded = digest.toString('base64'); return `${algo}-${encoded}`; } } //# sourceMappingURL=integrity.js.map