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

halite-ts

v5.0.0

Published

High-level cryptography interface powered by libsodium — TypeScript port of ParagonIE Halite

Readme

halite-ts

Version 5.0.0

A TypeScript port of ParagonIE Halite — a high-level cryptography library providing a safe, ergonomic API for common cryptographic operations, powered by libsodium.

import { ready, SymmetricCrypto, EncryptionKey } from 'halite-ts';

await ready();

const key = EncryptionKey.generate();
const encrypted = SymmetricCrypto.encrypt(key, 'hello world');
const decrypted = SymmetricCrypto.decrypt(encrypted, key);
console.log(decrypted.getString()); // "hello world"

Requirements

  • Node.js >= 22

Install

npm install halite-ts

Build

npm run build     # compiles src/ → dist/

Test

npm test          # runs node --test dist/test/**/*.test.js

Quick Reference

| Category | Import | Key Classes | |---|---|---| | Symmetric encryption | SymmetricCrypto | EncryptionKey | | Symmetric auth | SymmetricCrypto | AuthenticationKey | | Asymmetric encryption | AsymmetricCrypto | EncryptionSecretKey, EncryptionPublicKey | | Anonymous sealing | AsymmetricCrypto | EncryptionPublicKey / EncryptionSecretKey | | Digital signatures | AsymmetricCrypto | SignatureSecretKey, SignaturePublicKey | | Sign + encrypt | AsymmetricCrypto | SignatureSecretKey + EncryptionPublicKey | | Password hashing | Password | EncryptionKey | | Key derivation | KeyFactory | Various key types | | File operations | HaliteFile | Various key types | | Merkle trees | MerkleTree, TrimmedMerkleTree | Node | | Secure cookies | Cookie | EncryptionKey | | Utilities | Util | — |

API

Initialization

import { ready } from 'halite-ts';

// Must call once before using any crypto operations
await ready();

HiddenString

Wraps plaintext strings to prevent accidental leakage through debug output or logs.

import { HiddenString } from 'halite-ts';

const secret = new HiddenString('sensitive data');
secret.getString();        // "sensitive data"
console.log(secret);       // { value: '**protected**' }

Key Generation

import {
  EncryptionKey, AuthenticationKey,
  EncryptionKeyPair, SignatureKeyPair,
  EncryptionSecretKey, EncryptionPublicKey,
  SignatureSecretKey, SignaturePublicKey,
} from 'halite-ts';

// Symmetric keys
const encKey = EncryptionKey.generate();         // 32 bytes
const authKey = AuthenticationKey.generate();     // 32 bytes

// Asymmetric key pairs
const encKeyPair = EncryptionKeyPair.generate();  // X25519
const sigKeyPair = SignatureKeyPair.generate();   // Ed25519

Key Import / Export

Keys are exported as hex-encoded strings with a version prefix and checksum.

import { KeyFactory, HiddenString } from 'halite-ts';

// Export
const exported = KeyFactory.export(encKey);
console.log(exported.getString()); // hex string with version + checksum

// Import
const imported = KeyFactory.importEncryptionKey(exported);

// Other import methods:
KeyFactory.importAuthenticationKey(data: HiddenString)
KeyFactory.importEncryptionPublicKey(data: HiddenString)
KeyFactory.importEncryptionSecretKey(data: HiddenString)
KeyFactory.importSignaturePublicKey(data: HiddenString)
KeyFactory.importSignatureSecretKey(data: HiddenString)
KeyFactory.importEncryptionKeyPair(data: HiddenString)
KeyFactory.importSignatureKeyPair(data: HiddenString)

Key Derivation (from password)

Derive keys from passwords using scrypt with configurable security levels.

import { KeyFactory, HiddenString } from 'halite-ts';

const password = new HiddenString('correct horse battery staple');
const salt = sodium.randombytes_buf(16); // 16-byte salt

// Security levels
KeyFactory.INTERACTIVE  // ops=2,   mem=64MB   — for interactive use
KeyFactory.MODERATE     // ops=3,   mem=256MB  — for moderate security
KeyFactory.SENSITIVE    // ops=4,   mem=1024MB — for high-security

const encKey = KeyFactory.deriveEncryptionKey(password, salt, KeyFactory.INTERACTIVE);
const authKey = KeyFactory.deriveAuthenticationKey(password, salt);
const encKeyPair = KeyFactory.deriveEncryptionKeyPair(password, salt);
const sigKeyPair = KeyFactory.deriveSignatureKeyPair(password, salt);

Symmetric Encryption

XChaCha20-Poly1305 (Halite v5) or XSalsa20 (compatible with older Halite versions).

import { SymmetricCrypto, EncryptionKey } from 'halite-ts';

const key = EncryptionKey.generate();

// Encrypt / Decrypt
const ciphertext = SymmetricCrypto.encrypt(new HiddenString('hello'), key);
const plaintext = SymmetricCrypto.decrypt(ciphertext, key);

// With additional authenticated data
const ad = '{"context":"user-registration"}';
const enc = SymmetricCrypto.encryptWithAD(new HiddenString('data'), key, ad);
const dec = SymmetricCrypto.decryptWithAD(enc, key, ad);

// Encoding options (default: base64urlsafe)
SymmetricCrypto.encrypt(data, key, 'hex');
SymmetricCrypto.encrypt(data, key, 'base64');
SymmetricCrypto.encrypt(data, key, 'base64urlsafe');

Symmetric Authentication

BLAKE2b message authentication codes.

import { SymmetricCrypto, AuthenticationKey } from 'halite-ts';

const key = AuthenticationKey.generate();
const message = new TextEncoder().encode('authenticate me');

const mac = SymmetricCrypto.authenticate(message, key);
const valid = SymmetricCrypto.verify(message, key, mac);
// true

Asymmetric Encryption

X25519 key agreement + symmetric encryption.

import { AsymmetricCrypto, EncryptionKeyPair, HiddenString } from 'halite-ts';

const alice = EncryptionKeyPair.generate();
const bob = EncryptionKeyPair.generate();

// Alice encrypts to Bob
const ciphertext = AsymmetricCrypto.encrypt(
  new HiddenString('secret message'),
  alice.getSecretKey(),   // Alice's secret key
  bob.getPublicKey()      // Bob's public key
);

// Bob decrypts
const plaintext = AsymmetricCrypto.decrypt(
  ciphertext,
  bob.getSecretKey(),     // Bob's secret key
  alice.getPublicKey()    // Alice's public key
);

// With additional authenticated data
AsymmetricCrypto.encryptWithAD(data, senderSk, recipientPk, aad);
AsymmetricCrypto.decryptWithAD(ct, recipientSk, senderPk, aad);

Anonymous Sealing

Encrypt to a public key without sender authentication (crypto_box_seal).

import { AsymmetricCrypto, EncryptionKeyPair, HiddenString } from 'halite-ts';

const recipient = EncryptionKeyPair.generate();

const sealed = AsymmetricCrypto.seal(
  new HiddenString('anonymous message'),
  recipient.getPublicKey()
);

const opened = AsymmetricCrypto.unseal(sealed, recipient.getSecretKey());

Digital Signatures

Ed25519 detached signatures.

import { AsymmetricCrypto, SignatureKeyPair } from 'halite-ts';

const signer = SignatureKeyPair.generate();
const message = new TextEncoder().encode('important document');

const signature = AsymmetricCrypto.sign(message, signer.getSecretKey());
const ok = AsymmetricCrypto.verify(message, signer.getPublicKey(), signature);
// true

Sign-and-Encrypt / Verify-and-Decrypt

Combined authenticated encryption: sign with Ed25519, then encrypt the signed message.

import {
  AsymmetricCrypto,
  SignatureKeyPair, EncryptionKeyPair,
  HiddenString
} from 'halite-ts';

const sender = SignatureKeyPair.generate();
const recipient = EncryptionKeyPair.generate();

// Sender: sign + encrypt
const enc = AsymmetricCrypto.signAndEncrypt(
  new HiddenString('authenticated message'),
  sender.getSecretKey(),
  recipient.getPublicKey()
);

// Recipient: verify + decrypt
const dec = AsymmetricCrypto.verifyAndDecrypt(
  enc,
  sender.getPublicKey(),      // verify signature
  recipient.getSecretKey()    // decrypt
);

Password Hashing

Argon2id password hashing with encrypted hash storage.

import { Password, EncryptionKey, HiddenString, KeyFactory } from 'halite-ts';

const key = EncryptionKey.generate();
const password = new HiddenString('user password');

// Hash
const stored = await Password.hash(password, key, KeyFactory.INTERACTIVE);

// Verify
const match = await Password.verify(password, stored, key);
// true

// Check if rehashing is needed
const needsRehash = Password.needsRehash(stored, key, KeyFactory.MODERATE);

File Operations

Encrypt, seal, sign, or checksum files on disk.

import { HaliteFile, EncryptionKey, EncryptionKeyPair, SignatureKeyPair } from 'halite-ts';

const key = EncryptionKey.generate();

// Symmetric encrypt / decrypt
HaliteFile.encrypt('plain.txt', 'encrypted.txt', key);
HaliteFile.decrypt('encrypted.txt', 'decrypted.txt', key);

// Asymmetric encrypt / decrypt
const kp = EncryptionKeyPair.generate();
HaliteFile.asymmetricEncrypt('plain.txt', 'enc.asc', kp.getPublicKey(), kp.getSecretKey());
HaliteFile.asymmetricDecrypt('enc.asc', 'dec.txt', kp.getSecretKey(), kp.getPublicKey());

// Anonymous seal / unseal
HaliteFile.seal('plain.txt', 'sealed.txt', kp.getPublicKey());
HaliteFile.unseal('sealed.txt', 'open.txt', kp.getSecretKey());

// Digital signature (detached)
const signer = SignatureKeyPair.generate();
const sig = HaliteFile.sign('document.txt', signer.getSecretKey());
const verified = HaliteFile.verify('document.txt', signer.getPublicKey(), sig);

// Checksum (BLAKE2b)
const hash = HaliteFile.checksum('document.txt');                          // keyed hash
const hashKeyed = HaliteFile.checksum('document.txt', encryptionKey);

Merkle Trees

Binary hash trees using BLAKE2b. Supports configurable hash size and personalization strings.

import { MerkleTree, TrimmedMerkleTree, Node } from 'halite-ts';

const leaf1 = new Node(new TextEncoder().encode('transaction1'));
const leaf2 = new Node(new TextEncoder().encode('transaction2'));
const leaf3 = new Node(new TextEncoder().encode('transaction3'));

const tree = new MerkleTree(leaf1, leaf2, leaf3);
const root = tree.getRoot();

// Configurable hash size and personalization
tree.setHashSize(64).setPersonalizationString('MyApp');

// Trimmed Merkle Tree (supports subtree expansion)
const trimmed = new TrimmedMerkleTree(leaf1, leaf2);
const expanded = trimmed.getExpandedTree(leaf3);

Secure Cookies

Encrypted cookie value generation.

import { Cookie, EncryptionKey } from 'halite-ts';

const key = EncryptionKey.generate();
const cookie = new Cookie(key);

const encryptedValue = cookie.store('session', {
  userId: 42,
  role: 'admin'
});

Utilities

import { Util } from 'halite-ts';

// Hashing
Util.hash(data);                              // BLAKE2b (default 32 bytes)
Util.rawHash(data, 64);                       // custom output length
Util.keyedHash(data, key);                    // keyed BLAKE2b

// HKDF-BLAKE2b key derivation
Util.hkdfBlake2b(inputKeyMaterial, length, info, salt);

// Pre-Authentication Encoding
Util.PAE(piece1, piece2, piece3);

// XOR two equal-length byte arrays
Util.xorStrings(a, b);

// Constant-time memory zeroing
Util.memzero(sensitiveData);

// Safe copy
Util.safeStrcpy(data);

// Concatenate byte arrays
Util.concat(a, b, c);

Encoding

import { Halite } from 'halite-ts';

Halite.hexEncode(data);                  // Uint8Array → hex string
Halite.hexDecode(str);                   // hex string → Uint8Array
Halite.base64Encode(data);               // Uint8Array → base64
Halite.base64Decode(str);               // base64 string → Uint8Array
Halite.base64UrlSafeEncode(data);        // Uint8Array → base64url
Halite.base64UrlSafeDecode(str);        // base64url string → Uint8Array

Error Handling

All errors extend HaliteAlert:

| Error | Thrown When | |---|---| | InvalidKey | Key material validation fails | | InvalidMessage | Ciphertext is malformed or integrity check fails | | InvalidSignature | Signature verification fails | | InvalidSalt | Salt has wrong length | | InvalidDigestLength | Requested digest length is out of range | | InvalidType | Invalid encoding or type parameter | | CannotPerformOperation | Operation cannot be completed | | ConfigDirectiveNotFound | Configuration key is missing | | FileAccessDenied | File access is denied | | FileModified | File integrity check fails | | CannotSerializeKey | Key object cannot be serialized | | CannotCloneKey | Key object cannot be cloned |

import {
  HaliteAlert, InvalidKey, InvalidMessage,
  InvalidSignature, InvalidSalt, InvalidType,
  CannotPerformOperation, FileAccessDenied
} from 'halite-ts';

try {
  SymmetricCrypto.decrypt(tamperedCiphertext, key);
} catch (e) {
  if (e instanceof InvalidMessage) {
    console.error('Data integrity violation');
  }
}

Architecture

The library uses a versioned message format: every ciphertext and exported key includes a 4-byte version prefix (0x31 0x42 0x05 0x00 for Halite v5), enabling backward-compatible config resolution and format evolution.

For symmetric encryption, the library splits a master key into separate encryption and authentication sub-keys using HKDF-BLAKE2b (v5) or a simpler keyed BLAKE2b split (v4/v3), with domain separation strings to prevent key reuse across different operations.

License

MPL-2.0