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

@boringnode/encryption

v0.2.5

Published

A framework agnostic encryption library

Readme

@boringnode/encryption

typescript-image gh-workflow-image npm-image npm-download-image license-image

A framework-agnostic encryption library for Node.js. Built with simplicity and security in mind, @boringnode/encryption provides a unified API for encrypting and signing data with support for multiple encryption algorithms and key rotation.

Installation

npm install @boringnode/encryption

Features

  • Multiple Algorithms: ChaCha20-Poly1305, AES-256-GCM, AES-256-CBC
  • Key Rotation: Encrypt with new keys, decrypt with old ones
  • Purpose-Bound Encryption: Ensure encrypted values are used for their intended purpose
  • Expiration Support: Set time-to-live on encrypted values
  • Message Verification: Sign data without encrypting (HMAC-based)
  • Type-Safe: Full TypeScript support with typed payloads

Quick Start

1. Configure Encryption

import { Encryption } from '@boringnode/encryption'
import { chacha20poly1305 } from '@boringnode/encryption/drivers/chacha20_poly1305'

const encryption = new Encryption(
  chacha20poly1305({
    id: 'app',
    keys: [process.env.APP_KEY],
  })
)

2. Encrypt & Decrypt

// Encrypt any value
const encrypted = encryption.encrypt({ userId: 1, role: 'admin' })
// => "app.base64EncodedCipherText.base64EncodedIv.base64EncodedTag"

// Decrypt the value
const decrypted = encryption.decrypt(encrypted)
// => { userId: 1, role: 'admin' }

Supported Data Types

The library supports encrypting a wide range of data types:

  • Strings
  • Numbers
  • Booleans
  • Arrays
  • Objects
  • Dates

Encryption Drivers

ChaCha20-Poly1305 (recommended)

Modern, fast, and secure. Recommended for most use cases.

import { chacha20poly1305 } from '@boringnode/encryption/drivers/chacha20_poly1305'

const config = chacha20poly1305({
  id: 'app',
  keys: ['your-32-character-secret-key-here'],
})

AES-256-GCM

Industry-standard authenticated encryption.

import { aes256gcm } from '@boringnode/encryption/drivers/aes_256_gcm'

const config = aes256gcm({
  id: 'app',
  keys: ['your-32-character-secret-key-here'],
})

AES-256-CBC

Legacy support with HMAC authentication.

import { aes256cbc } from '@boringnode/encryption/drivers/aes_256_cbc'

const config = aes256cbc({
  id: 'app',
  keys: ['your-32-character-secret-key-here'],
})

Key Rotation

The library supports multiple keys for seamless key rotation. The first key is used for encryption, while all keys are tried during decryption.

const encryption = new Encryption(
  chacha20poly1305({
    id: 'app',
    keys: [
      process.env.NEW_APP_KEY, // Used for encryption
      process.env.OLD_APP_KEY, // Still valid for decryption
    ],
  })
)

// New encryptions use NEW_APP_KEY
const encrypted = encryption.encrypt('secret')

// Decryption works with both keys
encryption.decrypt(encryptedWithOldKey) // Works
encryption.decrypt(encryptedWithNewKey) // Works

Purpose-Bound Encryption

Ensure encrypted values are only used for their intended purpose:

// Encrypt with a purpose
const token = encryption.encrypt({ userId: 1 }, undefined, 'password-reset')

// Must provide same purpose to decrypt
encryption.decrypt(token, 'password-reset') // => { userId: 1 }
encryption.decrypt(token, 'email-verify')   // => null
encryption.decrypt(token)                    // => null

Expiration Support

Set a time-to-live on encrypted values:

// Expires in 1 hour
const token = encryption.encrypt({ userId: 1 }, '1h')

// Expires in 30 minutes
const token = encryption.encrypt({ userId: 1 }, '30m')

// Expires in 7 days
const token = encryption.encrypt({ userId: 1 }, '7d')

// After expiration, decrypt returns null
encryption.decrypt(expiredToken) // => null

Message Verifier

When you need to ensure data integrity without hiding the content, use the MessageVerifier. The payload is base64-encoded (not encrypted) and signed with HMAC.

import { MessageVerifier } from '@boringnode/encryption/message_verifier'

const verifier = new MessageVerifier(['your-secret-key'])

// Sign a value
const signed = verifier.sign({ userId: 1 })

// Verify and retrieve the value
const payload = verifier.unsign(signed)
// => { userId: 1 }

// Tampered values return null
verifier.unsign('tampered.value') // => null

The verifier also supports purpose and expiration:

// With expiration
const signed = verifier.sign({ userId: 1 }, '1h')

// With purpose
const signed = verifier.sign({ userId: 1 }, undefined, 'api-token')
const payload = verifier.unsign(signed, 'api-token')

Base64 Utilities

URL-safe base64 encoding/decoding utilities are available:

import { base64UrlEncode, base64UrlDecode } from '@boringnode/encryption/base64'

const encoded = base64UrlEncode('Hello World')
const decoded = base64UrlDecode(encoded, 'utf8')

HMAC

Generate and verify HMAC signatures:

import { Hmac } from '@boringnode/encryption'

const hmac = new Hmac(secretKey)

// Generate HMAC
const hash = hmac.generate('data to sign')

// Verify HMAC (timing-safe comparison)
const isValid = hmac.compare('data to sign', hash)

Error Handling

The library is designed to return null on decryption failures rather than throwing exceptions. This prevents timing attacks and simplifies error handling:

const result = encryption.decrypt(maybeInvalidValue)

if (result === null) {
  // Invalid, expired, wrong purpose, or tampered
}