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-auth
Import 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 privateKeyWuf = 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
: ExpectedAuthPayload
timePad
: 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