How OpenMAIC Uses Content Hashes for Secure Asset Storage
OpenMAIC protects binary assets by binding each file to a cryptographic SHA-256 hash, creating a content-addressable system that detects tampering through immutable content identifiers.
OpenMAIC implements a robust security layer for binary assets using content hashes in asset storage to guarantee integrity and authenticity. This cryptographic approach ensures that every rendered chunk, uploaded file, or binary blob stored within the system remains immutable and verifiable throughout its lifecycle. By computing hashes during ingestion and validating them on every read, OpenMAIC creates a tamper-evident storage architecture that prevents corruption and malicious modifications.
SHA-256 Hash Generation in the Chunk Executor
The foundation of OpenMAIC's security model lies in streaming hash computation implemented in render-service/src/chunk-executor.ts. At lines 298-311, the system initializes a SHA-256 hash instance using Node.js's createHash('sha256') method and feeds file bytes through the stream incrementally. This approach minimizes memory overhead while processing large assets, ensuring the entire file is digested into a unique hexadecimal identifier without loading the complete buffer into memory.
// Compute SHA-256 hash via streaming (from chunk-executor implementation)
import { createHash } from 'crypto';
import { createReadStream } from 'fs';
async function hashFile(path: string): Promise<string> {
const hash = createHash('sha256');
for await (const chunk of createReadStream(path)) {
hash.update(chunk);
}
return hash.digest('hex');
}
Content-Addressable Storage Architecture
OpenMAIC treats the computed hash as the immutable source of truth for asset identity. The hex-encoded hash value populates the contentHash field in asset metadata, as demonstrated in test fixtures such as tests/rag/in-memory-resource-scope.test.ts, and serves as the primary index for storage retrieval. According to the render-service/README.md, this side-car hash design creates immutability guarantees for chunk bytes, making the storage system content-addressable by definition.
// Store asset with content-derived hash identifier
const assetMeta = {
id: generateUuid(),
contentHash: await hashFile(uploadedFilePath), // immutable identifier
createdAt: Date.now()
};
await storage.save(assetMeta.id, uploadedFilePath, assetMeta);
Runtime Integrity Verification
When retrieving assets, OpenMAIC recomputes the hash of the retrieved bytes and compares it against the stored contentHash value. If the hashes mismatch, the system throws a ChunkExecutorError('stale_chunk'), immediately blocking the request and preventing corrupted or tampered data from reaching downstream consumers. This verification step protects against replay attacks and storage corruption by enforcing cryptographic proof of integrity before asset processing begins.
// Verify asset integrity on read
async function verifyAsset(path: string, expectedHash: string) {
const actualHash = await hashFile(path);
if (actualHash !== expectedHash) {
throw new Error('Asset hash mismatch – possible tampering');
}
// Asset is trustworthy, proceed with processing…
}
Secure Access via Signed URLs
For external storage backends like S3, OpenMAIC ensures hash integrity persists through the access layer. As shown in tests/persistence/route.test.ts (lines 1010-1022), when generating signed URLs, the contentHash travels unchanged through the request metadata while the signature layer only signs the access URL itself. This separation guarantees that the retrieval request can only succeed for the exact content matching the stored hash, effectively preventing substitution attacks during transit.
Summary
- Streaming SHA-256 computation in
render-service/src/chunk-executor.tsgenerates unique content identifiers without memory overhead. - Immutable
contentHashfields in asset metadata create a content-addressable storage system where identity equals integrity. ChunkExecutorError('stale_chunk')provides runtime tamper detection by validating hashes on every read operation.- Signed URL implementations preserve hash integrity across external storage boundaries, ensuring end-to-end cryptographic verification.
Frequently Asked Questions
What hash algorithm does OpenMAIC use for asset storage?
OpenMAIC uses SHA-256 (Secure Hash Algorithm 256-bit) to generate content-derived identifiers. The implementation in render-service/src/chunk-executor.ts uses Node.js's native createHash('sha256') method to compute hexadecimal digests from streaming file bytes.
How does OpenMAIC detect corrupted or tampered assets?
The system detects tampering through cryptographic hash verification. When reading an asset, OpenMAIC recomputes the SHA-256 hash of the retrieved bytes and compares it against the stored contentHash; any mismatch triggers a ChunkExecutorError('stale_chunk') that blocks the corrupted data from processing.
What happens if an asset's content hash does not match during verification?
If the recomputed hash does not match the stored contentHash, OpenMAIC immediately throws a ChunkExecutorError('stale_chunk'). This error halts the current operation and prevents the corrupted or modified asset from being handed to the caller, ensuring only cryptographically verified data enters the pipeline.
Are content hashes used as filenames in OpenMAIC storage?
Yes, in production environments the hex-encoded hash serves as part of the storage key or filename, making the system content-addressable. This design ensures that any alteration to file bytes produces a different identifier, effectively isolating corrupted data while maintaining a deduplication-friendly storage structure.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →