Secure storage (window.Electron.secureStorage)
Encrypted key/value storage, backed by Electron's OS-level safeStorage (Keychain / DPAPI / libsecret) plus a JSON file on disk. Source: src/main/secure-storage.ts, channel prefix secureStorage:*. Always on, no config needed — see Security configuration for the security.secureStorageKeys key-hashing option this module reads.
safeStorage only encrypts/decrypts individual strings — it isn't a database — so this module layers a plain JSON file at {userData}/secure-storage.json underneath it, with each value individually encrypted before being written. Every read-modify-write cycle (set/remove/clear) is queued through one promise chain per process, so two calls in a row can't silently clobber each other.
Methods
| Method | Returns | Notes |
|---|---|---|
isEncryptionAvailable() |
Promise<boolean> |
Whether the OS backend (Keychain/DPAPI/libsecret) is actually available. |
getSelectedStorageBackend() |
Promise<string> |
The OS backend Electron picked, when queryable; falls back to process.platform. |
set(key: string, value: string) |
Promise<void> |
Throws VALIDATION if key is empty. |
get(key: string) |
Promise<string | null> |
null when the key doesn't exist. Throws VALIDATION if key is empty. |
remove(key: string) |
Promise<void> |
|
clear() |
Promise<void> |
Wipes the whole store. |
keys() |
Promise<string[]> |
Throws NOT_CONFIGURED when security.secureStorageKeys is 'hashed' — see below. |
encryptString(value: string) |
Promise<string> |
One-off encryption without persisting to the store. |
decryptString(value: string) |
Promise<string> |
Inverse of encryptString. |
Key hashing (security.secureStorageKeys)
'plain' (default) keeps your original key names on disk — only the values are encrypted. 'hashed' stores a deterministic SHA-256 hash of ${appId}:${key} instead of the original name. In hashed mode, keys() always rejects with NOT_CONFIGURED rather than returning a list of unusable hashes — get()/remove() still work because they re-hash the key you pass in, but there's no way to recover the original names from what's stored. Existing data is not migrated automatically if you switch modes mid-project.
Example
await window.Electron.secureStorage.set('authToken', token);
const stored = await window.Electron.secureStorage.get('authToken'); // string | null
await window.Electron.secureStorage.remove('authToken');
.safe
Fully mirrored — window.Electron.safe.secureStorage.* resolves { ok: true, data } / { ok: false, error } instead of throwing. Useful for keys() specifically, since checking result.error.code === 'NOT_CONFIGURED' avoids a try/catch just to detect hashed-key mode.