STIR/SHAKEN caller ID attestation and call signing for Node.js with built-in Asterisk AGI server integration and Iconectiv API support.
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:
npm install @gibme/stir-shaken
# or
yarn add @gibme/stir-shaken
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();
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
);
import { generateAccountKeys } from '@gibme/stir-shaken';
const { publicKey, privateKey } = generateAccountKeys();
// Returns PEM-encoded ECDSA P-256 keys
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'
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);
| 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 |
AGIStirShakenServerAsterisk 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 |
IconectivClient 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 listInstance Methods:
ServiceProviderToken(spc, accountKey, ca?) - Provision an SPC tokenSPCService 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 representationgenerateIdentityHeader(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 keyFull API documentation is available at https://gibme-npm.github.io/stir-shaken/