Cryptography and Encryption Services Module.
The imtcrypt module provides comprehensive cryptographic services including symmetric and asymmetric encryption, hashing algorithms, and secure file persistence capabilities.
Overview
This module serves as the security foundation for ImtCore applications, providing:
- Symmetric encryption (AES-256)
- Asymmetric encryption (RSA)
- Hash generation (MD5, SHA)
- Encrypted file persistence
- Key management and provider infrastructure
- SSL/TLS certificate handling
Architecture
Design Patterns
Strategy Pattern:
- Multiple encryption algorithms (AES, RSA) behind common IEncryption interface
- Pluggable key providers through IEncryptionKeysProvider
- Algorithm selection at runtime via EncryptionAlgorithm enum
Adapter Pattern:
Provider Pattern:
- IEncryptionKeysProvider abstracts key storage and retrieval
- CStaticEncryptionKeyProviderComp for compile-time keys
- Supports runtime key injection and secure key storage
Core Interfaces
The module is organized around several key interface hierarchies:
Encryption Hierarchy:
├─ EncryptData() - Encrypt binary data with specified algorithm
├─ DecryptData() - Decrypt binary data with specified algorithm
└─ EncryptionAlgorithm enum: EA_RSA, EA_AES
│
└─ CEncryption (concrete implementation)
├─ CAesEncryption (AES-256 symmetric encryption)
└─ CRsaEncryption (RSA asymmetric encryption)
Key Management Hierarchy:
├─ GetPublicKey() - Retrieve public key for encryption
├─ GetPrivateKey() - Retrieve private key for decryption
└─ GetSymmetricKey() - Retrieve symmetric key for AES
│
├─ CStaticEncryptionKeyProviderComp (compile-time keys)
└─ Custom implementations for secure storage
Secure Persistence Hierarchy:
├─ Extends standard file persistence with encryption
├─ SaveToFile() - Encrypts before writing
└─ LoadFromFile() - Decrypts after reading
│
└─ Transparent encryption/decryption
Hashing Services:
├─ GenerateHash() - Generate hash from binary data
└─ Multiple algorithms (MD5, SHA-1, SHA-256)
│
└─ CMD5HashCalculator (MD5 implementation)
Supported Algorithms
Symmetric Encryption (AES)
CAesEncryption / CAesKey:**
- Algorithm: AES-256 in CBC mode
- Key size: 256 bits (32 bytes)
- Initialization Vector (IV): 128 bits (16 bytes)
- Padding: PKCS#7
Thread-safe: Yes
Usage:**
QByteArray keyData(32, 0);
CAesKey aesKey(keyData);
CAesEncryption aes;
QByteArray plaintext = "Sensitive data";
QByteArray ciphertext = aes.Encrypt(plaintext, aesKey);
QByteArray decrypted = aes.Decrypt(ciphertext, aesKey);
Q_ASSERT(decrypted == plaintext);
Asymmetric Encryption (RSA)
CRsaEncryption / CRsaKey:**
Hash Functions
CMD5HashCalculator:**
Encrypted File Persistence
Basic Usage
CEncryptionBasedPersistenceComp** provides transparent encryption for file operations, adapting any IFilePersistence-compatible object:
auto encryption = CEncryption::CreateInstance();
auto keyProvider = CStaticEncryptionKeyProviderComp::CreateInstance();
auto encryptedPersistence = CEncryptionBasedPersistenceComp::CreateInstance();
encryptedPersistence->SetEncryption(encryption.get());
encryptedPersistence->SetKeysProvider(keyProvider.get());
encryptedPersistence->SetAlgorithm(IEncryption::EA_AES);
MyDataObject dataObj;
encryptedPersistence->SaveToFile(&dataObj, "encrypted_data.bin");
MyDataObject loaded;
encryptedPersistence->LoadFromFile(&loaded, "encrypted_data.bin");
Integration Patterns
Pattern 1: Wrapper around existing persistence:**
auto jsonPersistence = CJsonPersistenceComp::CreateInstance();
auto encrypted = CEncryptionBasedPersistenceComp::CreateInstance();
encrypted->SetInnerPersistence(jsonPersistence.get());
encrypted->SetEncryption(myEncryption);
encrypted->SetKeysProvider(myKeyProvider);
Pattern 2: Component-based dependency injection:**
class CSecureDataManagerComp : public ACF_COMPONENT(IDataManager)
{
void InitializeComponent() override
{
m_persistence->SetEncryption(m_encryption);
m_persistence->SetKeysProvider(m_keyProvider);
}
};
Key Management
Static Keys
CStaticEncryptionKeyProviderComp** - For development or embedded scenarios:
auto keyProvider = CStaticEncryptionKeyProviderComp::CreateInstance();
QByteArray aesKey(32, 0);
keyProvider->SetSymmetricKey(aesKey);
QFile pubFile("public.pem");
pubFile.open(QIODevice::ReadOnly);
keyProvider->SetPublicKey(pubFile.readAll());
QFile privFile("private.pem");
privFile.open(QIODevice::ReadOnly);
keyProvider->SetPrivateKey(privFile.readAll());
Secure Key Storage
For production systems, implement custom IEncryptionKeysProvider:
class CSecureKeyProviderComp : public ACF_COMPONENT(IEncryptionKeysProvider)
{
public:
QByteArray GetSymmetricKey() const override
{
return LoadFromSecureStorage();
}
QByteArray GetPublicKey() const override
{
return LoadCertificate();
}
};
Security Considerations
Best Practices
Key Generation:**
- Use QRandomGenerator::system()->generate() for cryptographic keys
- Never hardcode keys in source code (use secure storage)
Minimum key sizes: AES-256 (32 bytes), RSA-2048 (2048 bits)
Key Storage:**
- Use platform-specific secure storage (Keychain, DPAPI, Keyring)
- Never store keys in plain text files
Consider hardware security modules (HSM) for critical applications
Algorithm Selection:**
- AES-256 for symmetric encryption (file contents, data at rest)
- RSA-2048+ for asymmetric encryption (key exchange, signatures)
SHA-256+ for hashing (never MD5 for security-critical operations)
Implementation Guidelines:**
- Always use authenticated encryption (consider AES-GCM instead of CBC)
- Generate new IV for each encryption operation
- Use constant-time comparison for authentication tags
- Clear sensitive data from memory after use
Known Limitations
- MD5 is provided for legacy compatibility only (NOT cryptographically secure)
- CBC mode without authentication is vulnerable to padding oracle attacks
- RSA PKCS#1 v1.5 padding has known weaknesses (consider OAEP)
- No built-in password-based key derivation (use PBKDF2/Argon2 externally)
Integration with Other Modules
With imtlic (Licensing):
- Encrypt license keys and activation data
- Protect license files from tampering
- Secure hardware binding information
With imtauth (Authentication):
- Hash passwords before storage
- Encrypt authentication tokens
- Secure session data persistence
With imtdb (Database):
- Encrypt sensitive database fields
- Secure database connection credentials
- Protect backup files with encryption
With imtfile (File I/O):
Complete Examples
Encrypted License File
void SaveEncryptedLicense(const ILicenseInstance* license)
{
auto encryption = CEncryption::CreateInstance();
auto keyProvider = LoadProductKeyProvider();
auto encryptedPersistence = CEncryptionBasedPersistenceComp::CreateInstance();
encryptedPersistence->SetEncryption(encryption.get());
encryptedPersistence->SetKeysProvider(keyProvider.get());
encryptedPersistence->SetAlgorithm(IEncryption::EA_AES);
QString licenseFile = QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation) + "/license.dat";
encryptedPersistence->SaveToFile(license, licenseFile);
}
ILicenseInstanceUniquePtr LoadEncryptedLicense()
{
auto encryption = CEncryption::CreateInstance();
auto keyProvider = LoadProductKeyProvider();
auto encryptedPersistence = CEncryptionBasedPersistenceComp::CreateInstance();
encryptedPersistence->SetEncryption(encryption.get());
encryptedPersistence->SetKeysProvider(keyProvider.get());
encryptedPersistence->SetAlgorithm(IEncryption::EA_AES);
auto license = CLicenseInstance::CreateInstance();
encryptedPersistence->LoadFromFile(license.get(), licenseFile);
return license;
}
Encrypted Configuration
class CSecureSettingsComp : public ACF_COMPONENT(IAppSettings)
{
void SaveSettings() override
{
QJsonObject settings;
settings["apiKey"] = m_apiKey;
settings["databasePassword"] = m_dbPassword;
QJsonDocument doc(settings);
QByteArray jsonData = doc.toJson();
QByteArray encrypted;
m_encryption->EncryptData(
jsonData,
IEncryption::EA_AES,
*m_keyProvider,
encrypted);
QFile file(GetSettingsPath());
file.open(QIODevice::WriteOnly);
file.write(encrypted);
}
void LoadSettings() override
{
QFile file(GetSettingsPath());
file.open(QIODevice::ReadOnly);
QByteArray encrypted = file.readAll();
QByteArray decrypted;
m_encryption->DecryptData(
encrypted,
IEncryption::EA_AES,
*m_keyProvider,
decrypted);
QJsonDocument doc = QJsonDocument::fromJson(decrypted);
QJsonObject settings = doc.object();
m_apiKey = settings["apiKey"].toString();
m_dbPassword = settings["databasePassword"].toString();
}
};
Testing and Debugging
Test Vectors
Use known test vectors to verify encryption implementation:
void TestAesEncryption()
{
QByteArray key = QByteArray::fromHex(
"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
QByteArray plaintext = QByteArray::fromHex(
"6bc1bee22e409f96e93d7e117393172a");
QByteArray expectedCiphertext = QByteArray::fromHex(
"f58c4c04d6e5f1ba779eabfb5f7bfbd6");
CAesKey aesKey(key);
CAesEncryption aes;
QByteArray ciphertext = aes.Encrypt(plaintext, aesKey);
Q_ASSERT(ciphertext == expectedCiphertext);
}
Debugging Tips
- Log encryption operations in debug builds (but never log keys!)
- Use hex encoding (QByteArray::toHex()) to display binary data
- Verify key sizes before encryption operations
- Check IV generation (must be unique per encryption)
- Test round-trip: encrypt → decrypt → verify original data
References
Related Modules:
- imtlic - License management with encryption support
- imtauth - Authentication with password hashing
- imtfile - File I/O operations
- imtdb - Database with encrypted field support
Standards and Specifications:
- NIST FIPS 197 - AES Specification
- RFC 3447 - RSA Cryptography Specifications (PKCS #1)
- RFC 1321 - MD5 Message-Digest Algorithm
- NIST SP 800-38A - Block Cipher Modes of Operation
External Documentation: