The "Bitcoin Auth" library simplifies authenticating REST APIs using Bitcoin keys by generating and verifying cryptographic signatures in an X-Auth-Token header.
Install with Bun:
bun add bitcoin-authImport and generate the token:
import { getAuthToken } from 'bitcoin-auth';
// Get a token
const token = getAuthToken({ privateKeyWif, requestPath });
// Include it in your API request
const response = await fetch("https://somedomain.com" + requestPath, {
headers: { 'X-Auth-Token': token }
});When your request includes a body:
const token = getAuthToken({ privateKeyWif, requestPath, body });Using Bitcoin Signed Message and specifying bodyEncoding:
const token = getAuthToken({
privateKeyWif,
requestPath,
scheme: 'bsm',
body: "eyJrZXkiOiJ2YWx1ZSJ9",
bodyEncoding: 'base64'
});- Auth Token Generation & Verification: Simple functions for handling tokens.
- Dual Cryptographic Schemes: Supports legacy 'bsm' and modern 'brc77' (recommended, BRC-77).
- Minimal Dependencies: Only requires the peer dependency
@bsv/sdk.
Tokens include:
- Request path (with query parameters)
- ISO8601 timestamp
- SHA256 hash of the body (if present)
- Signing scheme ('bsm' or 'brc77')
Token format:
pubkey|scheme|timestamp|requestPath|signature
Cryptographic schemes:
'brc77': Default and recommended, usesSignedMessage.sign()from BSV SDK.'bsm': Legacy Bitcoin Signed Message (BSM.sign()from BSV SDK).
import { getAuthToken, parseAuthToken, verifyAuthToken, AuthToken } from 'bitcoin-auth';
import { PrivateKey } from "@bsv/sdk";
const privateKeyWif = PrivateKey.fromRandom().toWif();
const requestPath = "/some/api/path?param1=value1";
const body = JSON.stringify(["hello", "world"]);
// body present, default (brc77) signing scheme, default body encoding (utf8)
const token = getAuthToken({ privateKeyWif, requestPath, body });
// no body, bsm signing scheme
const token = getAuthToken({ privateKeyWif, requestPath, scheme: 'bsm' });Parsing a token:
const parsedToken: AuthToken | null = parseAuthToken(tokenWithBody);
if (!parsedToken) {
console.error("Failed to parse bitcoin-auth token")
}
const { scheme, timestamp, requestPath, signature } = parsedToken;Verifying tokens:
const authPayload: AuthPayload = {
requestPath,
timestamp: new Date().toISOString(),
body
};
const isValid = verifyAuthToken(tokenWithBody, authPayload);
const payloadNoBody: AuthPayload = {
requestPath,
timestamp: new Date().toISOString()
};
const isValidNoBody = verifyAuthToken(tokenNoBodyBsm, payloadNoBody);Security Note: Always securely handle privateKeyWif.
Core authentication types:
AuthConfig:{ }AuthToken:{ pubkey, scheme, timestamp, requestPath, signature }AuthPayload: Data required for signing/verification:
export interface AuthPayload {
requestPath: string;
timestamp: string; // ISO8601 format
body?: string;
}Example payload construction:
const payloadWithBody: AuthPayload = {
requestPath: '/api/items',
timestamp: new Date().toISOString(),
body: JSON.stringify({ name: "gadget", price: 9.99 })
};
const payload: AuthPayload = {
requestPath: '/api/items/123',
timestamp: new Date().toISOString()
};Generates a token using an AuthConfig object:
config.privateKeyWif: Private key in WIF format (required)config.requestPath: Full URL path (required)config.body?: Optional request body stringconfig.scheme?: Signing scheme ('brc77'or'bsm', default'brc77')config.bodyEncoding?: Encoding for thebody('utf8','hex', or'base64', default'utf8')
Verifies a token:
token: Token stringtarget: ExpectedAuthPayloadtimePad: Allowed time skew in minutes (default5)bodyEncoding: Encoding type (default'utf8')
Returns true if valid, else false.
Parses token into AuthToken or returns null.
Use Bun to build and test:
bun run build
bun test