SessionKit docs
Security & versioning
How trust is established, what an attacker can and cannot do, and what we promise about upgrades.
SessionKit is the session layer of a wallet, so it is built on one rule: nothing is secret except private keys. The SDK, the protocol, and this documentation are all public. Anyone can read the code, fork it, or run it. Security comes from cryptography and user consent — never from obscurity.
How trust is established
Domain proof
Every BLAC Code carries an Ed25519 signature over its own contents, made by
a key published at https://your-domain/.well-known/blac-session.json. The wallet fetches that document over TLS and verifies the signature
before it shows anything to the user.
This means a scam site can run SessionKit — but it appears as its own domain, always. Impersonating you requires either your private key or a TLS certificate for your domain.
Consent
The approval screen shows the verified origin and every requested scope in plain language. Declining sends nothing at all — no user data exists anywhere until the moment of approval.
Pairwise identity
Each origin gets its own deterministically derived key pair, so the same user has a different id on every site. Two sites cannot compare notes and discover they share a user, and nobody gets a financial address unless they asked for one and the user agreed.
End-to-end encryption
P-256 ECDH between your session key and the wallet's, HKDF-SHA256 over a transcript that binds both public keys and the pairing topic, then AES-256-GCM for every message. Our relay forwards ciphertext it cannot read and stores nothing.
What an attacker can and cannot do
| Attack | Outcome |
|---|---|
| Claim to be your domain | Blocked. Codes are signed by a key served from the real domain. |
| Swap in their own key on your code | Blocked. The pairing topic is a hash of the key — a forged key can't match the scanned code. |
| Replay a captured login on another site | Blocked. The proof is bound to both the origin and that one session. |
| Add scopes to a valid request | Blocked. Any edit breaks the signature. |
| Compromise the relay | Yields ciphertext and downtime. No plaintext, no valid session. |
| Reverse engineer the SDK or wallet | Yields nothing. The protocol is published on purpose. |
| Show a victim a genuine code copied from your site | Mitigated, not blocked. This is inherent to every scan-to-login system: a screenshot of a real code, shown to someone else, is still a real code. Codes expire within seconds, the approval screen names your origin, and the login lands only in the session that requested the code — see "What you must do". |
| Run a real scam site with a real domain | Possible. See below. |
The honest limit
Cryptography proves which domain minted a code. It cannot prove that domain is honest, and it cannot prove that the page showing the code belongs to that domain. A typosquat with a valid certificate verifies correctly as itself, and a copied code verifies correctly as yours.
Three things contain that:
- BLACWALL domain reputation. Known-bad domains raise a hard warning in the approval screen; a domain the user has never connected to before is marked as new.
- A minimal scope catalog. The most a malicious site can obtain is what the user explicitly approved on screen.
- No money scope. No third-party session can move funds, so a bad decision costs an address, never a balance.
What you must do
- Keep the private key server-side. Environment variable, never in the repo, never in client code.
- Only sign for your own origin. Check
fields.originin your signing endpoint before signing. An open signing endpoint lets anyone borrow your identity. - Bind signing to the browser session that asked. Require
your own session cookie or a CSRF token on the signing endpoint, remember
which
pairingTopicyou signed for which session, and complete a login only into that session. A signing endpoint anyone can call mints genuine codes for anyone to relay; a session-bound one limits a relayed code to logging in the attacker's own session — which the short expiry then makes impractical. - Verify server-side. Call
verifyApprovalbefore you issue a cookie. The browser's word for who the user is means nothing on its own. - Rotate keys by publishing first. Add the new key to your well-known document, start signing with it, remove the old one after existing codes expire.
Versioning
The protocol version travels in the code itself, and BLAC Wallet speaks every version it has ever shipped. Your integration does not break behind your back.
- Additive changes — new scopes, new optional fields — keep the same version. Ignore what you don't recognise and you're forward-compatible.
- Breaking changes ship as a new version alongside the old one, with a deprecation window surfaced in the wallet before anything is retired.
- The CDN URL is major-pinned.
sessionkit.blaclabs.io/v1/receives patches and security fixes automatically; a new major is a new URL you opt into. - We can kill a broken version without you. The wallet and relay can refuse a version immediately — no coordination, no waiting for sites to update.
Reporting a vulnerability
Email security@blaclabs.io. Please give us a reasonable window to ship a fix before publishing. Anything affecting user funds or cross-origin identity leakage is treated as critical and worked immediately.