jmix-rs 0.2.0

Rust library for JMIX (JSON Medical Interchange) format - secure medical data exchange with cryptographic features
Documentation

JMIX-RS

A Rust implementation of the JMIX (JSON Medical Interchange) format for secure medical data exchange.

Features

  • DICOM file processing and metadata extraction
  • JSON Schema validation
  • AES-256-GCM encryption with Curve25519 ECDH key exchange
  • JWS digital signatures (Ed25519)
  • Cryptographic assertions for sender/requester/receiver identity verification
  • High-level builder API for envelope creation

Installation

[dependencies]
jmix-rs = "0.2.0"

Usage

Basic JMIX Envelope

use jmix_rs::{builder::JmixBuilder, config::Config};

let builder = JmixBuilder::new();
let config = Config::from_file("config.json")?;
let (envelope, files) = builder.build_from_dicom("path/to/dicom", &config)?;

With Security Features

// With encryption and signatures
let builder = JmixBuilder::with_complete_security()?;
let (envelope, files) = builder.build_from_dicom("path/to/dicom", &config)?;
let saved_files = builder.save_to_files(&envelope, &files, "output/")?;

DICOM Processing

use jmix_rs::dicom::DicomProcessor;

let processor = DicomProcessor::new();
let metadata = processor.process_dicom_folder("path/to/dicom", None)?;
println!("Extracted {} instances", metadata.instance_count);

Configuration Example

Create a configuration file:

{
  "version": "1.0",
  "sender": {
    "name": "Healthcare Provider",
    "id": "org:provider.123",
    "contact": "admin@provider.com"
  },
  "patient": {
    "name": "John Doe",
    "id": "PAT12345",
    "dob": "1985-03-15"
  }
}

Examples

# Basic envelope creation
cargo run --example build_jmix

# Digital signatures
cargo run --example jws_signing

# End-to-end encryption
cargo run --example envelope_encryption

# Identity verification
cargo run --example sender_assertions

CLI (runbeam)

A small CLI is included to validate JMIX packages.

Build and run:

cargo run --bin runbeam -- validate ./tmp/<ENVELOPE_ID>.jmix

Flags:

  • --validate-schema: enable JSON Schema validation (defaults to false)
  • --schema-dir PATH: custom schema directory (default ../jmix/schemas)
  • --verify-assertions: verify sender/requester/receiver assertions if present
  • --key PATH: recipient secret key for decrypting encrypted packages (payload.enc)
  • --json: output a machine-readable JSON report

Examples:

# Unencrypted package, no schema checks
cargo run --bin runbeam -- validate ./tmp/<id>.jmix

# Encrypted package: verify decryption + payload hash using secret key
cargo run --bin runbeam -- validate ./tmp/<id>.jmix --key ./tmp/keys_encrypted_test/recipient_secret.key

# With schema checks (requires schemas available)
cargo run --bin runbeam -- validate ./tmp/<id>.jmix --validate-schema --schema-dir ../jmix/schemas

# JSON output
cargo run --bin runbeam -- validate ./tmp/<id>.jmix --json

Verifying assertions

To verify sender/requester/receiver assertions during validation, add --verify-assertions:

# Build your envelope with assertions (see examples/sender_assertions.rs for generation)
# Then validate with assertion checks enabled
cargo run --bin runbeam -- validate ./tmp/<id>.jmix --verify-assertions

Decrypting an encrypted package

Extract the contents of payload.enc using the recipient's secret key:

cargo run --bin runbeam -- decrypt ./tmp/<id>.jmix \
  --key ./tmp/keys_encrypted_test/recipient_secret.key \
  --out ./tmp/decrypted

Tip: Temporary and example outputs are written under ./tmp/ by convention.

Technical Details

DICOM Processing

The library includes a DICOM processor that can:

  • Detect DICOM files by magic number, file extension, and parsing validation
  • Extract metadata: patient info, study details, series information
  • Handle multiple files by merging metadata from multiple instances
  • Fallback gracefully using config data when DICOM parsing fails

Example output:

Extracted DICOM metadata:
  Patient name: Some("Brown, Jane")
  Patient ID: Some("PID156695") 
  Study description: Some("CT Pulmonary Angiogram")
  Modalities: ["CT"]
  Series count: 1
  Instance count: 15

Cryptographic Features

  • AES-256-GCM: Authenticated encryption with 256-bit keys
  • Curve25519: Elliptic curve Diffie-Hellman key exchange
  • Ed25519: Elliptic curve digital signatures
  • SHA-256: Cryptographic hashing for fingerprints and integrity
  • JWS: JSON Web Signature standard (RFC 7515)

Payload Hashing

JMIX-RS computes and validates a deterministic payload hash stored in manifest.security.payload_hash (format: sha256:<hex>):

  • Unencrypted packages: The hash is computed over the contents of payload/ as follows:

    • Recursively list files under payload/
    • Sort by path relative to payload/ (Unicode codepoint order)
    • For each file: update the SHA-256 hasher with relative/path (UTF-8), then a single newline byte (\n), then the file's raw bytes
    • The final digest is emitted as sha256:<hex>
  • Encrypted packages: The payload is first assembled as a payload.tar and then encrypted to payload.enc using AES-256-GCM with ECDH (Curve25519) and HKDF-SHA256. The payload hash is computed as the SHA-256 over the plaintext payload.tar bytes prior to encryption and saved in the manifest. This makes the hash independent of IVs/ephemeral keys and stable across encryptions.

During validation:

  • Unencrypted: the validator recomputes the directory hash and compares it to the manifest value.
  • Encrypted: when a recipient secret key is provided, the validator decrypts payload.enc, hashes the plaintext TAR, and compares.

Schema Validation

The validation system supports:

  • Configurable schema path (default: ../jmix/schemas)
  • Lazy loading of schemas on demand
  • Comprehensive validation for manifest, metadata, audit, and files
  • Detailed error reporting with schema path and validation failures

To enable schema validation:

  1. Ensure schema files exist in ../jmix/schemas/ (or configure a custom directory)
  2. Configure schema discovery (precedence):
    • CLI flag --schema-dir <PATH>
    • Environment variable JMIX_SCHEMA_DIR=/absolute/or/relative/path
    • Default ../jmix/schemas
  3. Run validation tests:
    JMIX_SCHEMA_DIR=../jmix/schemas \
    cargo test test_validate_sample_files_with_schemas -- --ignored
    

CLI examples:

# Use a specific schema directory
cargo run --bin runbeam -- validate ./tmp/<id>.jmix --validate-schema --schema-dir ../jmix/schemas

# Or via environment variable (no flag needed)
JMIX_SCHEMA_DIR=../jmix/schemas \
  cargo run --bin runbeam -- validate ./tmp/<id>.jmix --validate-schema

Error Handling

use jmix_rs::error::{JmixError, ValidationError, DicomError, EncryptionError};

match result {
    Ok(envelope) => println!("Success: Secure envelope created"),
    Err(JmixError::Validation(e)) => eprintln!("Schema validation error: {}", e),
    Err(JmixError::Dicom(e)) => eprintln!("DICOM processing error: {}", e),
    Err(JmixError::Encryption(e)) => eprintln!("Encryption error: {}", e),
    Err(JmixError::Jws(e)) => eprintln!("Signing error: {}", e),
    Err(JmixError::Assertion(e)) => eprintln!("Assertion error: {}", e),
    Err(e) => eprintln!("Other error: {}", e),
}

Testing

# Run all tests (50+ tests)
cargo test

# Run with output
cargo test -- --nocapture

# Test specific modules
cargo test encryption
cargo test jws
cargo test assertion

Test Coverage

  • Unit tests (32): DICOM, encryption, JWS, assertions, builder, types
  • Integration tests (11): End-to-end security, DICOM processing, envelope structure
  • Sample validation tests (7): JSON sample consistency, config conversion

Project Structure

src/
├── lib.rs                  # Library root
├── config.rs               # Configuration types
├── types.rs                # JMIX core types
├── builder.rs              # High-level builder API
├── validation.rs           # JSON Schema validation
├── dicom.rs                # DICOM file processing
├── encryption.rs           # AES-256-GCM encryption (ECDH+HKDF)
├── jws.rs                  # JWS digital signatures
├── assertion.rs            # Ed25519 identity assertions
├── package_validation.rs   # Package-level validation API (hash, schema, assertions, decrypt)
├── bin/
│   └── runbeam.rs          # CLI: runbeam validate
└── error.rs                # Error handling

examples/
├── build_jmix.rs       # Basic envelope creation
├── jws_signing.rs      # Digital signature example
├── envelope_encryption.rs    # End-to-end encryption
└── sender_assertions.rs      # Identity verification

samples/
├── study_1/            # Real DICOM files (15 files, 3 series)
├── sample_config.json  # Configuration example
├── sample_manifest.json
├── sample_metadata.json
├── sample_audit.json
└── sample_files.json

Sample Data

The library includes real sample data for testing:

  • DICOM files: CT study with 15 instances across 3 series
  • JSON samples: Complete configuration and manifest examples
  • Test data: Used in integration tests and examples

Development

# Build and test
cargo build
cargo test

# Run examples
cargo build --examples

# Code quality
cargo clippy
cargo fmt

# Generate documentation
cargo doc --open

License

This project matches the licensing of the original PHP implementation.