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

sm-polyfill

v1.3.0

Published

SM2/SM3/SM4 polyfill for Node.js 16 and earlier. Provides SM2 signing/verification using sm-crypto when native OpenSSL support is unavailable.

Readme

sm-polyfill

NPM Version Node.js Version License: MIT

English | 中文

SM2/SM3/SM4 polyfill for Node.js 16 and earlier. Provides SM2 signing/verification using sm-crypto-v2 when native OpenSSL support is unavailable.

Background

Node.js 16 (OpenSSL 1.1.1) has partial SM algorithm support:

  • ✅ SM2 ECDH key exchange
  • ✅ SM3 hash
  • ✅ SM4 cipher
  • ❌ SM2 sign/verify (requires OpenSSL 3.0+)

Node.js 18+ (OpenSSL 3.0+) has full SM algorithm support.

This polyfill enables SM2 signing/verification on Node.js 16 by falling back to the pure JavaScript sm-crypto-v2 implementation when native support is unavailable.

Installation

npm install sm-polyfill

Usage

Basic Sign/Verify

const smPolyfill = require('sm-polyfill');

// Check if polyfill is being used
if (smPolyfill.needsPolyfill()) {
  console.log('Using SM2 polyfill (Node.js 16 or earlier)');
} else {
  console.log('Using native SM2 (Node.js 18+)');
}

// Sign data
const data = Buffer.from('Hello SM2!');
const privateKey = '-----BEGIN OPENSSH PRIVATE KEY-----\n...';
const signature = smPolyfill.sign(data, privateKey, 'sm3');

// Verify signature
const publicKey = 'ssh-sm2 AAAA...';
const verified = smPolyfill.verify(data, signature, publicKey, 'sm3');
console.log('Verified:', verified);

PEM Key Format

Both PEM and OpenSSH key formats are supported for sign and verify:

const smPolyfill = require('sm-polyfill');

// Generate a key pair (PEM format)
const keys = smPolyfill.generateKeyPair();
// keys.privateKey => SEC1 PEM (-----BEGIN EC PRIVATE KEY-----)
// keys.publicKey  => SPKI PEM (-----BEGIN PUBLIC KEY-----)

// Sign with PEM private key
const data = Buffer.from('Hello PEM!');
const sig = smPolyfill.sign(data, keys.privateKey, 'sm3');

// Verify with PEM public key
const ok = smPolyfill.verify(data, sig, keys.publicKey, 'sm3');
console.log('Verified:', ok); // true

SM3 Hash

const hash = smPolyfill.sm3('abc');
console.log(hash.toString('hex'));
// 66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0

SM4 Cipher

const crypto = require('crypto');
const key = crypto.randomBytes(16);
const iv = crypto.randomBytes(16);

// Encrypt
const cipher = smPolyfill.createSM4Cipher('sm4-ctr', key, iv);
const encrypted = Buffer.concat([cipher.update('Hello SM4!'), cipher.final()]);

// Decrypt
const decipher = smPolyfill.createSM4Decipher('sm4-ctr', key, iv);
const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);

Key Generation

const keys = smPolyfill.generateKeyPair();
console.log(keys.privateKey); // PEM format (SEC1)
console.log(keys.publicKey);  // PEM format (SPKI)

API

sign(data, privateKey, hashAlgo)

Sign data using SM2 with SM3 hash.

  • data: Buffer or string - Data to sign
  • privateKey: string or Buffer - Private key in PEM (SEC1) or OpenSSH format
  • hashAlgo: string - Must be 'sm3'
  • Returns: Buffer - Signature in DER format

verify(data, signature, publicKey, hashAlgo)

Verify SM2 signature with SM3 hash.

  • data: Buffer or string - Original data
  • signature: Buffer - Signature in DER format
  • publicKey: string or Buffer - Public key in PEM (SPKI), OpenSSH, or hex format
  • hashAlgo: string - Must be 'sm3'
  • Returns: boolean - True if signature is valid

sm3(data)

Compute SM3 hash.

  • data: Buffer or string - Data to hash
  • Returns: Buffer - 32-byte hash

createSM4Cipher(algorithm, key, iv)

Create SM4 cipher.

  • algorithm: string - 'sm4-ctr', 'sm4-cbc', etc.
  • key: Buffer - 16-byte key
  • iv: Buffer - Initialization vector
  • Returns: Cipher object

createSM4Decipher(algorithm, key, iv)

Create SM4 decipher.

  • algorithm: string - 'sm4-ctr', 'sm4-cbc', etc.
  • key: Buffer - 16-byte key
  • iv: Buffer - Initialization vector
  • Returns: Decipher object

generateKeyPair()

Generate an SM2 key pair in PEM format.

  • Returns: { privateKey: string, publicKey: string } - SEC1 private key and SPKI public key in PEM format

needsPolyfill()

Check if the polyfill is needed (native SM2 doesn't work).

  • Returns: boolean

checkNativeSM2Support()

Check if native SM2 signing works.

  • Returns: boolean

isSmCryptoAvailable()

Check if sm-crypto-v2 package is available.

  • Returns: boolean

parseOpenSSHPrivateKey(privateKey)

Parse OpenSSH format private key and extract the private key scalar.

  • privateKey: string or Buffer - OpenSSH format private key
  • Returns: string - Private key scalar as hex string

parseOpenSSHPublicKey(publicKey)

Parse OpenSSH format public key and extract the public key point.

  • publicKey: string or Buffer - OpenSSH format public key
  • Returns: string - Public key point (with 0x04 prefix) as hex string

signatureToDER(sigHex)

Convert sm-crypto-v2 signature format to DER.

  • sigHex: string - Signature as hex (r + s concatenated)
  • Returns: Buffer - DER-encoded signature

signatureFromDER(derSig)

Convert DER signature to sm-crypto-v2 format.

  • derSig: Buffer - DER-encoded signature
  • Returns: string - Signature as hex (r + s concatenated)

How It Works

  1. Detection: The library first checks if native SM2 signing works by attempting to sign and verify test data.

  2. Native Path: If native SM2 works AND the key is in PEM/DER format, it uses Node.js's built-in crypto.sign() and crypto.verify().

  3. Polyfill Path: If native SM2 doesn't work OR the key is in OpenSSH format, it:

    • Detects the key format (PEM or OpenSSH) automatically
    • For PEM keys: parses ASN.1 DER to extract raw key material (SEC1 for private, SPKI for public)
    • For OpenSSH keys: parses the OpenSSH key format to extract raw key material
    • Uses sm-crypto-v2 for the actual signing/verification
    • Converts between DER and sm-crypto-v2 signature formats

Key Format Support

The polyfill supports multiple key formats:

| Format | Private Key | Public Key | |--------|------------|------------| | PEM (SEC1/SPKI) | -----BEGIN EC PRIVATE KEY----- | -----BEGIN PUBLIC KEY----- | | OpenSSH | -----BEGIN OPENSSH PRIVATE KEY----- | ssh-sm2 AAAA... | | Hex | — | Raw hex string |

Requirements

  • Node.js >= 14.0.0
  • sm-crypto-v2 package (installed automatically)

License

MIT