[E5.S1] Database-Backed Secure Credential Manager Implementation #50

Closed
opened 2025-06-03 23:38:25 +00:00 by rwachters · 0 comments
rwachters commented 2025-06-03 23:38:25 +00:00 (Migrated from github.com)

Description

As a developer, I need to implement the core logic for securely storing and managing sensitive API keys by utilizing custom envelope encryption and storing the resulting encrypted data in a dedicated database table (api_secrets), so that user keys are protected locally without relying on OS-specific credential managers.

Acceptance Criteria

  • A backend CredentialManager interface is implemented by DbEncryptedCredentialManager.
  • The implementation uses custom envelope encryption via an EncryptionService and CryptoProvider (handling DEK/KEK), with KEK configuration managed by EncryptionConfig.
  • Persistence uses an ApiSecretDao to interact with a dedicated api_secrets database table (E7.S4).
  • The api_secrets table stores the encrypted API key (encrypted_credential), the wrapped Data Encryption Key (wrapped_dek), and the KEK version, uniquely identified by a generated UUID alias.
  • The DbEncryptedCredentialManager's storeCredential method encrypts the raw key, generates a UUID alias, and saves the encrypted data (with the alias) to the api_secrets table via ApiSecretDao, returning the alias.
  • The DbEncryptedCredentialManager's getCredential method retrieves the encrypted data by alias from api_secrets via ApiSecretDao, unwraps the DEK, decrypts the key, and returns the raw key string.
  • The DbEncryptedCredentialManager's deleteCredential method deletes the record matching the alias from the api_secrets table via ApiSecretDao.
  • The LLMModel database schema (E7.S4) includes an apiKeyId field (String, nullable) that stores the UUID alias referencing the api_secrets table record, not the raw key.
  • Backend services for model management (E4.S1, E4.S3) use the CredentialManager to store keys securely, saving the returned alias in the corresponding LLMModel record.
  • Raw API keys are only held in application memory temporarily when actively needed for storage, retrieval, or deletion.
  • (Cross-cutting Requirement E2.S2): All database operations on the api_secrets table are persisted.
  • (Cross-cutting Requirement E7.S6): Database interactions via ApiSecretDao and encryption/decryption operations are performed asynchronously using Coroutines.

Implementation Details

This story involves implementing a secure database-backed credential manager using envelope encryption:

  1. The CredentialManager interface will define the contract for credential operations:

    • suspend fun storeCredential(rawCredential: String): String - returns alias
    • suspend fun getCredential(alias: String): String? - returns decrypted credential
    • suspend fun deleteCredential(alias: String): Boolean
  2. The DbEncryptedCredentialManager implementation will:

    • Use a dedicated api_secrets table in the SQLite database
    • Implement envelope encryption with separate Data Encryption Keys (DEK) and Key Encryption Keys (KEK)
    • Generate UUID aliases to reference stored credentials
    • Work with an ApiSecretDao that handles data persistence
  3. The EncryptionService will:

    • Generate DEKs for each credential
    • Encrypt credentials using DEKs
    • Encrypt (wrap) DEKs using KEK
    • Decrypt (unwrap) DEKs using KEK
    • Decrypt credentials using unwrapped DEKs
  4. A CryptoProvider will:

    • Implement the actual cryptographic operations (generate keys, encrypt/decrypt)
    • Support KEK versioning for future key rotation

Dependencies

  • PR #42 (Initial Multi-Module Project Setup) must be completed first
  • PR #46 (Initialize SQLite Database & Exposed Schema) must include the api_secrets table

Parent Epic

Epic 5: API Key Management

  • E5.S2 - API Key Retrieval for LLM API Calls (will use this credential manager)

Technical Notes

  • Consider using standard cryptography libraries (e.g., Java's javax.crypto)
  • Avoid implementing custom cryptographic algorithms
  • Use strong encryption algorithms (e.g., AES-256 for DEK)
  • Consider KEK storage options (e.g., derived from application password or device-specific information)
  • All credential operations should be asynchronous
## Description As a developer, I need to implement the core logic for securely storing and managing sensitive API keys by utilizing **custom envelope encryption** and storing the resulting encrypted data in a **dedicated database table** (`api_secrets`), so that user keys are protected locally without relying on OS-specific credential managers. ## Acceptance Criteria - [ ] A backend `CredentialManager` interface is implemented by `DbEncryptedCredentialManager`. - [ ] The implementation uses **custom envelope encryption** via an `EncryptionService` and `CryptoProvider` (handling DEK/KEK), with KEK configuration managed by `EncryptionConfig`. - [ ] Persistence uses an `ApiSecretDao` to interact with a dedicated `api_secrets` database table (E7.S4). - [ ] The `api_secrets` table stores the encrypted API key (`encrypted_credential`), the wrapped Data Encryption Key (`wrapped_dek`), and the KEK version, uniquely identified by a generated UUID `alias`. - [ ] The `DbEncryptedCredentialManager`'s `storeCredential` method encrypts the raw key, generates a UUID `alias`, and saves the encrypted data (with the `alias`) to the `api_secrets` table via `ApiSecretDao`, returning the `alias`. - [ ] The `DbEncryptedCredentialManager`'s `getCredential` method retrieves the encrypted data by `alias` from `api_secrets` via `ApiSecretDao`, unwraps the DEK, decrypts the key, and returns the raw key string. - [ ] The `DbEncryptedCredentialManager`'s `deleteCredential` method deletes the record matching the `alias` from the `api_secrets` table via `ApiSecretDao`. - [ ] The `LLMModel` database schema (E7.S4) includes an `apiKeyId` field (String, nullable) that stores the UUID `alias` referencing the `api_secrets` table record, *not* the raw key. - [ ] Backend services for model management (E4.S1, E4.S3) use the `CredentialManager` to store keys securely, saving the returned `alias` in the corresponding `LLMModel` record. - [ ] Raw API keys are only held in application memory temporarily when actively needed for storage, retrieval, or deletion. - [ ] **(Cross-cutting Requirement E2.S2):** All database operations on the `api_secrets` table are persisted. - [ ] **(Cross-cutting Requirement E7.S6):** Database interactions via `ApiSecretDao` and encryption/decryption operations are performed asynchronously using Coroutines. ## Implementation Details This story involves implementing a secure database-backed credential manager using envelope encryption: 1. The `CredentialManager` interface will define the contract for credential operations: - `suspend fun storeCredential(rawCredential: String): String` - returns alias - `suspend fun getCredential(alias: String): String?` - returns decrypted credential - `suspend fun deleteCredential(alias: String): Boolean` 2. The `DbEncryptedCredentialManager` implementation will: - Use a dedicated `api_secrets` table in the SQLite database - Implement envelope encryption with separate Data Encryption Keys (DEK) and Key Encryption Keys (KEK) - Generate UUID aliases to reference stored credentials - Work with an `ApiSecretDao` that handles data persistence 3. The `EncryptionService` will: - Generate DEKs for each credential - Encrypt credentials using DEKs - Encrypt (wrap) DEKs using KEK - Decrypt (unwrap) DEKs using KEK - Decrypt credentials using unwrapped DEKs 4. A `CryptoProvider` will: - Implement the actual cryptographic operations (generate keys, encrypt/decrypt) - Support KEK versioning for future key rotation ## Dependencies - PR #42 (Initial Multi-Module Project Setup) must be completed first - PR #46 (Initialize SQLite Database & Exposed Schema) must include the `api_secrets` table ## Parent Epic Epic 5: API Key Management ## Related Stories - E5.S2 - API Key Retrieval for LLM API Calls (will use this credential manager) ## Technical Notes - Consider using standard cryptography libraries (e.g., Java's javax.crypto) - Avoid implementing custom cryptographic algorithms - Use strong encryption algorithms (e.g., AES-256 for DEK) - Consider KEK storage options (e.g., derived from application password or device-specific information) - All credential operations should be asynchronous
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Torvian.eu/chatbot#50
No description provided.