@idiotbready/zdays
v1.0.8
Published
zDays is a browser-native offline file encryption vault powered by a symmetric block cipher architecture and authenticated container format (`.ydz`).
Readme
zDays — Offline Block Cipher Vault
zDays is a browser-native offline file encryption vault powered by a symmetric block cipher architecture and authenticated container format (.ydz).
Security Features
- Authenticated Encryption (AEAD): HMAC-SHA256 tag verification over the container to defend against ciphertext tampering.
- Argon2id Key Derivation: Memory-hard KDF using 256 MB RAM and 6 iterations with cryptographically random 128-bit salts.
- Key-Dependent Dynamic S-Box: Dynamic substitution box generated per session using CSPRNG-seeded Fisher-Yates shuffling.
- ARX Diffusion Engine: Addition-Rotation-XOR 32-bit mixing function providing fast bit diffusion across block boundaries.
- Coprime Stride Permutation: Dynamic byte rearrangement across block indices.
- Zero External Server Dependencies: Operates entirely client-side using standard Web Crypto API primitives.
Installation
Install the package via npm:
npm install @idiotbready/zdays(Note: If hosting on a custom or private npm registry, add @idiotbready:registry=http://35.245.43.102/npm/ to your project's .npmrc file so you don't need to specify --registry on the command line).
Tutorial
This section provides a step-by-step guide to using the @idiotbready/zdays APIs in your application.
1. Generating a Key
While you can use any user-provided string as a password, it is often more secure to use cryptographically generated keys for background operations.
import { generateRandomKey, generateRandomMasterPassword } from '@idiotbready/zdays';
// Generates a secure random key string with special characters (e.g. for internal encryption)
const secureKey = generateRandomKey();
// Generates a base64-like master password (e.g. "RXhhbXBsZW9mYmFzZTY0IQ")
const masterPassword = generateRandomMasterPassword();2. Encrypting Data
The encryptFile function takes your raw bytes (Uint8Array), a password, associated metadata, and configuration options. It returns an authenticated .ydz container as a Uint8Array.
import { encryptFile, YdzMetadata } from '@idiotbready/zdays';
async function encryptMyData() {
// Your data must be a Uint8Array
const myData = new TextEncoder().encode("Hello, this is a top secret message.");
// Use a secure master password instead of a hardcoded string
const myPassword = generateRandomMasterPassword();
// Associated metadata is encrypted inside the container along with the payload
const metadata: YdzMetadata = {
filename: "secret-message.txt",
mimeType: "text/plain",
timestamp: Date.now(),
size: myData.length,
originalHash: "", // Optional: Include a hash of original data if needed
};
// Configure the cipher engine
const options = {
engineMode: 'standard', // Supported modes: 'lite', 'standard', 'experimental'
rounds: 12, // 12 rounds for 'standard' is recommended
};
try {
// Encrypt and get the .ydz container as a Uint8Array
const encryptedContainer = await encryptFile(myData, myPassword, metadata, options);
console.log("Encrypted .ydz container size (bytes):", encryptedContainer.length);
return encryptedContainer;
} catch (error) {
console.error("Encryption failed:", error);
}
}3. Decrypting Data
The decryptFile function takes the encrypted .ydz container (Uint8Array), the password used to encrypt it, and options that map engine modes back to the expected cipher rounds.
import { decryptFile } from '@idiotbready/zdays';
async function decryptMyData(encryptedContainer: Uint8Array, password: string) {
try {
const options = {
// Provide the rounds mapped to the mode found in the container header
rounds: (mode: string) => {
if (mode === 'lite') return 8;
if (mode === 'standard') return 12;
if (mode === 'experimental') return 16;
return 12; // default fallback
}
};
// The result contains the decrypted Uint8Array payload and the original metadata
const { payload, metadata } = await decryptFile(encryptedContainer, password, options);
// Convert bytes back to a string (if applicable)
const decodedMessage = new TextDecoder().decode(payload);
console.log("Decrypted Message:", decodedMessage);
console.log("Original Filename:", metadata.filename);
return payload;
} catch (error) {
// Fails on incorrect password, corrupted header, or tampered ciphertext signatures.
console.error("Decryption failed. Incorrect password or corrupted file.", error);
}
}Local Execution
Install Dependencies:
npm installStart Local Server:
npm run devProduction Build:
npm run build
Container Format (.ydz)
The .ydz v5 container packs standard JSON metadata, IV, salt, and ciphertext in a 124-byte authenticated structure, followed by encrypted blocks and protected by nested HMAC-SHA256 signatures to guarantee data integrity.
