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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@mkvisuals/hmac-simple

v0.2.0

Published

Simple HMAC-based authentication library for Node.js with replay attack prevention

Readme

@mkvisuals/hmac-simple

Simple HMAC-based authentication library with built-in replay attack prevention.

Features

  • HMAC-based request signing and verification
  • Works in both Node.js and browsers
  • Replay attack prevention with nonce tracking
  • Timestamp validation
  • Constant-time signature comparison to prevent timing attacks
  • Automatic cleanup of expired nonces
  • TypeScript support with full type definitions
  • Both ESM and CommonJS support
  • Tiny bundle size (~4.5KB ESM, ~3KB CJS)

Installation

npm install @mkvisuals/hmac-simple

Usage

import { HmacSimple, HMAC_HEADERS } from '@mkvisuals/hmac-simple';

// Initialize with a shared secret key
const hmac = new HmacSimple({
  secretKey: 'your-secret-key-here',
  algorithm: 'sha256', // optional, default: 'sha256'
  timestampToleranceMs: 5 * 60 * 1000, // optional, default: 5 minutes
  nonceMaxAgeMs: 30 * 60 * 1000, // optional, default: 30 minutes
});

// Client: Create headers for an outgoing request (async)
const clientId = 'client-123';
const requestBody = JSON.stringify({ data: 'example' });
const headers = await hmac.createHeaders(clientId, requestBody);

console.log(headers);
// {
//   'x-hmac-id': 'client-123',
//   'x-hmac-timestamp': '1234567890',
//   'x-hmac-nonce': 'abc123...',
//   'x-hmac-signature': 'def456...'
// }

// Server: Verify headers from an incoming request (async)
const result = await hmac.verifyHeaders(
  headers[HMAC_HEADERS.id],
  headers[HMAC_HEADERS.ts],
  headers[HMAC_HEADERS.nonce],
  headers[HMAC_HEADERS.sig],
  requestBody
);

if (result.valid) {
  console.log('Request authenticated successfully');
} else {
  console.error('Authentication failed:', result.error);
}

API Reference

HmacSimple

Constructor

new HmacSimple(config: HmacConfig)

Config Options:

  • secretKey (string, required): The shared secret key used for HMAC signature generation
  • algorithm (string, optional): Hash algorithm to use (default: 'sha256')
  • timestampToleranceMs (number, optional): Maximum allowed time difference in milliseconds (default: 300000 - 5 minutes)
  • nonceMaxAgeMs (number, optional): How long to track nonces in milliseconds (default: 1800000 - 30 minutes)

Methods

async createHeaders(clientId: string, payload?: string): Promise<Record<string, string>>

Creates HMAC authentication headers for a request.

Parameters:

  • clientId: Unique identifier for the client
  • payload: Optional request payload (typically JSON stringified body)

Returns: Promise resolving to an object containing HMAC headers

async verifyHeaders(clientId: string, timestamp: string, nonce: string, signature: string, payload?: string): Promise<HmacVerificationResult>

Verifies HMAC authentication headers from a request.

Parameters:

  • clientId: Client identifier from the request
  • timestamp: Timestamp from the request header
  • nonce: Nonce from the request header
  • signature: Signature from the request header
  • payload: Optional request payload to verify

Returns: Promise resolving to a verification result object with valid boolean and optional error message

getNonceCount(): number

Returns the current number of tracked nonces (useful for monitoring).

destroy(): void

Cleans up resources by clearing all tracked nonces.

HMAC_HEADERS

Object containing header name constants:

{
  id: 'x-hmac-id',
  ts: 'x-hmac-timestamp',
  nonce: 'x-hmac-nonce',
  sig: 'x-hmac-signature',
}

Complete Example

Client (Making a Request)

import { HmacSimple } from '@mkvisuals/hmac-simple';

const hmac = new HmacSimple({ secretKey: 'shared-secret' });
const clientId = 'client-123';

async function makeAuthenticatedRequest() {
  const body = JSON.stringify({ action: 'getData' });
  const headers = await hmac.createHeaders(clientId, body);

  const response = await fetch('https://api.example.com/data', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      ...headers,
    },
    body,
  });

  return response.json();
}

Server (Verifying a Request)

import express from 'express';
import { HmacSimple, HMAC_HEADERS } from '@mkvisuals/hmac-simple';

const app = express();
const hmac = new HmacSimple({ secretKey: 'shared-secret' });

app.use(express.json());

app.post('/data', async (req, res) => {
  const clientId = req.headers[HMAC_HEADERS.id];
  const timestamp = req.headers[HMAC_HEADERS.ts];
  const nonce = req.headers[HMAC_HEADERS.nonce];
  const signature = req.headers[HMAC_HEADERS.sig];

  const payload = JSON.stringify(req.body);

  const result = await hmac.verifyHeaders(clientId, timestamp, nonce, signature, payload);

  if (!result.valid) {
    return res.status(401).json({ error: result.error });
  }

  // Request is authenticated
  res.json({ success: true, data: 'your data here' });
});

app.listen(3000);

Security Considerations

  • Secret Key: Keep your secret key secure and never commit it to version control
  • HTTPS: Always use HTTPS in production to prevent man-in-the-middle attacks
  • Payload Verification: Always include the request payload in the signature to prevent tampering
  • Time Synchronization: Ensure server clocks are synchronized (NTP) for timestamp validation
  • Nonce Storage: For distributed systems, consider using a shared cache (Redis) for nonce tracking

License

MIT