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

cryptofence

v0.1.1

Published

hashing and key derivation in pure typescript, sync, zero deps, runs everywhere

Readme

cryptofence

sha-2, hmac, pbkdf2 and hkdf in pure typescript. synchronous, zero deps, runs anywhere.

npm i cryptofence

why

when browser code touches node's crypto, bundlers reach for crypto-browserify and pull in a tree that has quietly rotted:

| package | weekly | last published | |---|---|---| | crypto-browserify | 11.8M | oct 2024 | | create-hash | 13.9M | april 2018 | | create-ecdh | 11.3M | august 2020 | | public-encrypt | 11.2M | october 2018 | | diffie-hellman | 11.2M | april 2018 | | browserify-cipher | — | april 2018 |

eleven million installs a week each, on packages that have not shipped in six to eight years. nobody is going to fix them.

this is the hashing and key derivation part, written once, with no dependencies at all.

use

import { sha256, hmac, pbkdf2Async, hkdf, toHex } from 'cryptofence'

toHex(sha256('hello'))                            // synchronous
toHex(hmac('sha256', key, message))
await pbkdf2Async('sha256', password, salt, 600000, 32)
hkdf('sha256', ikm, salt, info, 42)

streaming works the way you expect:

import { createHash } from 'cryptofence'

const h = createHash('sha512')
for await (const chunk of stream) h.update(chunk)
h.digest()

algorithms: sha224, sha256, sha384, sha512.

speed, honestly

pure javascript hashing is not native hashing. measured on an m-series mac against node's openssl:

sha256, 4MB      ours 104ms   node 2ms    38 MB/s
sha512, 4MB      ours 123ms   node 3ms
pbkdf2, 100k     ours 819ms   node 13ms

so:

  • on node, for large data, use node:crypto. it is right there and it is forty times quicker. this package is for where that is not an option.
  • for pbkdf2, use pbkdf2Async. it hands the work to webcrypto, which is native on node, workers, deno, bun and browsers — the same 100k rounds drop from 819ms to 13ms. it falls back to the sync code when webcrypto is missing or the algorithm is sha224, and the two are asserted to agree.

for the sizes this is usually reaching for — a token, a session id, a signature over a few kilobytes — the difference does not show up.

it says no to a few things

pbkdf2 under 1000 iterations throws. a low count is the usual way this gets misused, and quietly deriving a weak key is worse than failing.

timingSafeEqual reads every byte. comparing secrets with === stops at the first wrong byte, and the timing tells an attacker how much of a token they have guessed. there is a test asserting a difference in the first byte takes the same time as one in the last.

randomInt uses rejection sampling. taking a modulus of a random number skews the low end of the range.

a hash cannot be reused after digest(). it throws rather than silently returning a stale value.

correctness

38 tests, on two legs.

published vectors — fips 180-4 for sha-224/256/384/512, rfc 4231 for hmac, rfc 5869 test case 1 for hkdf including the intermediate PRK.

agreement with node's own openssl — every algorithm, against every input, must produce the identical digest to node:crypto. that covers hmac at key lengths either side of the block size, pbkdf2, hkdf at seven output lengths, a 1,000,000 byte input, streaming in chunks of ten different sizes so they straddle block boundaries, and every message length around the 55/56 and 111/112 padding edges where the length field forces an extra block.

api

  • createHash(alg){ update, digest, blockSize, digestLength }
  • hash(alg, data), sha224 / sha256 / sha384 / sha512
  • hmac(alg, key, data)
  • pbkdf2(alg, password, salt, iterations, length) — sync
  • pbkdf2Async(...) — same, via webcrypto
  • hkdf(alg, ikm, salt, info, length), hkdfExtract, hkdfExpand
  • timingSafeEqual(a, b)
  • randomBytes(n), randomInt(min, max?), randomUUID()
  • toHex(bytes), fromHex(string)

strings are treated as utf-8. everything else takes and returns Uint8Array.

runtime

the hashing is pure javascript and would run anywhere, but randomBytes, randomInt and randomUUID need crypto.getRandomValues, so node 20 or newer — node 18 went end of life in april 2025 and never exposed webcrypto as a global. workers, deno and bun all have it.

what it is not

no md5 or sha-1 — if you need them for a legacy checksum, they are not here on purpose. no ciphers, no public key operations. this is the hashing half.

license

MIT