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

@open-charging-cloud/totp

v0.3.1

Published

Time-based one-time password generator for Open Charging Cloud applications.

Readme

@open-charging-cloud/totp

CI Nightly npm

TOTP is a TypeScript library for creating Time-based One-Time Passwords (TOTPs).

https://www.npmjs.com/package/@open-charging-cloud/totp

It can be used e.g. for Secure Dynamic QR-Codes in E-Mobility or a secure alternative for legacy HTTP BASIC Authentication mechanisms using Authorization: TOTP login="<b64>", totp="<b64>".

The token format is frozen and independently specified. The C# TOTPGenerator in Vanaheimr Hermod derives byte-identical tokens. The written specification and its normative test-vector annex live in OpenChargingTechnology/Whitepapers → TimeBasedOneTimePasswords, and both implementations are held to that annex by the conformance suite TOTPConformanceTests — a harness per implementation, running the very same vectors (generated by an independent third implementation and vendored here under test/vectors/). The format was developed for OCPP v2.1, which specifies it in use case C25 "Ad hoc payment via a QR code" as "TOTP algorithm, version 1" — exactly this format with HMAC-SHA256 and the default Base62 alphabet.

Installation

npm install @open-charging-cloud/totp

Where it runs

Everywhere a one-time password is needed: Node, browsers, bundler output (webpack, Vite, esbuild, Rollup), Cordova, Deno, service workers. The library uses nothing that only Node has — no node:crypto, no Buffer — so a bundler needs no alias, no fallback and no polyfill for it, and test/portability.test.ts keeps it that way.

The HMAC comes from @noble/hashes, the library's only runtime dependency. It is what keeps the API synchronous: WebCrypto could compute the same digest in a browser, but only asynchronously, which would turn generateTOTPs() into a promise for every caller.

Usage

import { generateTOTPs } from "@open-charging-cloud/totp";

const totps = generateTOTPs("secure!Charging!");

console.log(totps.current);
console.log(totps.remainingTime);

You can also pass an options object:

const totps = generateTOTPs({
  sharedSecret:  "secure!Charging!",
  validityTime:   30,
  totpLength:     12,
  alphabet:      "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
  timestamp:      Date.now(),
  hashAlgorithm: "sha256"
});

API

generateTOTPs(sharedSecret, validityTime, totpLength, alphabet, timestamp, hashAlgorithm)

Generates TOTP values for the previous, current, and next time slot.

Parameters:

| Parameter | Description | Default | | --- | --- | --- | | sharedSecret | Shared secret string, at least 16 characters, without whitespace. | Required | | validityTime | Slot duration in seconds. | 30 | | totpLength | Generated token length. | 12 | | alphabet | Alphabet used for token characters. | Digits, lowercase letters, and uppercase letters | | timestamp | Unix timestamp in milliseconds or Date. | Date.now() | | hashAlgorithm | HMAC hash algorithm. Must be sha256, sha384, or sha512. | sha256 |

Returns:

{
  previous:       string;
  current:        string;
  next:           string;
  remainingTime:  number;
}

Security notes

The token format is shared with the C# TOTPGenerator in Vanaheimr Hermod, which produces byte-identical tokens for the same secret, time slot and alphabet — for all three hash algorithms, and both sides default to HMAC-SHA256. The format is therefore frozen: neither of the two quirks below can be "fixed" here without breaking every deployed verifier. So they are documented instead — with numbers, because the numbers are the interesting part.

Modulo bias

Each token character is chosen as hashByte % alphabet.length. Whenever the alphabet length does not divide 256, the first 256 % length characters of the alphabet are reachable from one extra byte value: with the default 62-character alphabet, 256 = 4·62 + 8, so its first eight characters (07) each appear with probability 5/256 ≈ 1.953 %, the remaining 54 with 4/256 ≈ 1.563 % — a relative excess of 25 %, easily visible in a frequency count over a few thousand tokens.

Per character this costs almost nothing in Shannon entropy (5.9497 bits instead of log₂ 62 ≈ 5.9542), and noticeably more in min-entropy, the measure a guessing attacker cares about: −log₂(5/256) ≈ 5.678 bits. A default 12-character token therefore carries ≈ 71.40 bits of Shannon entropy and ≈ 68.14 bits of min-entropy instead of the ideal 71.45 — the single most likely token is about ten times more probable than under a perfectly uniform draw, at (5/256)¹² ≈ 3.1·10⁻²¹, inside a 30-second validity window. For calibration: a six-digit RFC 6238 code carries 19.93 bits, and RFC 4226's dynamic truncation has a modulo bias of its own (2³¹ mod 10⁶ = 483 648, a 0.047 % excess for the residues below it). Ours is larger only because 256 and 62 are the same order of magnitude, while 2³¹ dwarfs 10⁶.

Choosing an alphabet whose length divides 256 removes the bias entirely, no code change required: appending - and _ to the default alphabet yields the 64-character base64url character set, and 256 = 4·64 exactly. A digits-only alphabet ("0123456789") leans the other way: 256 = 25·10 + 6, so 05 are 4 % more likely than 69.

Token length vs. hash length

Characters are read from the HMAC output at index (offset + i) % hashLength — the hash is a ring buffer. Position i + hashLength therefore always repeats position i, and a token longer than the hash simply starts over:

generateTOTPs("secure!Charging!", 30, 64, null, 1718611200000).current
// "akF3c7qY2uiuO4rpyU0SC0W8VFE6nvxz" + "akF3c7qY2uiuO4rpyU0SC0W8VFE6nvxz"
//  — the 32-character sha256 token, twice.

Entropy stops growing at hashLength characters:

| hashAlgorithm | Hash bytes | Longest useful token | Min-entropy at that length (default alphabet) | | --- | --- | --- | --- | | sha256 | 32 | 32 characters | ≈ 181.7 bits | | sha384 | 48 | 48 characters | ≈ 272.5 bits | | sha512 | 64 | 64 characters | ≈ 363.4 bits |

totpLength still accepts up to 255 — the bound is part of the shared format contract, and the C# implementation cycles identically — but characters beyond the hash length add no security, and the visible period incidentally reveals which hash algorithm produced the token. If you need a longer token, pick a longer hash, not a longer totpLength.

Development

npm install
npm test

The suite runs the canonical conformance vectors vendored under test/vectors/ (test/vectors.test.ts) — they come from the normative annex of the specification and are regenerated via the TOTPConformanceTests suite, never edited here.