
Security News
Lovable’s OJ Rewrites Vite’s Dev Server in Rust as AI Lowers the Cost of Forking Open Source
Lovable’s OJ rewrites Vite’s dev server in Rust, reducing memory use and preview times as AI lowers the cost of open source reimplementation.
@otplib/core
Advanced tools
Core types, interfaces, and utilities for the otplib OTP library suite.
@otplib/core provides the foundational abstractions for all otplib packages. It includes:
CryptoContextBase32Contextnpm install @otplib/core
pnpm add @otplib/core
yarn add @otplib/core
otplib uses a plugin architecture for both cryptographic operations and Base32 encoding:
import type { CryptoPlugin, Base32Plugin } from "@otplib/core";
// Crypto plugins implement HMAC and random byte generation
interface CryptoPlugin {
name: string;
hmac(
algorithm: HashAlgorithm,
key: Uint8Array,
data: Uint8Array,
): Uint8Array | Promise<Uint8Array>;
randomBytes(length: number): Uint8Array;
}
// Base32 plugins implement encoding and decoding
interface Base32Plugin {
name: string;
encode(data: Uint8Array, options?: Base32EncodeOptions): string;
decode(str: string): Uint8Array;
}
The CryptoContext class provides a unified interface for crypto operations:
import { createCryptoContext } from "@otplib/core";
import { crypto as plugin } from "@otplib/plugin-crypto-node";
const crypto = createCryptoContext(plugin);
// Async HMAC computation
const digest = await crypto.hmac("sha1", key, data);
// Sync HMAC computation
const digest = crypto.hmacSync("sha1", key, data);
// Random bytes
const secret = crypto.randomBytes(20);
The Base32Context class provides a unified interface for Base32 operations:
import { createBase32Context } from "@otplib/core";
import { base32 as plugin } from "@otplib/plugin-base32-scure";
const base32 = createBase32Context(plugin);
// Encode binary data to Base32
const encoded = base32.encode(new Uint8Array([1, 2, 3]), { padding: false });
// Decode Base32 string to binary
const decoded = base32.decode("MFRGGZDFMZTWQ");
import { validateSecret, MIN_SECRET_BYTES, RECOMMENDED_SECRET_BYTES } from "@otplib/core";
try {
validateSecret(secretBytes);
} catch (error) {
if (error instanceof SecretTooShortError) {
console.error(`Secret must be at least ${MIN_SECRET_BYTES} bytes`);
} else if (error instanceof SecretTooLongError) {
console.error(`Secret must not exceed ${RECOMMENDED_SECRET_BYTES} bytes`);
}
}
import { validateCounter, MAX_COUNTER } from "@otplib/core";
try {
validateCounter(123n);
validateCounter(0);
} catch (error) {
if (error instanceof CounterNegativeError) {
console.error("Counter cannot be negative");
} else if (error instanceof CounterOverflowError) {
console.error(`Counter exceeds maximum (${MAX_COUNTER})`);
}
}
import { validateTime, validatePeriod, MIN_PERIOD, MAX_PERIOD } from "@otplib/core";
validateTime(Math.floor(Date.now() / 1000));
validatePeriod(30); // Default TOTP period
import { validateToken } from "@otplib/core";
try {
validateToken("123456", 6);
} catch (error) {
if (error instanceof TokenLengthError) {
console.error("Token has incorrect length");
} else if (error instanceof TokenFormatError) {
console.error("Token must contain only digits");
}
}
import { counterToBytes } from "@otplib/core";
// Convert counter to 8-byte big-endian array
const counterBytes = counterToBytes(42n);
// Output: Uint8Array [0, 0, 0, 0, 0, 0, 0, 42]
import { dynamicTruncate } from '@otplib/core';
// Extract 31-bit integer from HMAC result
const hmacResult = new Uint8Array([...]); // 20 bytes for SHA-1
const truncated = dynamicTruncate(hmacResult);
import { truncateDigits } from "@otplib/core";
// Convert truncated value to OTP string
const otp = truncateDigits(123456789, 6);
// Output: "456789"
import { constantTimeEqual } from "@otplib/core";
// Timing-safe comparison to prevent timing attacks
const isValid = constantTimeEqual("123456", "123456");
const isValid = constantTimeEqual(uint8Array1, uint8Array2);
All errors extend from OTPError:
import {
OTPError,
SecretError,
SecretTooShortError,
SecretTooLongError,
CounterError,
CounterNegativeError,
CounterOverflowError,
TimeError,
PeriodError,
TokenError,
TokenLengthError,
TokenFormatError,
CryptoError,
HMACError,
RandomBytesError,
} from "@otplib/core";
// Check error types
try {
// ... OTP operation
} catch (error) {
if (error instanceof SecretTooShortError) {
// Handle short secret
} else if (error instanceof CryptoError) {
// Handle crypto failure
}
}
type HashAlgorithm = "sha1" | "sha256" | "sha512";
type Digits = 6 | 7 | 8;
interface HOTPOptions {
secret: Uint8Array;
counter: number | bigint;
algorithm?: HashAlgorithm;
digits?: Digits;
}
interface TOTPOptions {
secret: Uint8Array;
epoch?: number; // Unix time in seconds
algorithm?: HashAlgorithm;
digits?: Digits;
period?: number; // Time step in seconds (default: 30)
}
interface HOTPVerifyOptions extends HOTPOptions {
token: string;
counterTolerance?: number | [number, number]; // Number: [0, n] look-ahead; Tuple: [past, future]
}
interface TOTPVerifyOptions extends TOTPOptions {
token: string;
epochTolerance?: number | [number, number]; // Time tolerance in seconds
}
interface VerifyResult {
valid: boolean;
delta?: number; // Counter/time steps from expected value
}
@otplib/hotp - HOTP implementation@otplib/totp - TOTP implementation@otplib/plugin-crypto-node - Node.js crypto plugin@otplib/plugin-crypto-web - Web Crypto API plugin@otplib/plugin-base32-scure - Base32 plugin using @scure/baseFull documentation available at otplib.yeojz.dev:
Speakeasy is a library for generating and verifying one-time passwords (OTPs) using TOTP and HOTP algorithms. It offers similar functionalities to @otplib/core but also includes additional features like QR code generation for easier secret sharing.
Notp is a minimalistic library for generating and verifying TOTP and HOTP tokens. It is lightweight and easy to use, making it a good alternative to @otplib/core for simpler use cases.
OtpAuth is a library that provides a comprehensive set of tools for generating and validating OTPs, including support for TOTP and HOTP. It also offers additional features like URI generation for easy integration with OTP apps.
FAQs
Core interfaces, types, and crypto abstraction for otplib
The npm package @otplib/core receives a total of 0 weekly downloads. As such, @otplib/core popularity was classified as not popular.
We found that @otplib/core demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Lovable’s OJ rewrites Vite’s dev server in Rust, reducing memory use and preview times as AI lowers the cost of open source reimplementation.

Security News
It has been one year since Shai-Hulud made its first appearance on npm.

Research
/Security News
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.