From 1457de487fdebe3c1b161c6f58f75bd6b3ea8205 Mon Sep 17 00:00:00 2001
From: null
Date: Sun, 5 Jul 2026 19:15:32 -0500
Subject: [PATCH] feat(security): show a key fingerprint (not the key) in the
encryption status
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The encryption key must never be retrievable through the app (that would undo
the whole point of TOKEN_ENCRYPTION_KEY — a stolen session/XSS could then read
the master key). Instead surface a non-reversible fingerprint so operators can:
- verify which key is currently active,
- confirm a running instance matches the key they backed up, and
- spot an accidental key change (which would make existing secrets unrecoverable).
- encryptionService.keyFingerprint(): domain-separated SHA-256 prefix of the
active key (env if set, else the stored DB key); never force-creates a key
(returns null when none exists), shares nothing with the cipher derivation.
- admin bank-sync-config exposes key_fingerprint alongside encryption_key_source.
- Admin Bank Sync card renders it with backup guidance.
- Test: stable per key, differs by key, not reversible / not the raw key.
Co-Authored-By: Claude Opus 4.8
---
client/components/admin/BankSyncAdminCard.tsx | 12 ++++++++
routes/admin.js | 4 +--
services/encryptionService.js | 23 ++++++++++++++-
tests/encryptionService.test.js | 28 +++++++++++++++++++
4 files changed, 64 insertions(+), 3 deletions(-)
diff --git a/client/components/admin/BankSyncAdminCard.tsx b/client/components/admin/BankSyncAdminCard.tsx
index 65dbee2..53f3182 100644
--- a/client/components/admin/BankSyncAdminCard.tsx
+++ b/client/components/admin/BankSyncAdminCard.tsx
@@ -23,6 +23,7 @@ interface BankSyncConfig {
seed_days?: number;
worker?: BankSyncWorker;
encryption_key_source?: string;
+ key_fingerprint?: string | null;
}
function timeAgo(iso: string | null | undefined): string | null {
@@ -293,6 +294,17 @@ export default function BankSyncAdminCard() {
Regular database backups preserve all user connections.
+ {config?.key_fingerprint && (
+
+ Active key fingerprint{' '}
+ {config.key_fingerprint}
+ {' '}— a one-way check of the current key (never the key itself). Keep your{' '}
+ TOKEN_ENCRYPTION_KEY in a password manager; this fingerprint lets you
+ confirm a running instance matches the key you saved, and spot an accidental key change (which would make
+ existing secrets unrecoverable).
+