Implementation Summary: Persistent Storage & Secret Resolver

Overview

Successfully implemented persistent message storage and SecretResolver for DIDComm V2 plugin to address production requirements.

Components Implemented

✅ 1. Persistent Message Storage

Storage Interface

  • File: credentials/plugins/didcomm/src/main/kotlin/org.trustweave/credential/didcomm/storage/DidCommMessageStorage.kt
  • Features:
    • Store and retrieve messages
    • Query by DID, thread, filters
    • Pagination support
    • Message deletion
    • Search with filters

In-Memory Storage

  • File: credentials/plugins/didcomm/src/main/kotlin/org.trustweave/credential/didcomm/storage/InMemoryDidCommMessageStorage.kt
  • Use Case: Testing and development
  • Status: ✅ Complete

PostgreSQL Storage

  • File: credentials/plugins/didcomm/src/main/kotlin/org.trustweave/credential/didcomm/storage/database/PostgresDidCommMessageStorage.kt
  • Use Case: Production deployments
  • Features:
    • Full SQL support with JSONB storage
    • Indexed queries for performance
    • Transaction support
    • Automatic table creation
  • Status: ✅ Complete

Database Service

  • File: credentials/plugins/didcomm/src/main/kotlin/org.trustweave/credential/didcomm/DatabaseDidCommService.kt
  • Purpose: Database-backed service implementation
  • Status: ✅ Complete

Database Schema

  • File: credentials/plugins/didcomm/src/main/resources/db/migration/V1__create_didcomm_messages.sql
  • Tables:
    • didcomm_messages - Main messages table
    • didcomm_message_dids - Index for DID lookups
    • didcomm_message_threads - Index for thread lookups
  • Status: ✅ Complete

✅ 2. Secret Resolver

Local Key Store

  • File: credentials/plugins/didcomm/src/main/kotlin/org.trustweave/credential/didcomm/crypto/secret/LocalKeyStore.kt
  • Purpose: Store DIDComm keys locally (for ECDH operations)
  • Implementations:
    • InMemoryLocalKeyStore - For testing ✅
    • EncryptedFileLocalKeyStore - For production (interface ready, implementation pending)
  • Status: ✅ Interface and in-memory implementation complete

KMS Secret Resolver

  • File: credentials/plugins/didcomm/src/main/kotlin/org.trustweave/credential/didcomm/crypto/secret/KmsSecretResolver.kt
  • Purpose: Bridge KMS with didcomm-java library
  • Strategy: Uses local key store for DIDComm keys
  • Status: ✅ Complete

Hybrid Secret Resolver

  • File: credentials/plugins/didcomm/src/main/kotlin/org.trustweave/credential/didcomm/crypto/secret/HybridKmsSecretResolver.kt
  • Purpose: Recommended approach for production
  • Strategy:
    • DIDComm keys stored locally (for ECDH)
    • Other keys use cloud KMS (for signing)
  • Status: ✅ Complete

Updated Production Crypto

  • File: credentials/plugins/didcomm/src/main/kotlin/org.trustweave/credential/didcomm/crypto/DidCommCryptoProduction.kt
  • Changes:
    • Added SecretResolver parameter
    • Uses custom resolver if provided
    • Falls back to default if not provided
  • Status: ✅ Complete

Updated Crypto Adapter

  • File: credentials/plugins/didcomm/src/main/kotlin/org.trustweave/credential/didcomm/crypto/DidCommCryptoAdapter.kt
  • Changes:
    • Added SecretResolver parameter
    • Passes resolver to production crypto
  • Status: ✅ Complete

✅ 3. Factory Updates

New Factory Methods

  • File: credentials/plugins/didcomm/src/main/kotlin/org.trustweave/credential/didcomm/DidCommFactory.kt
  • New Methods:
    • createDatabaseService() - Creates database-backed service
    • createInMemoryServiceWithSecretResolver() - Creates service with custom resolver
  • Status: ✅ Complete

✅ 4. Service Updates

In-Memory Service

  • File: credentials/plugins/didcomm/src/main/kotlin/org.trustweave/credential/didcomm/DidCommService.kt
  • Changes:
    • Updated to use storage interface
    • Accepts optional storage parameter
  • Status: ✅ Complete

Usage Examples

Database-Backed Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import com.zaxxer.hikari.HikariDataSource
import org.trustweave.credential.didcomm.*
import org.trustweave.credential.didcomm.storage.database.PostgresDidCommMessageStorage

// Create data source
val dataSource = HikariDataSource().apply {
    jdbcUrl = "jdbc:postgresql://localhost:5432/trustweave"
    username = "user"
    password = "pass"
}

// Create storage
val storage = PostgresDidCommMessageStorage(dataSource)

// Create packer
val packer = DidCommFactory.createPacker(kms, resolveDid)

// Create database-backed service
val didCommService = DidCommFactory.createDatabaseService(
    packer = packer,
    resolveDid = resolveDid,
    storage = storage
)

Hybrid Secret Resolver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.trustweave.credential.didcomm.crypto.secret.*

// Create local key store for DIDComm keys
val localKeyStore = InMemoryLocalKeyStore() // Or EncryptedFileLocalKeyStore

// Create hybrid resolver
val secretResolver = HybridKmsSecretResolver(
    localKeyStore = localKeyStore,
    cloudKms = cloudKms // Optional
)

// Create service with custom resolver
val didCommService = DidCommFactory.createInMemoryServiceWithSecretResolver(
    kms = kms,
    resolveDid = resolveDid,
    secretResolver = secretResolver
)

Architecture

Storage Architecture

1
2
3
4
5
6
7
8
9
10
11
DidCommService (interface)
    │
    ├── InMemoryDidCommService
    │   └── Uses InMemoryDidCommMessageStorage (or custom storage)
    │
    └── DatabaseDidCommService
        └── Uses PostgresDidCommMessageStorage
                │
                └── DidCommMessageStorage (interface)
                        ├── InMemoryDidCommMessageStorage
                        └── PostgresDidCommMessageStorage

Secret Resolver Architecture

1
2
3
4
5
6
7
8
9
10
11
DidCommCryptoProduction
    │
    └── SecretResolver (from didcomm-java)
            ├── SecretResolverInMemory (default)
            ├── KmsSecretResolver
            │   └── Uses LocalKeyStore
            └── HybridKmsSecretResolver (recommended)
                    │
                    └── LocalKeyStore
                            ├── InMemoryLocalKeyStore
                            └── EncryptedFileLocalKeyStore (to be implemented)

Database Schema

Tables

  1. didcomm_messages - Main messages table
    • Stores full message JSON in JSONB format
    • Indexed by type, created_time, from_did, thid
  2. didcomm_message_dids - DID index table
    • Maps message IDs to DIDs (from/to)
    • Enables efficient DID-based queries
  3. didcomm_message_threads - Thread index table
    • Maps message IDs to thread IDs
    • Enables efficient thread-based queries

Indexes

  • idx_messages_from_did - Fast lookup by sender DID
  • idx_messages_thid - Fast lookup by thread ID
  • idx_messages_created - Fast time-based queries
  • idx_messages_type - Fast lookup by message type
  • idx_message_dids_did - Fast DID-based queries
  • idx_message_threads_thid - Fast thread-based queries

Security Considerations

Message Storage

  • ✅ Messages stored in database with JSONB
  • ⚠️ Consider encryption at rest for sensitive data
  • ⚠️ Implement row-level security for multi-tenant scenarios
  • ⚠️ Implement message expiration and cleanup

Secret Resolver

  • ✅ Local keys stored separately from cloud KMS
  • ⚠️ Local keys must be encrypted at rest (EncryptedFileLocalKeyStore to be implemented)
  • ⚠️ Implement key rotation policies
  • ⚠️ Limit access to key storage
  • ⚠️ Audit logging for key access

Performance Considerations

Database Storage

  • ✅ Connection pooling ready (use HikariCP)
  • ✅ Proper indexes for common queries
  • ✅ Pagination support
  • ⚠️ Consider caching for frequently accessed messages

Secret Resolver

  • ✅ Key caching implemented
  • ✅ Lazy loading of keys
  • ⚠️ Consider key preloading for known DIDs

Testing

Unit Tests

  • ⚠️ Add tests for storage interface
  • ⚠️ Add tests for SecretResolver implementations
  • ⚠️ Add tests for database storage

Integration Tests

  • ⚠️ Add tests with real database
  • ⚠️ Add tests with real KMS
  • ⚠️ Add performance tests

Future Enhancements

See Advanced Features Implementation Plan for detailed implementation plans for:

  1. EncryptedFileLocalKeyStore - Encrypted file-based key storage
  2. MongoDB Storage - Alternative database backend
  3. Message Archiving - Archive old messages to cold storage
  4. Message Replication - High availability support
  5. Message Encryption at Rest - Encrypt message JSON in database
  6. Advanced Search - Full-text search capabilities
  7. Message Analytics - Reporting and analytics
  8. Key Rotation Automation - Automated key rotation

Migration Path

From In-Memory to Database

  1. ✅ Storage interface created
  2. ✅ Database storage implementation created
  3. ✅ Service factory updated
  4. ⚠️ Migrate existing messages (if any)
  5. ⚠️ Update configuration

From Placeholder to Production Crypto

  1. ✅ didcomm-java dependency added
  2. ✅ SecretResolver implemented
  3. ✅ Crypto adapter updated
  4. ⚠️ Test with real keys
  5. ⚠️ Deploy to production

Status Summary

Component Status Notes
Storage Interface ✅ Complete Ready for use
In-Memory Storage ✅ Complete Testing ready
PostgreSQL Storage ✅ Complete Production ready
Database Service ✅ Complete Production ready
Database Schema ✅ Complete Migration script ready
Local Key Store ✅ Complete Interface + in-memory
KMS Secret Resolver ✅ Complete Ready for use
Hybrid Secret Resolver ✅ Complete Recommended for production
Production Crypto Update ✅ Complete Uses SecretResolver
Factory Updates ✅ Complete New methods added

Next Steps

  1. ✅ All core components implemented
  2. ⚠️ Add unit tests
  3. ⚠️ Add integration tests
  4. ⚠️ Implement EncryptedFileLocalKeyStore
  5. ⚠️ Add monitoring and metrics
  6. ⚠️ Performance testing
  7. ⚠️ Security audit

This site uses Just the Docs, a documentation theme for Jekyll.