@voideddev/enc-server
v1.0.0
Published
Server-side hashing, compression, encryption, and v3 monolith artifact library backed by Rust
Maintainers
Readme
@voideddev/enc-server
@voideddev/enc-server is the Node.js package for Voided's native Rust-backed
runtime. It exposes synchronous server-side APIs for hashing, compression,
authenticated encryption, fused shell operations, and monolith protected
artifacts.
Under the hood, the package is layered like this:
voided-core- source-of-truth Rust implementation
voided-node- N-API binding over
voided-core
- N-API binding over
@voideddev/enc-server- TypeScript package surface over the native binding
Contents
- What This Package Is For
- Installation
- Quick Start
- What Fused Means In Node.js
- Choosing The Right API Layer
- Primitive Crypto APIs
- Fused Shell And Full-Flow APIs
- Higher-Level Helper Exports
- Fused Presets
- Native Runtime Behavior
- Development
- Troubleshooting
- License
What This Package Is For
Use @voideddev/enc-server when you want:
- Node.js access to the Voided native runtime
- synchronous server-side APIs backed by Rust
- the monolith-first Voided 1.0 artifact model
- direct use of hashing, compression, encryption, shell, and artifact helpers
- small higher-level utilities that are packaged on top of the native runtime
If you want direct Rust instead, use voided-core. If you want browser-side
usage, use @voideddev/e2ee-client.
Installation
npm install @voideddev/enc-serverThe package ships native prebuilds for macOS Apple Silicon, Linux x64 GNU, and Windows x64 MSVC. The loader verifies each artifact's hash and provenance before use. Unsupported platforms cannot load the native runtime; installation never compiles source code.
The Linux x64 prebuild requires glibc 2.34 or newer. Consumers on another architecture, C library, or older Linux distribution should build the binding from the tagged Voided source release and run the native verification suite.
Quick Start
Full-Flow Monolith Artifact
This is the normal Voided 1.0 path in Node.js.
import {
generateKey,
protect,
open,
inspectArtifact,
} from "@voideddev/enc-server";
const key = generateKey();
const plaintext = Buffer.from("hello from enc-server");
const protectedResult = protect(plaintext, key, {
preset: "balanced",
compressionAlgorithm: "brotli",
encryptionAlgorithm: "xchacha20-poly1305",
});
const info = inspectArtifact(protectedResult.artifact);
const restored = open(protectedResult.artifact, key);
console.log(info.preset);
console.log(restored.toString("utf8"));Primitive Encryption
Use raw AEAD helpers when you want to manage the outer format yourself.
import {
generateKey,
encrypt,
decrypt,
} from "@voideddev/enc-server";
const key = generateKey();
const plaintext = Buffer.from("primitive path");
const encrypted = encrypt(plaintext, key, "xchacha20-poly1305");
const restored = decrypt(encrypted, key);
console.log(restored.equals(plaintext));Inspect And Repack
Use inspectArtifact when you want metadata without opening the payload, and
repackArtifact when you want to move an artifact between presets.
import {
generateKey,
protect,
repackArtifact,
inspectArtifact,
open,
} from "@voideddev/enc-server";
const key = generateKey();
const payload = Buffer.from("repack me".repeat(1024));
const initial = protect(payload, key, { preset: "balanced" });
const repacked = repackArtifact(initial.artifact, key, { preset: "concealed" });
const info = inspectArtifact(repacked.artifact);
const restored = open(repacked.artifact, key);
console.log(info.preset);
console.log(restored.equals(payload));What Fused Means In Node.js
The fused shell is the outer artifact format. It wraps bytes that are already prepared and gives them a stable, inspectable, preset-driven envelope.
In the standard Voided 1.0 product flow, protect/open own the whole artifact
plan:
- optionally compressed
- encrypted
- shaped by the whole-monolith shell
That means:
encryptgives you ciphertext and encryption metadata, but not the standard monolith artifactfusewraps prepared bytes in the shellprotectruns the normal full flow and returns the standard monolith artifact
Use fuse/unfuse when you already control the bytes that should live inside
the shell.
Use protect/open when you want the normal Voided artifact contract.
Choosing The Right API Layer
The package exposes several layers. Use the smallest one that fits your job.
Use primitive helpers when you want:
- direct hashing
- direct AEAD encryption
- direct compression
- explicit control over your own outer format
Use fused shell helpers when you want:
fuseunfuseinspectFused
These are for cases where you already own the bytes being shelled.
Use full-flow helpers when you want:
protectopeninspectArtifactrepackArtifact
These are the standard Voided monolith artifact APIs.
Primitive Crypto APIs
Primitive exports include:
generateKeyencryptdecryptderiveKeyHkdfderiveKeyPbkdf2generateRecoveryDeckvalidateRecoveryDeckencodeRecoveryDeckderiveRecoveryKeywrapRootWithRecoveryKeyunwrapRootWithRecoveryKeycreateRecoveryDeckrotateRecoveryDeckhashhashWithSaltcompareHashesgenerateHmacverifyHmachashPbkdf2verifyPbkdf2fingerprintsafetyNumberscompressdecompressrandomBytesgenerateSaltsecureWipebase64Encodebase64DecodehexEncodehexDecode
Important behavior notes:
- all binary inputs and outputs use Node
Buffer - the package is synchronous because the native module is loaded directly into Node.js
- there is no TypeScript crypto fallback in this package
- Recovery Deck is stateless: persist only its opaque
rootWrapper, never the ordered deck, permutation rank, or derived Recovery Key - the permanent card ordering, rank encoding, derivation domain, and wrapper
format are documented in the
Recovery Deck protocol - XChaCha20-Poly1305 is the default primitive; direct AES-256-GCM callers must count uses across their system, prevent nonce reuse, and rotate a key before 2^32 encryptions
- PBKDF2 helpers require a 16-1024 byte salt and 100,000-1,000,000 iterations; they are synchronous, so application-selected higher work factors belong in a worker thread
hashWithSaltuses domain-separated, length-prefixed fields; it is not compatible with the ambiguous legacyhash(data || salt)constructionsafetyNumbersis only a grouped SHA-256 fingerprint display; it is not Signal's identity-binding Safety Number protocol- direct decompression and stream helpers enforce output and expansion limits; use bounded authenticated records for larger streaming workloads
Fused Shell And Full-Flow APIs
Fused Shell
Use these when you want the shell layer directly:
fuse(data, key, preset?, chunkSize?)unfuse(data, key)inspectFused(data)
What each one does:
fuse- wrap already-prepared bytes in the fused shell
unfuse- strip the shell and return the inner bytes
inspectFused- inspect shell metadata without opening the inner payload
inspectFused gives you metadata such as:
- preset
- chunk size
- chunk count
- payload size
- shell size
Full-Flow Artifacts
Use these when you want the standard Voided monolith artifact contract:
protect(data, key, options?)open(artifact, key)inspectArtifact(artifact)repackArtifact(artifact, key, options?)
What each one does:
protect- compress, encrypt, and shape the input into the standard monolith artifact
open- reverse
protectand return the original plaintext bytes
- reverse
inspectArtifact- inspect artifact metadata without opening it
repackArtifact- reopen and rewrite an artifact with new preset or pipeline settings
protect and repackArtifact accept:
presetcompressionAlgorithmcompressionLevelencryptionAlgorithmshellChunkSize
inspectArtifact reports:
- preset
- compression algorithm
- encryption algorithm
- original size
- compressed size
- encrypted size
- protected size
- shell chunk size
- shell chunk count
All inspectFused, inspectArtifact, and inspectRotationArtifact results are
untrusted keyless hints. Do not use them for authorization, quota accounting,
billing, allocation decisions, or algorithm policy. Only a successful
open/openRotationArtifact authenticates the artifact. Native keyless inspect
accepts at most 1 GiB in one in-memory buffer and rejects metadata values that
cannot be represented exactly as JavaScript integers.
If you do not have a strong reason otherwise, start with:
preset: "balanced"compressionAlgorithm: "brotli"encryptionAlgorithm: "xchacha20-poly1305"
Higher-Level Helper Exports
The package also includes higher-level helper modules built on top of the native runtime:
KeyManager- key lifecycle and storage helper
SigningService- higher-level signing orchestration using Node.js crypto
StatsTracker- metrics collection for tests and measurement
- stream helpers
- compression
- decompression
- encryption
- decryption
- chunking
- line splitting
- limits helpers
- upload limit checks
- stream threshold helpers
- benchmarks
- compression
- encryption
- hashing
The package also re-exports the low-level runtime as a namespace:
import { rust } from "@voideddev/enc-server";That can be convenient when you want the raw native wrapper grouped under one namespace instead of pulling individual functions.
Fused Presets
The stable public fused presets are:
compactbalancedconcealed
Use balanced unless the application has a measured reason to prefer the
lower-overhead compact or heavier concealed shell profile.
Native Runtime Behavior
Important runtime facts:
- the package requires the native Node binding
- native loading happens at runtime when the package is first used
- the loader accepts only provenance-verified artifacts under
prebuilds/ - cached binaries under
native/are not a runtime fallback
For local development:
npm run build:native
npm run buildDevelopment
Useful commands:
npm run build
npm run build:native
npm run test
npm run test:native
npm run test:integration
npm run test:allThe package-level integration tests are especially useful when you change the monolith artifact model or its Node wrapper behavior.
Troubleshooting
The native module does not load
Usually this means one of these:
- there is no prebuilt binary for the current platform
- the local source build did not run successfully
- the workspace has not been built yet in local development
Typical fixes:
- install Rust if a source build is required
- run
npm run build:native - run
npm run build
I want the standard artifact path, but I am using encrypt/decrypt
Use protect/open instead. encrypt/decrypt are primitive AEAD helpers, while
protect/open are the monolith-first full-flow artifact APIs.
I only want the shell layer
Use fuse/unfuse instead of protect/open.
License
MIT
