//unsecurebysandros94

unsecure

A collection of runtime-agnostic cryptographically-secure utilities.

3
0
3
TypeScript

unsecure

npm version
npm downloads
bundle size

unsecure is a collection of runtime-agnostic cryptographically-secure utilities. (ba dum tss 🥁)

Usage

Install the package:

# ✨ Auto-detect (supports npm, yarn, pnpm, deno and bun)
npx nypm install unsecure

Import:

undefinedESM (Node.js, Bun, Deno)

// Main functions
import { hash, secureGenerate, secureCompare } from "unsecure";
// Utility functions
import {
  hexEncode,
  hexDecode,
  secureShuffle,
  // ...
} from "unsecure/utils";

undefinedCDN (Deno, Bun and Browsers)

// Main functions
import { hash, secureGenerate, secureCompare } from "https://esm.sh/unsecure";
// Utility functions
import {
  hexEncode,
  hexDecode,
  secureShuffle,
  // ...
} from "https://esm.sh/unsecure/utils";

hash

Hashes input data using a specified cryptographic algorithm. It uses the Web Crypto API, so it works in any modern JavaScript runtime.

options:

  • undefinedalgorithm: SHA-256, SHA-384, SHA-512 (default SHA-256)
  • undefinedreturnAs: hex, base64, base64url, bytes (default hex)
import { hash } from "unsecure";

// Hash an input using the default SHA-256 and return as a hex string
const hashHex = await hash("hello world");
// 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'

// Hash an input using the default SHA-256 and return as a base64 string
const hashBase64 = await hash("hello world", { returnAs: "base64" });
// 'UhywQV8aBkKEVtnvTpSMAnCoBkQjJSU8t6imt+Q9qcc='

// Hash an input using the default SHA-256 and return as a base64 URL string
const hashBase64URL = await hash("hello world", { returnAs: "base64url" });
// 'UhywQV8aBkKEVtnvTpSMAnCoBkQjJSU8t6imt-Q9qcc'

// Hash and get raw bytes (Uint8Array)
const hashBytes = await hash("hello world", { returnAs: "bytes" });
// Uint8Array(32) [ 185, 77, 39, 185, 147, 77, ... ]

// Hash using SHA-512
const hash512 = await hash("hello world", { algorithm: "SHA-512" });
// '309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f...'

secureGenerate (or generateSecureToken)

Generates a cryptographically secure string. You can customize its length and character set (all enabled by default). If a string is passed it will be used as a set of allowed characters.

Internally it uses a buffer, which is constantly updated, to minimize Web Crypto API calls and greatly improve performance. This becomes useful when generating 128-512 characters long tokens.

import { secureGenerate } from "unsecure";

// Generate a default 16-character password
const password = secureGenerate();
// e.g. 'Zk(p4@L!v9{g~8sB'

// Generate 28-character password
const password = secureGenerate(28);
// e.g. '4~j&zgf-tO+PoMBVl}tK/}5$FgzF'

// Generate a 24-character token with no special characters
const token = secureGenerate({
  length: 24,
  specials: false,
});

// Generate a pin using only custom numbers
const pin = secureGenerate({
  length: 6,
  uppercase: false,
  lowercase: false,
  specials: false,
  numbers: "13579",
});

// Generate a token with current timestamp prefix
const stamp = secureGenerate({ length: 20, timestamp: true });
// Output example: "mi6dcq...random..."

// Generate a token with a specific date prefix
const date = new Date("2023-01-01T00:00:00Z");
const datestamp = secureGenerate({ length: 20, timestamp: date });
// Output example: "lcclw5...random..."

secureCompare

Compares two values (string or Uint8Array) in a timing-attack-safe manner. The first argument is always the reference value, which determines the time it takes for verification.

import { secureCompare } from "unsecure";

const secret = "my-super-secret-token";
const userInput = "my-super-secret-token";
// from user input

if (secureCompare(secret, userInput)) {
  console.log("Tokens match!");
} else {
  console.log("Tokens do not match!");
}

// Also works with Uint8Array and mixed types
const mac1 = new Uint8Array([1, 2, 3]);
const mac2 = new Uint8Array([1, 2, 3]);
secureCompare(mac1, mac2); // true
secureCompare(secret, mac2); // false

Utilities (unsecure/utils)

A collection of supplementary utilities for encoding, decoding, and random number generation.

Encoding

Includes hexEncode, hexDecode, base64Encode, base64Decode, base64UrlEncode, and base64UrlDecode.

import { hexEncode, hexDecode } from "unsecure/utils";

const hex = hexEncode("hello"); // "68656c6c6f"
const text = hexDecode(hex); // "hello"

Randomness

Includes createSecureRandomGenerator, secureRandomNumber and secureShuffle.

import {
  createSecureRandomGenerator,
  secureRandomNumber,
  secureShuffle,
} from "unsecure/utils";

// Creates a secure random number generator (more performant for subsequent calls)
const generator = createSecureRandomGenerator();
const n = generator.next(1000); // Get a secure random number between 0 and 999

// Get a secure random number between 0 and 99 (more memory-efficient for single use)
const n = secureRandomNumber(100);

// Securely shuffle an array in-place
const list = [1, 2, 3, 4, 5];
secureShuffle(list); // e.g. [ 3, 1, 5, 2, 4 ]

// Or spread the original to not mutate it
const shuffled = secureShuffle([...list]);

sanitizeObject

Remove prototype-pollution vectors from a plain record in-place. It strips the dangerous own properties __proto__, prototype, and constructor from the target and all nested objects/arrays. It returns the same reference you pass in.

  • Deep, in-place sanitization over objects and arrays
  • Cycle-safe (handles circular references)
  • Leaves non-objects, functions, Dates, Maps/Sets unchanged
import { sanitizeObject } from "unsecure";

const payload: Record<string, unknown> = {
  user: {
    name: "alice",
    // potential pollution vectors
    __proto__: { hacked: true },
    profile: [{ constructor: "bad" }, { prototype: { x: 1 } }],
  },
};

sanitizeObject(payload); // returns the same reference

// After sanitization
Object.hasOwn(payload.user, "__proto__"); // false
Object.hasOwn(payload.user.profile[0]!, "constructor"); // false
Object.hasOwn(payload.user.profile[1]!, "prototype"); // false

Notes:

  • Only own properties named exactly __proto__, prototype, and constructor are removed.
  • The function doesn’t clone; it mutates the input value in-place for performance and memory efficiency.
  • Values like Date, Map, Set, functions, and primitives are returned unchanged (but still traversed through if found as nested values on a plain object/array).

Development

local development
  • Clone this repository
  • Install latest LTS version of Node.js
  • Enable Corepack using corepack enable
  • Install dependencies using pnpm install
  • Run interactive tests using pnpm dev

Credits

Inspired by DeepSource Corp work.

License

Published under the MIT license.
Made by community 💛






🤖 auto updated with automd

[beta]v0.14.0