The key generation functionality has been consolidated from WalletsService and WalletCreationOrchestrator into the centralized KeyManagementService. This consolidation provides:
- Single Source of Truth: All key generation goes through one service
- Consistent Security: Uniform key generation, encryption, and audit logging
- Easier Maintenance: Updates to key generation logic only need to happen in one place
- Better Audit Trail: Centralized tracking of all key operations
- Provider Abstraction: Easy to swap key providers (HSM, KMS, etc.)
WalletsService
└─ generateStellarKeyPair() ❌ Duplicated logic
└─ Uses crypto directly
WalletCreationOrchestrator
└─ generateStellarKeyPair() ❌ Duplicated logic
└─ Uses crypto directly
WalletsService
└─ Uses KeyManagementService.generateKey() ✅
WalletCreationOrchestrator
└─ Uses KeyManagementService.generateKey() ✅
KeyManagementService (Single Source)
├─ generateKey()
├─ sign()
├─ validateKey()
└─ Audit logging
└─ Provider abstraction (StellarKeyProvider, etc.)
Before:
private generateStellarKeyPair(): { publicKey: string; privateKey: string } {
const keyPair = crypto.generateKeyPairSync('ed25519');
return {
publicKey: keyPair.publicKey.export({ type: 'spki', format: 'der' }).toString('hex'),
privateKey: keyPair.privateKey.export({ type: 'pkcs8', format: 'der' }).toString('hex'),
};
}After:
// Constructor now injects KeyManagementService
constructor(
private encryptionService: EncryptionService,
private configService: ConfigService,
private keyManagementService: KeyManagementService, // ✅ New dependency
) {}
// Key generation now uses centralized service
const encryptedKeyMaterial = await this.keyManagementService.generateKey({
keyType: KeyType.STELLAR_ED25519,
metadata: { userId, network },
});Before:
private generateStellarKeyPair(): { publicKey: string; privateKey: string } {
const privateKey = crypto.randomBytes(32).toString('hex');
const publicKey = `G${crypto.randomBytes(32).toString('hex').toUpperCase()}`;
return { publicKey, privateKey };
}After:
// Constructor now injects KeyManagementService
constructor(
private encryptionService: EncryptionService,
private configService: ConfigService,
private idempotentUserService: IdempotentUserService,
private keyManagementService: KeyManagementService, // ✅ New dependency
) {}
// Key generation now uses centralized service
const encryptedKeyMaterial = await this.keyManagementService.generateKey({
keyType: KeyType.STELLAR_ED25519,
metadata: { userId: request.userId, network: request.network },
});WalletsModule now imports KeyManagementModule:
@Module({
imports: [
EncryptionModule,
ApiKeyModule,
RateLimitModule,
KeyManagementModule, // ✅ New import
],
controllers: [WalletsController],
providers: [WalletsService, WalletCreationOrchestrator, EncryptionService],
exports: [WalletsService, WalletCreationOrchestrator],
})
export class WalletsModule {}All wallets now use the same key generation logic through StellarKeyProvider:
- Proper Ed25519 key generation using
stellar-sdk - Consistent key format and encoding
- Immediate encryption of private keys
Every key generation is automatically logged:
{
operation: 'GENERATE',
keyId: 'new',
publicKey: 'GABC...',
timestamp: Date,
success: true,
metadata: { userId: 'user-123', network: 'TESTNET' }
}Easy to swap key providers for different blockchains or security requirements:
// Stellar keys
keyManagementService.generateKey({ keyType: KeyType.STELLAR_ED25519 });
// Future: Ethereum keys
keyManagementService.generateKey({ keyType: KeyType.ETHEREUM_SECP256K1 });
// Future: HSM-backed keys
keyManagementService.generateKey({
keyType: KeyType.STELLAR_ED25519,
provider: 'HSM'
});All keys benefit from centralized security controls:
- Private keys are NEVER returned from KeyManagementService
- Private keys are NEVER logged
- All key operations are audited
- Keys are encrypted immediately after generation
- Graceful handling of invalid/disconnected states
When creating a new service that needs key generation:
import { KeyManagementService } from '../key-management/key-management.service';
import { KeyType } from '../key-management/domain/key-types';
@Injectable()
export class YourNewService {
constructor(
private keyManagementService: KeyManagementService,
) {}
async createNewKey() {
const encryptedKeyMaterial = await this.keyManagementService.generateKey({
keyType: KeyType.STELLAR_ED25519,
metadata: { /* your metadata */ },
});
// Use encryptedKeyMaterial.publicKey for storage
// Use encryptedKeyMaterial.encryptedData for encrypted private key storage
}
}If you have existing key generation code:
- Add
KeyManagementServiceto constructor dependencies - Replace direct
cryptocalls withkeyManagementService.generateKey() - Update module imports to include
KeyManagementModule - Update tests to mock
KeyManagementService
Services now mock KeyManagementService:
const mockKeyManagementService = {
generateKey: jest.fn().mockResolvedValue({
encryptedData: 'encrypted-secret',
encryptionVersion: 1,
keyType: KeyType.STELLAR_ED25519,
publicKey: 'GABC123...',
}),
};Integration tests verify the end-to-end flow:
- See
src/wallets/wallets-keygen-integration.spec.ts - Tests verify
KeyManagementService.generateKey()is called correctly - Tests verify audit logs are created
- Tests verify error handling
The provider pattern makes it easy to add HSM or KMS support:
// Example: AWS KMS provider
class AwsKmsKeyProvider implements IKeyProvider {
async generateKeyPair(keyType: KeyType): Promise<GeneratedKeyPair> {
// Call AWS KMS to generate key
}
}
// Register in KeyManagementService
this.providers.set(KeyType.STELLAR_ED25519_KMS, new AwsKmsKeyProvider());Add providers for other blockchains:
// Ethereum provider
class EthereumKeyProvider implements IKeyProvider {
async generateKeyPair(keyType: KeyType): Promise<GeneratedKeyPair> {
// Generate secp256k1 key for Ethereum
}
}
// Register
this.providers.set(KeyType.ETHEREUM_SECP256K1, new EthereumKeyProvider());Centralized key rotation across all wallets:
async rotateAllKeys(reason: string): Promise<RotationSummary> {
// Iterate through all wallets
// Generate new keys using KeyManagementService
// Update all wallet records atomically
}src/key-management/key-management.service.ts- Core servicesrc/key-management/providers/stellar-key.provider.ts- Stellar implementationsrc/key-management/interfaces/key-provider.interface.ts- Provider interfacesrc/wallets/wallets.service.ts- Example usagesrc/wallets/wallet-creation-orchestrator.service.ts- Example usagesrc/wallets/wallets-keygen-integration.spec.ts- Integration tests