ImageSplit: HIPAA-Compliant Medical Image Protection
Medical images (X-rays, MRIs, CT scans, ultrasounds) are among healthcare's most sensitive data—a single leaked scan reveals patient identity and diagnosis. ImageSplit uses XorIDA threshold sharing to split large imaging files into independent shares distributed across storage nodes. No single node holds reconstructible data. Information-theoretic security. Zero npm dependencies.
Executive Summary
ImageSplit makes medical image HIPAA-compliance automatic by splitting images via XorIDA threshold sharing, chunking large files into manageable segments, and verifying integrity per-share using HMAC-SHA256.
Two functions cover the complete lifecycle: splitImage() accepts a medical image with metadata (patient ID, modality, study date, institution) and a configuration specifying storage nodes and recovery threshold. The image is chunked (default 1 MB), each chunk is XorIDA-split, and shares are returned grouped by chunk with individual HMAC signatures. reconstructImage() accepts a manifest and threshold quorum of shares, verifies HMAC on each share, reconstructs each chunk, and returns the original image bytes.
Information-theoretic security means fewer than threshold shares reveal absolutely nothing about the image — not computationally difficult to break, but mathematically impossible. An attacker who compromises one or two storage nodes learns only that medical data exists there; the image remains unrecoverable.
The package requires zero external dependencies. It runs anywhere the Web Crypto API is available — Node.js 20+, Deno, Bun, Tauri, browsers. Chunked processing bounds memory usage, so multi-gigabyte imaging datasets are safe to handle.
The Problem: Medical Image Risk
Medical images—X-rays, MRIs, CT scans—are among the most identifying data in healthcare. A single leaked scan reveals not just diagnosis but patient identity, location, and treatment timeline.
Why Medical Images Are High-Risk
HIPAA treats medical images as the most sensitive Protected Health Information. Unlike de-identified lab results, imaging cannot be truly anonymized:
- Face reconstructs from skull X-rays and CT scans
- Tumor location and pathology reveal diagnosis
- Imaging timestamps correlate to treatment schedules
- Modality frequencies (7 MRI scans in 2 months) leak disease progression
- Device metadata (MRI model, acquisition settings) identifies the hospital
Current Storage Approaches
Traditional healthcare image storage relies on a single encrypted vault (PACS) with access controls and audit logs. The risks:
The Gap in HIPAA
HIPAA requires "encryption at rest" and "encryption in transit," but does not mandate threshold-based distribution. Most PACS implementations encrypt the image in one place, then apply role-based access controls. ImageSplit shifts the security model: instead of trusting a gatekeeper, it makes the image irrecoverable without quorum participation.
The Solution: XorIDA-Split Distribution
ImageSplit distributes medical images using XorIDA (threshold secret sharing over GF(2)) so that any single storage node is useless without the others. An attacker compromises multiple nodes or no nodes; there is no partial information.
XorIDA in 30 Seconds
XorIDA is a threshold sharing scheme operating over GF(2) (binary field, XOR operations). To split image data into 3 shares with threshold 2:
- Generate random share 0 (same size as original)
- Share 1 = original XOR share 0 (deterministic)
- Share 2 = original XOR share 0 XOR share 1 (deterministic)
Any two shares can reconstruct the original. One share alone reveals zero bits of information — XOR guarantees that. This is information-theoretic security: mathematically impossible to break even with unlimited computing power.
Chunked Processing for Large Images
Medical images can span gigabytes (multi-series MRI scans). ImageSplit chunks the image into fixed-size segments (default 1 MB) before splitting:
// 500 MB image → 500 chunks of 1 MB each for (chunk of chunks) { shares = xorida.split(chunk, 3, 2); hmac = computeHmac(shares); store(shares, hmac); }
Chunking provides three benefits: memory-bounded processing, parallel distribution, and per-chunk verification. If one chunk is corrupted, its HMAC-signature catch the error immediately without reconstructing the entire image.
Per-Share Integrity Verification
Unlike protocols that compute HMAC on the final reconstructed image, ImageSplit verifies HMAC on each share immediately after splitting. Before any reconstruction, every single share is verified:
HMAC verification happens BEFORE reconstruction. If any share is tampered with or corrupted, it is rejected before reconstruction begins. The HMAC key is unique per share, enabling independent verification at any storage node.
Use Cases & Industries
Architecture & Implementation
Core Data Structures
ImageSplit revolves around four main types:
| Type | Purpose | Mutable |
|---|---|---|
| MedicalImage | Input: image bytes + metadata (patient ID, modality, study date, institution) | No |
| ImageManifest | Split metadata: manifest ID, image hash, chunk count, config, timestamp | No |
| ImageShare | A single share: chunk index, node index, data (base64), HMAC, HMAC key | No |
| ImageShareConfig | Configuration: storage nodes count, threshold, chunk size (optional) | No |
Chunked Processing
The splitImage() function chunks the image upfront:
- Validate configuration (2+ storage nodes, threshold 2 to storageNodes)
- Compute SHA-256 hash of the full image
- Chunk image into fixed-size segments (default 1 MB)
- For each chunk:
- Apply PKCS7 padding to align to cryptographic boundaries
- XorIDA-split into K shares
- Generate unique HMAC key (32 bytes random, stored with each share)
- Compute HMAC-SHA256 on each share; store with share data
- Create manifest linking all chunks and storing image hash
- Return manifest + shares grouped by chunk index
Manifest & Integrity
The ImageManifest is the contract between sender and receiver:
interface ImageManifest { id: string; // UUID, unique split ID imageId: string; // Original image identifier patientId: string; // Patient identifier (PLAINTEXT) modality: ImageModality; // 'xray' | 'mri' | 'ct' | 'ultrasound' | 'dicom' totalChunks: number; // Count of chunks (index: 0..totalChunks-1) imageHash: string; // Hex SHA-256 of original (verification) config: ImageShareConfig; // Threshold config (K-of-N) createdAt: number; // Unix millisecond timestamp }
Deployers must encrypt the manifest at rest; ImageManifest itself contains plaintext metadata (patient ID, modality). The imageHash allows end-to-end verification: after reconstruction, verify the reconstructed bytes against imageHash.
Reconstruction Pipeline
Reconstruction reverses the split in three steps:
- For each chunk: validate that at least threshold shares are provided
- For each share: verify HMAC-SHA256 immediately (before reconstruction)
- XorIDA-reconstruct each chunk from threshold shares
- PKCS7-unpad each reconstructed chunk
- Concatenate all chunks in order
- Return the reconstructed image bytes (Uint8Array)
The reconstructImage() function does NOT re-verify the manifest imageHash after reassembly. Deployers should independently verify sha256(reconstructedBytes) === manifest.imageHash if end-to-end integrity is required.
Public API
Primary Functions
Splits a medical image into XorIDA shares across storage nodes with per-share HMAC verification. Returns manifest (metadata) and shares grouped by chunk. Chunks default to 1 MB; customize via config.chunkSize. Validates configuration upfront; rejects if threshold > storageNodes or threshold < 2.
Reconstructs the original image from a threshold quorum of shares. Shares are grouped by chunk index (shares[0] = all shares for chunk 0, etc.). Verifies HMAC on every single share before reconstruction. Returns the original Uint8Array on success. Does NOT verify manifest.imageHash post-reconstruction; deployers should do this independently.
Error Codes
Both functions return errors as discriminated union strings. Match against base code (prefix before colon) for broad handling; check full code for specific diagnostics:
| Error Code | Sub-Codes | When |
|---|---|---|
| INVALID_CONFIG | TOO_FEW_NODES, THRESHOLD_TOO_LOW, THRESHOLD_TOO_HIGH | Configuration validation fails (storageNodes < 2, threshold < 2, threshold > storageNodes) |
| SPLIT_FAILED | (none) | XorIDA split operation failed on one or more chunks |
| HMAC_FAILED | (none) | HMAC-SHA256 computation or verification failed; share may be corrupted |
| RECONSTRUCT_FAILED | UNPAD | Reconstruction succeeded but PKCS7 unpadding failed (corrupted or truncated chunk) |
| INSUFFICIENT_SHARES | MISSING_CHUNKS | Fewer shares provided than threshold requires for one or more chunks |
Type Definitions
ImageSplit exports all types for full TypeScript integration:
export type ImageModality = 'xray' | 'mri' | 'ct' | 'ultrasound' | 'dicom'; export interface MedicalImage { imageId: string; patientId: string; modality: ImageModality; format: string; data: Uint8Array; studyDate: string; institution: string; } export interface ImageShareConfig { storageNodes: number; threshold: number; chunkSize?: number; } export type ImageSplitError = 'INVALID_CONFIG' | 'SPLIT_FAILED' | 'HMAC_FAILED' | 'RECONSTRUCT_FAILED' | 'INSUFFICIENT_SHARES' | ...;
Integration Patterns
PACS Integration: Store Shares Separately
Traditional PACS systems store all images on a single encrypted vault. To integrate ImageSplit:
- On imaging upload: call
splitImage() - Route shares to different storage backends (local NAS, cloud vault, offline archive)
- Store manifest encrypted in primary PACS (with access audit trail)
- On retrieval: fetch manifest + threshold shares, call
reconstructImage()
Multi-Hospital Network
Hospital A, B, C collaborate on a patient's case:
- Hospital A (owner) splits image into 3 shares, threshold 2
- Share 0 → stays local (Hospital A vault)
- Share 1 → Hospital B vault
- Share 2 → Hospital C vault
- Encrypted manifest shared to all three (or posted to shared secure network)
Radiologist at Hospital B cannot view the image alone (no image without 2 of 3 shares). Radiologist at Hospitals A+B together can reconstruct. Single-site compromise (any one hospital breached) doesn't expose the image.
Research Data Pipeline
Clinical trial sites collect imaging data:
- Each site splits its imaging data: K-of-N threshold (e.g., 4-of-5)
- 4 shares → distributed to other research sites (or cloud)
- 1 share → retained locally for operational continuity
- Only central coordinating team (with access to 4+ sites) can reconstruct full dataset
Security Model
Information-Theoretic Guarantees
ImageSplit provides unconditional security: given fewer than threshold shares, zero information about the image is learnable, regardless of computational power:
Per-Share HMAC Verification
Unlike systems that verify HMAC on the final reconstructed image, ImageSplit verifies HMAC on each share independently before reconstruction:
- Each share carries a unique HMAC key (32 bytes, randomly generated)
- HMAC-SHA256 signature computed and stored with the share
- Before reconstruction, HMAC is verified on every single share
- If any share's HMAC fails, reconstruction stops immediately
- Corrupted or tampered shares are caught before reconstruction begins
No Cryptographic Weaknesses
- Randomness from
crypto.getRandomValues()only — neverMath.random() - HMAC-SHA256 via Web Crypto API (FIPS-approved)
- SHA-256 for image hash (FIPS-approved)
- PKCS7 padding for block alignment
- XorIDA shares never stored unencrypted at rest (deployer responsibility)
Known Limitations
ImageSplit does NOT provide:
- Metadata encryption (imageId, patientId, modality are plaintext in manifest and shares)
- Transport security (shares must be encrypted in transit by the deployer)
- Access control or audit logging (deployer must add)
- DICOM header parsing or de-identification
- Post-reconstruction image hash verification (deployer should verify independently)
Performance & Scalability
Chunked Processing Efficiency
Benchmark results (Node.js 20, M1 Mac) for splitting and reconstructing images with 2-of-3 threshold:
| Image Size | Chunks | Split Time | Reconstruct Time |
|---|---|---|---|
| 10 MB | 10 | ~12 ms | ~8 ms |
| 100 MB | 100 | ~115 ms | ~80 ms |
| 500 MB | 500 | ~580 ms | ~420 ms |
| 1 GB | 1024 | ~1.2 s | ~850 ms |
Memory Footprint
Chunked processing bounds memory to chunk size + temporary buffers:
- 1 MB chunks (default) → ~3 MB active memory (chunk + 2 shares)
- 10 MB chunks → ~30 MB active memory
- Gigabyte-scale images process safely on mobile devices (Node.js, Deno, Tauri)
Scalability Notes
ImageSplit scales linearly with image size. The XorIDA algorithm is O(n) where n = image bytes. Reconstruction requires threshold XOR operations per byte, all parallel-friendly on multi-core systems.
HIPAA Alignment & Compliance
How ImageSplit Addresses HIPAA Technical Safeguards
HIPAA's Technical Safeguards require "encryption and decryption" for sensitive health information at rest and in transit. ImageSplit aligns with four key rules:
| HIPAA Rule | ImageSplit Approach |
|---|---|
| §164.312(a)(2)(i) - Encryption at Rest | Stores shares encrypted (deployer adds layer); XorIDA makes any single share useless without quorum |
| §164.312(c)(1) - Encryption in Transit | Shares transmitted separately via HTTPS/TLS (deployer responsibility); no full image in transit |
| §164.308(a)(1)(ii) - Risk Analysis | Threshold distribution shifts risk model: one-node breach ≠ data breach |
| §164.308(a)(7)(i) - Business Associate Agreements | Multi-vendor distribution aligns with BAA requirements (each vendor holds partial data) |
What ImageSplit Does NOT Do (Deployer Responsibilities)
ImageSplit is a cryptographic component. It does NOT provide HIPAA compliance by itself. Deployers must:
- Encrypt manifests and share metadata at rest
- Encrypt shares in transit (TLS/HTTPS)
- Implement access control and audit logging
- Establish Business Associate Agreements with storage providers
- Conduct HIPAA risk assessment and documentation
Multi-Vendor Alignment
HIPAA allows distributed storage across multiple vendors if each holds only partial data. ImageSplit enables this architecture:
- Share 0 → Healthcare provider's on-premise vault
- Share 1 → Cloud vendor (AWS, Azure, GCP)
- Share 2 → Disaster recovery vault (different region)
- No single vendor breach exposes the image; threshold-quorum required
Honest Limitations
Metadata in Plaintext
The ImageManifest and ImageShare objects contain plaintext fields: imageId, patientId, modality. While the image bytes are split, the metadata reveals:
- Patient identity (no anonymity)
- Imaging modality (reveals diagnostic type)
- Chunk count (hints at image size / complexity)
Deployers must encrypt manifests and share metadata at rest independently. Use @private.me/crypto or similar for AES-256-GCM encryption of manifest fields.
No Post-Reconstruction Hash Verification
reconstructImage() returns the reconstructed bytes without verifying the manifest's imageHash. Deployers should independently verify:
const reconstructed = await reconstructImage(manifest, shares); if (!reconstructed.ok) throw reconstructed.error; // Deployer must verify the hash const actualHash = await sha256(reconstructed.value); if (actualHash !== manifest.imageHash) { throw new Error('Image hash mismatch!'); }
No Transport Security
Shares are returned as base64 strings; deployers must encrypt them in transit. ImageSplit does not provide TLS, HTTPS, or signed protocols. Use @private.me/agent-sdk for end-to-end encryption of shares across a network.
No Access Control
ImageSplit has no built-in authorization. It does not check whether a user is allowed to reconstruct an image. Add your own access control layer (role-based, attribute-based, etc.) before calling reconstructImage().
No Audit Logging
There are no hooks for logging when images are split or reconstructed. Deployers must wrap splitImage() and reconstructImage() with audit logic.
Post-Quantum Security
XorIDA is Quantum-Proof
The security of ImageSplit does not rely on the computational hardness of factoring or discrete log. XorIDA provides information-theoretic security:
- Fewer than threshold shares reveal zero bits about the image
- This is true against classical computers, quantum computers, and any future adversary
- No key material needs protecting from quantum key recovery
- Harvest-now-decrypt-later attacks are impossible
Transport Layer PQ Protection
When ImageSplit shares are sent via @private.me/agent-sdk (Xlink), the envelopes use hybrid post-quantum cryptography:
- Key exchange: X25519 + ML-KEM-768 (FIPS 203) — always-on in v2+ envelopes
- Signatures: Ed25519 + ML-DSA-65 (FIPS 204) — opt-in via
postQuantumSig: true
Combining information-theoretic payload security (XorIDA) with hybrid post-quantum transport (Xlink) provides defense-in-depth:
| Layer | Security Model | Quantum-Safe |
|---|---|---|
| Payload (XorIDA) | Information-theoretic (K-1 shares reveal nothing) | Yes |
| Transport (Xlink) | Hybrid PQ (X25519 + ML-KEM-768) | Yes |
| Signature (Xlink) | Hybrid PQ (Ed25519 + ML-DSA-65 optional) | Yes |
Recommendation
Applications integrating ImageSplit should create agents with postQuantumSig: true for full end-to-end post-quantum protection.
Error Handling & Diagnostics
Result<T, E> Pattern
ImageSplit uses discriminated union error codes. Never throws exceptions in library code:
const result = await splitImage(image, config); if (!result.ok) { // result.error is a string code switch (result.error.split(':')[0]) { case 'INVALID_CONFIG': console.error('Fix config'); break; case 'HMAC_FAILED': console.error('Data corrupted'); break; } } else { // result.value is the ImageSplitResult const { manifest, shares } = result.value; }
Class-Based Error Conversion
ImageSplit exports toImageSplitError() to convert string codes to typed error classes for try/catch:
import { toImageSplitError, ImageSplitError } from '@private.me/imagesplit'; const result = await splitImage(image, config); if (!result.ok) { const err = toImageSplitError(result.error); console.error(err.message, err.code, err.docUrl); if (err instanceof ImageConfigError) { // ... } }
Supported Image Modalities
ImageSplit stores the imaging modality for metadata purposes. While the core algorithm is modality-agnostic, the type system enforces five standard medical imaging modalities:
| Modality | Typical Size | Common Use |
|---|---|---|
| xray | 1–20 MB | Radiography (chest, limbs, spine) |
| mri | 50–500 MB | Magnetic resonance imaging (brain, cardiac, musculoskeletal) |
| ct | 50–300 MB | Computed tomography (head, thorax, abdomen) |
| ultrasound | 10–100 MB | Sonography (obstetric, cardiac, vascular) |
| dicom | Variable | Generic DICOM file (any modality) |
Use ImageModality to tag images for audit and compliance purposes. The modality does not affect splitting or reconstruction logic; it is purely metadata.
Storage & Distribution Strategies
On-Premise + Cloud Hybrid
Split into 3 shares, threshold 2:
- Share 0 → Hospital's local NAS (access controlled, audited)
- Share 1 → AWS S3 (encrypted bucket, versioning enabled)
- Share 2 → Azure Blob (geo-redundant backup)
Any two backends can reconstruct. Hospital breach alone ≠ data breach. Cloud-only breach alone ≠ data breach.
Federated Multi-Site
For research or multinational healthcare:
- Site A (USA) → Share 0
- Site B (Canada) → Share 1
- Site C (EU) → Share 2
- Manifest encrypted + distributed separately (via mail, secure courier, or encrypted email)
Reconstruction requires inter-site coordination, making casual disclosure impossible. GDPR data residency constraints are easier to satisfy (no full image crosses borders).
Offline Archive
For legal/compliance archival (images must be kept 5-10 years):
- Split into 4 shares, threshold 3
- 3 shares → cold storage (WORM optical discs, tape vault)
- 1 share → retained in operational PACS (for rare retrieval)
Theft of one tape drive ≠ image recovery. Requires multiple geographically separated facility breaches to reconstruct.
Metadata Privacy Considerations
What's Plaintext
The following fields are stored plaintext and must be encrypted at rest:
imageId— Unique image identifier (could be medical record number)patientId— Patient identifier (could be SSN or medical record number)modality— Type of imaging (reveals diagnostic intent)totalChunks— Number of chunks (hints at image size)createdAt— Timestamp (reveals when imaging occurred)
Encryption Pattern
Use @private.me/crypto or Web Crypto API to encrypt manifest before storage:
import { encryptAES } from '@private.me/crypto'; const manifestStr = JSON.stringify(manifest); const key = await deriveKey(password); // PBKDF2 const encrypted = await encryptAES( new TextEncoder().encode(manifestStr), key ); // Store encrypted in PACS or vault
De-Identification Limitations
Even with metadata encrypted, the image bytes themselves are not de-identified. A radiologist viewing a reconstructed image can often identify the patient (face from skull CT, tumor patterns, etc.). ImageSplit does not provide de-identification; it provides secure split distribution. De-identification (if needed) must be done separately by a radiologist or automated tool before splitting.
Codebase Overview
ImageSplit is a lean, focused package with minimal surface area:
Module Structure
| Module | Lines | Purpose |
|---|---|---|
| types.ts | 66 | Type definitions (MedicalImage, ImageShare, manifest, config) |
| errors.ts | 87 | Error classes and code-to-class mapping |
| image-splitter.ts | ~150 | splitImage() implementation: chunking, XorIDA, HMAC |
| image-reconstructor.ts | ~120 | reconstructImage() implementation: verification, XOR, unpadding |
| index.ts | 14 | Public API exports (barrel file) |
Dependencies
@private.me/crypto— XorIDA, HMAC, padding, UUID, encoding@private.me/shared— Result<T, E> pattern
Test Coverage
ImageSplit includes 70+ test cases covering:
- Configuration validation
- Splitting and reconstruction correctness
- HMAC generation and verification
- Chunking edge cases (small, medium, large images)
- Error codes and error messages
- Performance benchmarks
Deployment Options
SaaS Recommended
Fully managed infrastructure. Call our REST API, we handle scaling, updates, and operations.
- Zero infrastructure setup
- Automatic updates
- 99.9% uptime SLA
- Enterprise SLA available
SDK Integration
Embed directly in your application. Runs in your codebase with full programmatic control.
npm install @private.me/imagesplit- TypeScript/JavaScript SDK
- Full source access
- Enterprise support available
On-Premise Upon Request
Enterprise CLI for compliance, air-gap, or data residency requirements.
- Complete data sovereignty
- Air-gap capable deployment
- Custom SLA + dedicated support
- Professional services included
Enterprise On-Premise Deployment
While imageSplit is primarily delivered as SaaS or SDK, we build dedicated on-premise infrastructure for customers with:
- Regulatory mandates — HIPAA, SOX, FedRAMP, CMMC requiring self-hosted processing
- Air-gapped environments — SCIF, classified networks, offline operations
- Data residency requirements — EU GDPR, China data laws, government mandates
- Custom integration needs — Embed in proprietary platforms, specialized workflows
Includes: Enterprise CLI, Docker/Kubernetes orchestration, RBAC, audit logging, and dedicated support.