// NON ATTIVO: per ora nessuno lo importa (vedi vite-plugins/encrypt-models.js). // // Carica un modello GLB cifrato in build (vedi vite-plugins/encrypt-models.js): scarica il .bin, // lo decifra in memoria con WebCrypto e lo passa al GLTFLoader. Nessun .glb in chiaro passa in rete. // // WebCrypto richiede un contesto sicuro: https, oppure http://localhost. /* global __KREIOS_MK__, __KREIOS_MM__ */ let keyPromise = null; function rawKey() { const masked = __KREIOS_MK__; const mask = __KREIOS_MM__; return Uint8Array.from(masked, (b, i) => b ^ mask[i]); } function getKey() { keyPromise ??= (async () => { const raw = rawKey(); const cryptoKey = await crypto.subtle.importKey('raw', raw, 'AES-GCM', false, ['decrypt']); return { raw, cryptoKey }; })(); return keyPromise; } async function fileName(raw, relPath) { const data = new Uint8Array([...raw, ...new TextEncoder().encode(relPath)]); const digest = new Uint8Array(await crypto.subtle.digest('SHA-256', data)); return [...digest].map((b) => b.toString(16).padStart(2, '0')).join('').slice(0, 32) + '.bin'; } // Scarica con avanzamento, compatibile con il callback di progresso del GLTFLoader ({ loaded, total }). async function download(url, onProgress) { const res = await fetch(url); if (!res.ok) throw new Error(`Modello non disponibile (${res.status})`); const total = Number(res.headers.get('Content-Length')) || 0; if (!res.body || !total) { const buf = await res.arrayBuffer(); onProgress?.({ loaded: buf.byteLength, total: buf.byteLength }); return new Uint8Array(buf); } const out = new Uint8Array(total); const reader = res.body.getReader(); let loaded = 0; for (;;) { const { done, value } = await reader.read(); if (done) break; out.set(value, loaded); loaded += value.length; onProgress?.({ loaded, total }); } return out.subarray(0, loaded); } /** * @param {import('three/examples/jsm/loaders/GLTFLoader').GLTFLoader} loader * @param {string} relPath percorso sotto assets/models, es. "pvc/finestra_1_anta.glb" */ export async function caricaModelloCifrato(loader, relPath, onProgress) { const { raw, cryptoKey } = await getKey(); const data = await download(`./assets/m/${await fileName(raw, relPath)}`, onProgress); const glb = await crypto.subtle.decrypt( { name: 'AES-GCM', iv: data.subarray(0, 12), additionalData: new TextEncoder().encode(relPath) }, cryptoKey, data.subarray(12), ); const dir = relPath.includes('/') ? relPath.slice(0, relPath.lastIndexOf('/') + 1) : ''; return loader.parseAsync(glb, `./assets/models/${dir}`); } /** Stessa firma di GLTFLoader.load, ma su modelli cifrati. */ export function loadModello(loader, relPath, onLoad, onProgress, onError) { caricaModelloCifrato(loader, relPath, onProgress).then(onLoad, (err) => (onError ? onError(err) : console.error(err))); }