# How to Implement Secure Credential Storage and Encryption in Fincept Terminal

> Secure credential storage in Fincept Terminal uses OS-native services like Windows Credential Manager and macOS Keychain for robust API key protection. Learn how encryption is delegated for enhanced security.

- Repository: [Fincept Corporation/FinceptTerminal](https://github.com/Fincept-Corporation/FinceptTerminal)
- Tags: how-to-guide
- Published: 2026-04-20

---

**Fincept Terminal uses a two-layer architecture combining OS-native secret services with per-account key scoping to protect API keys and tokens, delegating encryption to Windows Credential Manager, macOS Keychain, and a temporary XOR obfuscation on Linux.**

The Fincept Terminal trading platform stores sensitive broker credentials through a hardened abstraction layer that avoids custom cryptography in favor of operating-system native secure storage. The **SecureStorage** class in [`fincept-qt/src/storage/secure/SecureStorage.h`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/fincept-qt/src/storage/secure/SecureStorage.h) provides a unified API for persisting secrets, while **AccountManager** in [`fincept-qt/src/trading/AccountManager.h`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/fincept-qt/src/trading/AccountManager.h) orchestrates credential lifecycles with per-account isolation. Together, these components ensure that API keys, access tokens, and user secrets remain encrypted at rest without exposing plain text to the application layer.

## SecureStorage Architecture and Key Scoping

The credential system centers on two primary classes that separate storage mechanics from business logic.

**SecureStorage** exposes three core operations—`store()`, `retrieve()`, and `remove()`—implemented in [`fincept-qt/src/storage/secure/SecureStorage.cpp`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/fincept-qt/src/storage/secure/SecureStorage.cpp). These methods delegate to platform-native backends:

- **Windows**: DPAPI-encrypted Credential Manager via `CredWriteW`
- **macOS**: Keychain Services via `SecKeychainAddGenericPassword` 
- **Linux**: XOR-obfuscated `QSettings` (with planned libsecret migration)

**AccountManager** consumes this API to manage **BrokerCredentials** structures defined in [`fincept-qt/src/trading/BrokerInterface.h`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/fincept-qt/src/trading/BrokerInterface.h). It enforces per-account key scoping using the format `account.<account_id>.<field>`, preventing cross-account leakage. For example, an API key for account `12345` stores under `account.12345.api_key`.

## Storing Credentials with AccountManager

To persist credentials, populate a **BrokerCredentials** object and invoke `AccountManager::save_credentials()`.

```cpp
// Create and populate credentials
BrokerCredentials creds;
creds.broker_id    = "alpaca";
creds.api_key      = "PK_TEST_KEY";
creds.api_secret   = "SECRET_VALUE";
creds.access_token = "jwt_token_123";
creds.user_id      = "user456";

// Persist to secure storage
AccountManager::instance().save_credentials(account_id, creds);

```

Under the hood, `save_credentials()` constructs keys like `account.<id>.api_key` and delegates to `SecureStorage::store()`.

- **Windows**: Calls `CredWriteW` with a `CREDENTIALW` structure (lines 65-81 in [`SecureStorage.cpp`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/SecureStorage.cpp))
- **macOS**: Invokes `SecKeychainAddGenericPassword` after deleting existing entries (lines 83-107)
- **Linux**: XOR-obfuscates the payload and writes Base64 to `QSettings` under the `secure/` namespace (lines 109-117)

All operations return a **Result<T>** object, allowing error handling without exceptions. Failed writes trigger `LOG_ERROR` entries while leaving the application state intact.

## Retrieving and Clearing Credentials

Loading credentials mirrors the storage pattern with automatic decryption on supported platforms.

```cpp
// Load credentials for a specific account
BrokerCredentials creds = AccountManager::instance().load_credentials(account_id);

if (!creds.api_key.isEmpty()) {
    // Initialize broker client with decrypted credentials
}

```

On Windows and macOS, `SecureStorage::retrieve()` returns clear text after the OS automatically decrypts the secret. On Linux, the method decodes Base64 and reverses the XOR obfuscation (lines 55-64 in [`SecureStorage.cpp`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/SecureStorage.cpp)).

To remove credentials permanently:

```cpp
AccountManager::instance().clear_credentials(account_id);

```

This calls `SecureStorage::remove()` for each stored field, deleting entries from the respective backend.

## Platform-Specific Encryption Backends

Fincept Terminal leverages native OS security rather than implementing custom encryption algorithms.

**Windows**: Uses `CredWriteW` to store secrets in the Windows Credential Manager, automatically protected by DPAPI (Data Protection API). The implementation creates `CREDENTIALW` structures with the `CRED_TYPE_GENERIC` type.

**macOS**: Integrates with Keychain Services via `SecKeychainAddGenericPassword`. The code handles item updates by first deleting existing entries, ensuring atomic replacement of secrets.

**Linux**: Currently implements a **deliberately weak XOR obfuscation** only to prevent casual inspection of `QSettings` files. The source code at lines 112-117 of [`SecureStorage.cpp`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/SecureStorage.cpp) contains TODO markers indicating planned migration to **libsecret** or similar secret-service integration. Do not rely on the Linux implementation for production security without replacing this backend.

## Migrating Legacy Credentials

Historical versions stored credentials under flat keys like `broker.<broker_id>.api_key`. The `AccountManager` constructor automatically invokes `migrate_legacy_credentials()` (lines 49-128 in [`AccountManager.cpp`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/AccountManager.cpp)) to transition data to the scoped format.

The migration process:

1. Checks a flag in `SettingsRepository` to prevent duplicate runs
2. Iterates registered brokers from `BrokerRegistry`
3. Reads legacy keys via `SecureStorage::retrieve`
4. Creates new `BrokerAccount` instances with UUID-based IDs
5. Re-saves credentials using `save_credentials()` under scoped keys
6. Updates the migration flag

This runs once per installation and is safe to execute on every startup.

## Extending Linux Storage with libsecret

To replace the XOR fallback with proper Linux encryption:

1. Create [`SecureStorageLibsecret.cpp`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/SecureStorageLibsecret.cpp) implementing the storage interface using `libsecret` APIs
2. Guard with `#elif defined(Q_OS_LINUX)` in [`SecureStorage.cpp`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/SecureStorage.cpp)
3. Replace the XOR block (lines 109-117) with calls to your new wrapper
4. Update [`CMakeLists.txt`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/CMakeLists.txt) in `fincept-qt/src/storage/secure` to link against `libsecret-1`

Maintain the **Result<T>** return pattern to preserve error-handling contracts with `AccountManager`.

## Summary

- **SecureStorage** abstracts OS-native encryption via `store()`, `retrieve()`, and `remove()` in [`fincept-qt/src/storage/secure/SecureStorage.cpp`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/fincept-qt/src/storage/secure/SecureStorage.cpp)
- **AccountManager** provides per-account isolation using scoped keys like `account.<id>.api_key`
- Windows and macOS use DPAPI and Keychain respectively; Linux currently uses XOR obfuscation requiring replacement
- Legacy credentials automatically migrate to the new scoped format via `migrate_legacy_credentials()`
- Always use the `Result<T>` pattern for error handling rather than exceptions

## Frequently Asked Questions

### How does Fincept Terminal encrypt stored API keys?

On Windows, Fincept Terminal uses the Data Protection API (DPAPI) through the Credential Manager. macOS leverages the Keychain Services framework. Linux currently applies XOR obfuscation as a placeholder, with the source code in [`SecureStorage.cpp`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/SecureStorage.cpp) marked for replacement with libsecret integration. No custom encryption algorithms are implemented.

### Where are credentials physically stored on each operating system?

Windows stores secrets in the Credential Manager vault under generic credentials. macOS writes to the user Keychain as generic passwords. Linux persists Base64-encoded XOR data in `QSettings` files typically located in `~/.config/Fincept/` until the planned libsecret backend relocates them to the Secret Service.

### Is the Linux XOR implementation secure for production use?

No. The XOR obfuscation in [`SecureStorage.cpp`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/SecureStorage.cpp) (lines 109-117) provides only casual obfuscation against file inspection. It lacks cryptographic security and should be replaced with a libsecret or D-Bus Secret Service implementation before deploying in production environments.

### How do I add a new broker with custom credential fields?

Define the credential schema in your broker implementation of `IBroker` from [`fincept-qt/src/trading/BrokerInterface.h`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/fincept-qt/src/trading/BrokerInterface.h), specify the required fields in `credential_fields`, then collect values through `AccountManagementDialog` in [`fincept-qt/src/screens/equity_trading/AccountManagementDialog.cpp`](https://github.com/Fincept-Corporation/FinceptTerminal/blob/main/fincept-qt/src/screens/equity_trading/AccountManagementDialog.cpp). Pass the populated `BrokerCredentials` struct to `AccountManager::save_credentials()` with a unique account ID to trigger automatic secure storage.