@gibme/stir-shaken
v22.0.1
Published
STIR/SHAKEN CallerID Attestation & Call Signing
Maintainers
Readme
@gibme/stir-shaken
STIR/SHAKEN caller ID attestation and call signing for Node.js with built-in Asterisk AGI server integration and Iconectiv API support.
Overview
STIR/SHAKEN (Secure Telephone Identity Revisited / Signature-based Handling of Asserted information using toKENs) is a framework that cryptographically verifies the legitimacy of the calling party and their authorization to use a particular telephone number, helping prevent caller ID spoofing and robocall fraud.
This package provides:
- AGI Server for automatic STIR/SHAKEN call signing in Asterisk PBX systems
- Identity header generation using ES256-signed JWTs
- Iconectiv API client for SPC token provisioning, CRL retrieval, and CA trust list management
- Service Provider Code (SPC) ASN.1 DER encoding and decoding
- ECDSA key generation and fingerprinting utilities
- Auto formats caller ID and called numbers into E.164 format when signing
Requirements
- Node.js >= 22
Installation
npm install @gibme/stir-shaken
# or
yarn add @gibme/stir-shakenQuick Start
AGI Server
Set up an Asterisk AGI server that automatically signs outbound calls:
import { AGIStirShakenServer } from '@gibme/stir-shaken';
const server = new AGIStirShakenServer({
port: 4573,
certificatePath: './certificate.pem',
privateKeyPath: './private-key.pem',
publicCertificateURL: 'https://example.com/certificate.pem',
attestationProvider: async (callerId, channel) => {
// Determine attestation level based on your business logic
return 'A';
},
logger: (entry) => {
console.log(`[${entry.event}] ${entry.message}`);
}
});
await server.start();Generate Identity Headers Directly
import { generateIdentityHeader } from '@gibme/stir-shaken';
import { readFileSync } from 'fs';
const privateKey = readFileSync('./private-key.pem', 'utf8');
const header = generateIdentityHeader(
'+15550100', // caller ID
'+15550200', // called number
'unique-call-id', // unique ID
'A', // attestation level
'https://example.com/cert.pem',
privateKey
);Key Generation
import { generateAccountKeys } from '@gibme/stir-shaken';
const { publicKey, privateKey } = generateAccountKeys();
// Returns PEM-encoded ECDSA P-256 keysService Provider Code Encoding
import { SPC } from '@gibme/stir-shaken';
// Encode a numeric SPC to DER/Base64
const spc = new SPC('8864');
console.log(spc.tkvalue); // 'MAigBhYEODg2NA=='
// Decode back to numeric
const decoded = SPC.from('MAigBhYEODg2NA==');
console.log(decoded.value); // '8864'Iconectiv API
import { Iconectiv, generateAccountKeys } from '@gibme/stir-shaken';
// Static methods (no authentication required)
const crl = await Iconectiv.crl();
const caList = await Iconectiv.STICertificateAuthorities();
// Authenticated methods
const api = new Iconectiv('username', 'password');
const { publicKey } = generateAccountKeys();
const token = await api.ServiceProviderToken('8864', publicKey);Attestation Levels
| Level | Name | Description | |-------|------|-------------| | A | Full | Originating carrier has authenticated the caller and verified they are authorized to use the calling number | | B | Partial | Originating carrier has authenticated the call source but cannot verify the caller's authorization for the number | | C | Gateway | Call originated from a gateway where the carrier cannot authenticate the source |
API Reference
Classes
AGIStirShakenServer
Asterisk AGI server that listens for incoming channel connections and signs calls with STIR/SHAKEN Identity headers.
Options:
| Property | Type | Description |
|----------|------|-------------|
| port | number | Port to bind to |
| host | string | Host/IP address (default: "0.0.0.0") |
| certificatePath | string | Path to STI certificate file |
| privateKeyPath | string | Path to the private key file |
| publicCertificateURL | string | Publicly reachable URL to the certificate |
| attestationProvider | (callerId, channel?) => AttestationLevel | Callback to determine attestation level |
| logger | (entry) => void | Optional structured logging callback |
Iconectiv
Client for the Iconectiv STIR/SHAKEN service provider API.
Static Methods:
accessible()- Check if the Iconectiv API is reachablecrl()- Fetch the Certificate Revocation ListSTICertificateAuthorities()- Retrieve the STI CA trust list
Instance Methods:
ServiceProviderToken(spc, accountKey, ca?)- Provision an SPC token
SPC
Service Provider Code encoder/decoder using ASN.1 DER encoding.
new SPC(value)- Create from numeric SPCSPC.from(tkvalue)- Decode from Base64 DER token.value- Numeric SPC string.tkvalue- Base64-encoded DER representation
Functions
generateIdentityHeader(callerId, calledNumber, uniqueId, attestationLevel, certificateUrl, privateKey)- Generate a signed STIR/SHAKEN Identity headergenerateAccountKeys(namedCurve?)- Generate ECDSA key pairs (default: P-256)generateKeyFingerprint(input)- Compute SHA256 fingerprint of a key
Certificate Requirements
- Certificate: X.509 STI certificate with CN or SAN containing the Service Provider Code
- Private Key: PEM-encoded ECDSA key corresponding to the certificate
- Public URL: The certificate must be publicly accessible for call recipients to verify signatures
Documentation
Full API documentation is available at https://gibme-npm.github.io/stir-shaken/
