npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@majikah/majik-file

v0.4.1

Published

Majik File is the core cryptographic engine for secure file handling in the Majikah ecosystem. It provides a post-quantum secure "MJKB" format designed for file encryption, multi-recipient key encapsulation, and transparent compression using NIST-standard

Readme

Majik File

Developed by Zelijah GitHub Sponsors

Static Badge

Platform-agnostic post-quantum file encryption. Produces self-contained .mjkb binary files — sealed with ML-KEM-768 + AES-256-GCM, optionally Zstd-compressed, readable without any network access.

Note on Architecture: This library provides the core, decoupled MajikFile base class. It knows nothing about chat, threads, or storage backends. For Majikah messaging-specific implementations — including R2 keys, automatic WebP image conversions, and chat context routing — use MajikMessageFile (which subclasses MajikFile).

npm npm downloads npm bundle size License TypeScript


Contents


How it works

flowchart TD
    A[Raw Bytes]

    A --> B["SHA-256 Hash<br/>(Pre-compression for stable deduplication)"]

    B --> C["Extensibility Hook<br/>_preProcess(raw)<br/><br/>Default: No-op<br/>Example: WebP conversion"]

    C --> D{"Already Compressed?"}

    D -- No --> E["Zstd Compression<br/>Adaptive Level"]
    D -- Yes --> F["Skip Compression"]

    E --> G{"Recipients"}
    F --> G

    G -- "Single Recipient" --> H["ML-KEM-768 Encapsulate<br/>Owner Public Key"]

    H --> I["Shared Secret (32 bytes)<br/>Used directly as AES-256-GCM key"]

    I --> J["AES-256-GCM Encrypt<br/>12-byte Random IV<br/>16-byte Authentication Tag"]

    G -- "Group (2+ Recipients)" --> K["Generate Random<br/>32-byte AES Key"]

    K --> L["Encrypt File Once<br/>Using AES-256-GCM"]

    L --> M["For Each Recipient<br/>ML-KEM-768 Encapsulate<br/>Recipient Public Key"]

    M --> N["Encrypted AES Key<br/>AES Key XOR Shared Secret"]

    N --> O["Store Encrypted AES Keys"]

    O --> P[".mjkb Binary"]

    J --> P

The encrypted binary is completely self-contained.


The .mjkb binary format

Version: 0x01 (v2 Payload)

┌──────────────────────────────────────────────────────┐
│  4 bytes  │  Magic: ASCII "MJKB"  (0x4D 0x4A 0x4B 0x42)  │
│  1 byte   │  Version (currently 0x01)                      │
│ 12 bytes  │  AES-GCM IV (random per file)                  │
│  4 bytes  │  Payload JSON length (big-endian uint32)        │
│  N bytes  │  Payload JSON (UTF-8)                           │
│  M bytes  │  AES-GCM ciphertext (compressed plaintext + 16-byte auth tag) │
└──────────────────────────────────────────────────────┘

Single-recipient payload JSON (v2):

{
  "mlKemCipherText": "<base64, 1088 bytes>",
  "n": "photo.png",
  "m": "image/png",
  "z": true
}

Group payload JSON (v2):

{
  "keys": [
    {
      "fingerprint": "<base64 SHA-256 of public key>",
      "mlKemCipherText": "<base64, 1088 bytes>",
      "encryptedAesKey": "<base64, 32 bytes>"
    }
  ],
  "n": "photo.png",
  "m": "image/png",
  "z": true
}

Note: z is the explicit compression flag (v2). Older v1 legacy payloads used c and inferred decompression from messaging contexts.


Extensibility & Subclassing

MajikFile is engineered to be extended by platforms (like Majik Message) without duplicating cryptographic logic. Subclasses compose the crypto pipeline by overriding protected static hooks:

  • _preProcess(raw, mimeType): Alter bytes before compression (e.g., image resizing).
  • _resolveCompressionPolicy(mimeType): Override default MIME-based compression rules.

When invoking MySubclass.create(), the base _encryptCore() correctly routes to the subclass's overrides via late-bound static dispatch.


Installation

npm install @majikah/majik-file

Quick start

1. Encrypt a file (single recipient)

import { MajikFile } from '@majikah/majik-file'

// Identity must be supplied (MajikFile does not manage keys)
const identity = {
  publicKey: 'owner-address',
  fingerprint: 'base64-sha256-of-public-key',
  mlKemPublicKey: new Uint8Array(1184),
  mlKemSecretKey: new Uint8Array(2400), 
}

const fileBytes = await file.arrayBuffer()

const majikFile = await MajikFile.create({
  data: fileBytes,
  userId: 'user-uuid',
  identity,
  originalName: file.name,
  mimeType: file.type,
})

// Export the encrypted binary and metadata
const blob = majikFile.toMJKB()             
const metadata = majikFile.toJSON()         

2. Encrypt for a Group

const majikFile = await MajikFile.create({
  data: fileBytes,
  userId: 'sender-uuid',
  identity: senderIdentity,
  recipients: [
    { fingerprint: 'recipient-a-fp', mlKemPublicKey: recipientAKey, publicKey: 'addr-a' },
    { fingerprint: 'recipient-b-fp', mlKemPublicKey: recipientBKey, publicKey: 'addr-b' },
  ],
})

3. Decrypt a file

const { bytes, originalName, mimeType } = await MajikFile.decryptWithMetadata(
  mjkbBlob,
  { fingerprint: identity.fingerprint, mlKemSecretKey: identity.mlKemSecretKey }
)

const recovered = new Blob([bytes], { type: mimeType ?? 'application/octet-stream' })

4. Signatures & Offline Verification

.mjkb files support appending a cryptographic signature trailer (MJKS) for tamper-evident offline verification.

// Sign an existing file
await majikFile.sign(signingKey)

// Export with the appended signature trailer
const signedBlob = majikFile.toSignedMJKB()

// Verify later without a database round-trip
const isValid = await MajikFile.verifySignedMJKB(signedBlob, publicKeys)

API reference

MajikFile.create(options)

static async create(options: MajikFileCreateOptions): Promise<MajikFile>

| Field | Type | Required | Description | |---|---|---|---| | data | Uint8Array \| ArrayBuffer | ✓ | Raw file bytes to encrypt | | userId | string | ✓ | Owner's UUID | | identity | MajikFileIdentity | ✓ | Owner's full identity | | recipients | MajikFileRecipient[] | — | Group recipients. Empty → single-recipient | | originalName | string | — | Original filename (embedded in .mjkb) | | mimeType | string | — | MIME type | | id | string | — | UUID record ID. Auto-generated if omitted | | bypassSizeLimit | boolean | — | Default false. Bypasses 100MB cap | | compressionLevel| number | — | Zstd level to apply if compressible |


MajikFile.decryptWithMetadata(source, identity)

static async decryptWithMetadata(
  source: Blob | Uint8Array | ArrayBuffer,
  identity: MajikFileDecryptIdentity
): Promise<{
  bytes: Uint8Array
  originalName: string | null
  mimeType: string | null
  signature: MajikSignature | null
}>

Returns decrypted bytes alongside the file's metadata and signature, directly from the binary payload.


Type reference

MajikFileJSON

The serialised JSON representation of a generic file record. Notice the lack of platform-specific storage keys (like R2 paths) — those belong to subclasses.

interface MajikFileJSON {
  id: string
  schema_version: number
  kind: "file"
  user_id: string
  original_name: string | null
  mime_type: string | null
  size_original: number
  size_stored: number
  file_hash: string
  encryption_iv: string
  participants: string[]
  kem_alg: string
  cipher_alg: string
  timestamp: string | null
  last_update: string | null
  signature: string | null
}

Storage model

MajikFile separates the cryptographic artefact from the storage representation:

  • toMJKB() returns the encrypted binary blob (upload this to object storage like R2/S3).
  • toJSON() returns the metadata structure (store this in a database like Supabase).

It is up to the platform implementing MajikFile to manage where and how these artifacts are persisted and retrieved.


Related Projects

Majik Message

A secure software product available on Windows and WebApp, powered by these exact post-quantum file encryption techniques.

Majik Key

Seed phrase account library for generating deterministic ML-KEM-768 keypairs.

Majik Envelope

The core cryptographic engine handling message encryption and multi-recipient key encapsulation.


Apache-2.0 — free for personal and commercial use.


Author

Made with 💙 by @thezelijah