UNPKG

@praecise/tere

Version:

Trusted Execution Runtime Environment SDK

174 lines (173 loc) 6.33 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TerePackager = void 0; const crypto_1 = __importDefault(require("crypto")); /** * Utilities for packaging TERE scripts */ class TerePackager { /** * Create a TERE script from code and metadata * @param options Packaging options * @returns The compiled TERE binary as a Buffer */ static createScript(options) { // Generate a unique ID if not provided const scriptId = options.id || `script_${crypto_1.default.randomUUID ? crypto_1.default.randomUUID() : this.generateUUID()}`; // Create metadata JSON const metadata = { id: scriptId, name: options.name, version: options.version, timestamp: new Date().toISOString(), author: options.author || '', description: options.description || '', functions: options.functions || [], sha256: '' // Will be filled in later }; // Convert code to Buffer const codeBuffer = Buffer.from(options.code, 'utf8'); // Calculate SHA-256 hash of the code const hash = crypto_1.default.createHash('sha256').update(codeBuffer).digest('hex'); metadata.sha256 = hash; // Convert metadata to Buffer const metadataJson = JSON.stringify(metadata); const metadataBuffer = Buffer.from(metadataJson, 'utf8'); // Create metadata length Buffer (4 bytes, little-endian) const metadataLengthBuffer = Buffer.alloc(4); metadataLengthBuffer.writeUInt32LE(metadataBuffer.length, 0); // Create magic header Buffer const headerBuffer = Buffer.from(this.MAGIC_HEADER, 'utf8'); // Combine all Buffers return Buffer.concat([ headerBuffer, metadataLengthBuffer, metadataBuffer, codeBuffer ]); } /** * Validate a TERE script * @param script The TERE script to validate * @returns True if the script is valid, false otherwise */ static validateScript(script) { // Check minimum length if (script.length < 13) { return false; } // Check magic header const header = script.toString('utf8', 0, 8); if (header !== this.MAGIC_HEADER) { return false; } // Get metadata length const metadataLength = script.readUInt32LE(8); // Check if script is long enough to contain metadata if (script.length < 12 + metadataLength) { return false; } // Get metadata const metadataJson = script.toString('utf8', 12, 12 + metadataLength); let metadata; try { metadata = JSON.parse(metadataJson); } catch (e) { return false; } // Get code const code = script.slice(12 + metadataLength); // Verify hash if present if (metadata.sha256) { const calculatedHash = crypto_1.default.createHash('sha256').update(code).digest('hex'); if (calculatedHash !== metadata.sha256) { return false; } } return true; } /** * Extract metadata from a TERE script * @param script The TERE script to extract metadata from * @returns The metadata as a ScriptMetadata object */ static extractMetadata(script) { if (!this.validateScript(script)) { throw new Error('Invalid TERE script'); } // Get metadata length const metadataLength = script.readUInt32LE(8); // Get metadata const metadataJson = script.toString('utf8', 12, 12 + metadataLength); return JSON.parse(metadataJson); } /** * Get the script ID from a TERE script * @param script The TERE script to get the ID from * @returns The script ID, or null if not found */ static getScriptId(script) { try { const metadata = this.extractMetadata(script); return metadata.id || null; } catch (e) { return null; } } /** * Generate a UUID (fallback for older Node.js versions) * @returns A UUID string */ static generateUUID() { // Simple UUID v4 implementation for older Node.js versions return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } /** * Update the functions list in a TERE script * @param script The TERE script to update * @param functions The updated list of exported functions * @returns The updated TERE binary as a Buffer */ static updateFunctions(script, functions) { if (!this.validateScript(script)) { throw new Error('Invalid TERE script'); } // Get metadata length const metadataLength = script.readUInt32LE(8); // Get metadata const metadataJson = script.toString('utf8', 12, 12 + metadataLength); const metadata = JSON.parse(metadataJson); // Update functions metadata.functions = functions; // Get code const code = script.slice(12 + metadataLength); // Create updated metadata Buffer const updatedMetadataJson = JSON.stringify(metadata); const updatedMetadataBuffer = Buffer.from(updatedMetadataJson, 'utf8'); // Create updated metadata length Buffer const updatedMetadataLengthBuffer = Buffer.alloc(4); updatedMetadataLengthBuffer.writeUInt32LE(updatedMetadataBuffer.length, 0); // Create magic header Buffer const headerBuffer = Buffer.from(this.MAGIC_HEADER, 'utf8'); // Combine all Buffers return Buffer.concat([ headerBuffer, updatedMetadataLengthBuffer, updatedMetadataBuffer, code ]); } } exports.TerePackager = TerePackager; /** * Magic header for TERE scripts */ TerePackager.MAGIC_HEADER = 'TERE0001';