Encryption & Key Management
AES-256-GCM encryption and AWS KMS key management
Data at Rest
All sensitive data stored by the platform is encrypted using AES-256-GCM:
API response payloads for dashboard sessions are encrypted end-to-end with a per-session derived key
Session keys are derived as
HMAC-SHA256(masterKey, userId:sessionId)— each session gets a unique keyRotating the master encryption key immediately invalidates all active sessions
Data in Transit
All API traffic uses TLS 1.2+. There are no unencrypted endpoints.
Incoming webhooks (from payment networks) are verified using RSA-SHA256 signature validation against published public keys. Requests with missing or invalid signatures are rejected and logged.
API Key Storage
API keys are never stored in plaintext. Only the SHA-256 hash of each key is persisted in MongoDB:
SHA-256 is appropriate here (not bcrypt) because 128-bit entropy makes brute-force infeasible and enables fast O(1) indexed lookups
The full key is shown once at creation via the dashboard and is not recoverable afterward
Revocation is instant — deleting the hash record immediately blocks all requests using that key
Signing Keys (AWS KMS)
On-chain signing operations (ERC-4337 UserOps, Safe transactions) use AWS KMS with secp256k1 key material:
The private key is generated inside and never leaves the KMS HSM
All signing requests call
kms.sign()— the plaintext key is never in application memoryThe IAM role requires only
kms:Signandkms:GetPublicKey— no export permissionsDER-encoded ECDSA signatures are normalized (low-S) for EVM compatibility
WebAuthn Passkey Authentication
Dashboard users authenticate using WebAuthn passkeys (device biometrics or hardware security keys):
No passwords stored anywhere in the system
Private keys are generated and stored by the device's secure enclave
The server verifies assertions using
@simplewebauthn/server— the private key never leaves the deviceSignature counters are checked on every login to detect cloned authenticators
For high-value actions (initiating a transfer from the dashboard), a second passkey ceremony is required — generating cryptographic proof that the user physically authorized the specific action.
Session Security
JWT access token
3 hours
API credential, auto-refreshed every 30 min
mw_sess httpOnly cookie
7 days
Session identity — not accessible by JavaScript
MongoDB UserSession
7 days
Server-side revocation support
Session key (in-memory)
Page load
AES key — never persisted to disk
Deleting a UserSession record from MongoDB immediately invalidates all tokens for that session, even within the 3-hour JWT lifetime.
Last updated
Was this helpful?