Backend Guide
Building the Server-Side Certification Engine with BSV SDK
This guide covers backend patterns for implementing certificate issuance, field encryption, mutual authentication middleware, and certificate-gated routes using the BSV SDK, wallet-toolbox-client, and auth-express-middleware.
Complete Code Repository: https://github.com/bsv-blockchain-demos/certification-platform
All code examples in this guide are taken from the working implementation in the
backend/directory.
Table of Contents
Setup
Installation
Project Structure
Environment Configuration
Create .env:
SERVER_PRIVATE_KEY
32-byte hex private key — this IS the server's identity
BSV_NETWORK
'test' or 'main' — determines chain for wallet services
WALLET_STORAGE_URL
Remote storage endpoint for the full Wallet
PORT
Express server port
Server Identity & Key Architecture
Pattern 1: Deriving the Certifier Identity
Every participant in the BSV certificate system has an identity derived from an elliptic curve key pair (secp256k1). The server's private key generates its public identity:
See full implementation:
backend/src/wallet.ts
Where the Certifier Public Key Appears:
Key Derivation Chain:
Certificate Type
The certificate type is a base64-encoded string that categorizes the certificate. The SDK's Utils class handles encoding:
Utils.toArray(str, 'utf8') converts the string to a byte array. Utils.toBase64(bytes) encodes it. This is the standard way to create certificate type identifiers in the BSV SDK.
Wallet Configuration
Pattern 2: Two Wallet Tiers
The backend uses two different wallet types for different purposes:
ProtoWallet — Certificate Signing
Lightweight wallet created from just a PrivateKey. No storage, no network. Used exclusively for MasterCertificate.issueCertificateForSubject():
Why ProtoWallet? MasterCertificate.issueCertificateForSubject() only needs cryptographic operations (key derivation, encryption, signing). A ProtoWallet is sufficient and avoids the overhead of storage initialization.
Full Wallet — Auth Middleware
The auth middleware requires a full WalletInterface because it needs to decrypt certificate fields, manage session nonces, and respond to the client's auth protocol:
Construction Chain:
Why Two Wallets?
Issue certificates
No
No
ProtoWallet
Auth middleware (ECDH, sessions)
Yes
Yes
Full Wallet
Decrypt certificate fields
Yes
No
Full Wallet
Certificate Issuance
Pattern 3: MasterCertificate.issueCertificateForSubject()
The core issuance method creates a complete, encrypted, signed certificate for a given subject:
Parameters:
certifierWallet
ProtoWallet
Server's lightweight wallet
subjectPublicKey
string
User's identity key from request body
fields
Record<string, string>
Plaintext fields to encrypt
certificateType
string
"Y2VydGlmaWNhdGlvbg=="
getRevocationOutpoint
() => Promise<string>
Returns "000...0.0"
What Happens Internally:
Returning the Certificate:
Field Encryption Model
Certificate fields use a two-layer encryption scheme based on ECDH key agreement:
Why Two Layers?
Field values are encrypted with a shared key from ECDH
The shared key is encrypted in the keyring, targeted at the subject's public key
This means only the subject (user) or the certifier (server) can decrypt the fields.
Revocation Outpoint Format
The revocationOutpoint must follow the format <txid>.<outputIndex>:
In production, this would point to a real UTXO. Spending that UTXO revokes the certificate.
Auth Middleware & Sessions
Pattern 4: createAuthMiddleware Configuration
@bsv/auth-express-middleware implements mutual authentication between the client (browser wallet) and server. It intercepts requests on protected routes:
Configuration Parameters:
wallet
WalletInterface
Server's wallet — ECDH, decryption, session signing
certificatesToRequest.certifiers
string[]
Only accept certs from these public keys
certificatesToRequest.types
Record<string, string[]>
Certificate types and which fields to request
sessionManager
SessionManager
Manages auth session state
onCertificatesReceived
Callback
Called when client presents certificates
logger
Console
Logging interface
logLevel
string
'debug', 'info', 'warn', 'error'
Session Negotiation Protocol
SessionManager
SessionManager from @bsv/sdk manages the mapping between client identity keys and session tokens:
Certificate Verification & Field Decryption
Pattern 5: VerifiableCertificate
When the auth middleware receives certificates from a client, the onCertificatesReceived callback decrypts and verifies the certificate fields:
Decryption Flow:
onCertificatesReceived Callback
This callback fires when a client presents certificates during authentication:
Why the Server Can Decrypt
The server's wallet holds the same private key used as the certifier when issuing the certificate. Since field encryption keys are derived via ECDH between certifier and subject, the server has one side of the ECDH:
Verification Tracking
Use a simple in-memory map to track which users have verified certificates:
Protected Routes
Pattern 6: Certificate-Gated Endpoints
Routes placed after the auth middleware are automatically protected. The middleware adds req.auth.identityKey to authenticated requests:
Route Organization:
Certificate Revocation
Pattern 7: Session and Verification Cleanup
When a user revokes their certificate, clean up server-side state:
Revocation Flow:
Complete Server
Main Server Setup
See full implementation:
backend/src/server.ts
Important Concepts
SDK Class Reference
PrivateKey
@bsv/sdk
Server identity key
KeyDeriver
@bsv/sdk
Derives child keys from root private key
ProtoWallet
@bsv/sdk
Lightweight wallet for certificate signing
MasterCertificate
@bsv/sdk
Issues encrypted, signed certificates
VerifiableCertificate
@bsv/sdk
Wraps cert + keyring for field decryption
SessionManager
@bsv/sdk
Manages auth session state
Utils
@bsv/sdk
Base64 encoding, byte array conversions
Wallet
@bsv/wallet-toolbox-client
Full wallet implementation
WalletSigner
@bsv/wallet-toolbox-client
Transaction and message signing
WalletStorageManager
@bsv/wallet-toolbox-client
Manages storage providers
StorageClient
@bsv/wallet-toolbox-client
Connects to remote storage
Services
@bsv/wallet-toolbox-client
Network services (chain queries)
createAuthMiddleware
@bsv/auth-express-middleware
Factory for Express auth middleware
AuthRequest
@bsv/auth-express-middleware
Extended Request type with auth property
Route Architecture
Security Considerations
Private Key Storage: The
SERVER_PRIVATE_KEYshould be stored securely (environment variable, secrets manager) — never committed to source controlCORS: Configure
originto your frontend's domain in productionHTTPS: Use TLS in production for all endpoints
Revocation Outpoints: In production, use real UTXOs for certificate revocation tracking
Rate Limiting: Add rate limits to
/api/certifyto prevent abuse
BRC Standards Implemented
BRC-31
Auth Protocol
createAuthMiddleware + AuthFetch mutual authentication
BRC-42
Key Derivation
KeyDeriver derives child keys for field encryption
BRC-43
Security Levels
Certificate field keys use specific security levels in ECDH
BRC-52
Certificate Creation
MasterCertificate.issueCertificateForSubject()
BRC-53
Certificate Verification
VerifiableCertificate.decryptFields()
BRC-56
Wallet Wire Protocol
WalletClient communicates with extensions via BRC-56
Testing
Start the Server
Test Endpoints
Summary
This backend guide covered:
Server Identity — Deriving certifier public key from private key
Wallet Types — ProtoWallet for signing, full Wallet for auth middleware
Certificate Issuance —
MasterCertificate.issueCertificateForSubject()with field encryptionAuth Middleware —
createAuthMiddlewarefor mutual authenticationField Decryption —
VerifiableCertificate.decryptFields()for server-side verificationProtected Routes — Certificate-gated endpoints with verification tracking
Revocation — Session and verification cleanup
These patterns form the foundation for building self-hosted certification servers on BSV.
Next Steps
Frontend Application Guide — Build the browser-side interface
BSV SDK Documentation — Full SDK reference
BRC-52: Certificate Creation — Certificate standard specification
BRC-31: Auth Protocol — Authentication protocol details
Last updated
