# How OpenMAIC Uses Content Hashes for Secure Asset Storage

> Discover how OpenMAIC uses SHA-256 content hashes for secure asset storage, creating a tamper-proof system with immutable identifiers.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: how-to-guide
- Published: 2026-09-01

---

**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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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.

```typescript
// 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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/rag/in-memory-resource-scope.test.ts), and serves as the primary index for storage retrieval. According to the [`render-service/README.md`](https://github.com/THU-MAIC/OpenMAIC/blob/main/render-service/README.md), this side-car hash design creates immutability guarantees for chunk bytes, making the storage system content-addressable by definition.

```typescript
// 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.

```typescript
// 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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/render-service/src/chunk-executor.ts) generates unique content identifiers without memory overhead.
- **Immutable `contentHash` fields** 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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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.