The M3 Security Module provides production-grade encryption, digital signatures, and secrets management for PhishGuard. This guide covers setup, usage, and best practices.
- Algorithm: AES-256-GCM (Authenticated Encryption)
- Key Derivation: scrypt (N=16384, r=8, p=1)
- Format:
salt(16 bytes) + nonce(12 bytes) + ciphertext+tag - Functions:
encrypt_data(data, passphrase)→ bytesdecrypt_data(blob, passphrase)→ dictsave_encrypted(data, filepath, passphrase)load_encrypted(filepath, passphrase)→ dictencrypt_to_base64(data, passphrase)→ strdecrypt_from_base64(b64_string, passphrase)→ dict
- Algorithm: HMAC-SHA256
- Output: Base64-encoded signatures
- Functions:
sign(record, secret)→ strverify(record, signature, secret)→ boolsign_analysis(analysis_json, secret)→ dict (with signature)verify_analysis(signed_analysis, secret)→ bool
- Interactive CLI for encrypting API keys and secrets
- Generates cryptographically secure signing secret (256-bit)
- Creates
secrets.encfile (binary encrypted format)
- Load encrypted secrets at runtime (hybrid mode)
- Verify digital signatures of analysis records
- No app restart required for secret loading
Ensure you have the cryptography library installed:
pip install cryptographyRun the interactive CLI tool:
python encrypt_secrets.pyYou will be prompted for:
- Master passphrase (create a strong one!)
- Gemini API Key
- MongoDB URI (optional)
- Twilio Account SID (optional)
- Twilio Auth Token (optional)
Output:
- Creates
secrets.enc(encrypted binary file) - Auto-generates a 256-bit signing secret
- Displays usage instructions
-
Run the Streamlit app:
streamlit run app.py
-
Navigate to the 🔐 Security tab
-
Click 🔓 Load Secrets
-
Enter your master passphrase
-
Secrets are now loaded in
st.session_state.secrets
from crypto_simple import load_encrypted
# Load secrets
secrets = load_encrypted('secrets.enc', passphrase)
# Access secrets
gemini_key = secrets['gemini_api_key']
mongo_uri = secrets.get('mongo_uri', '')
signing_secret = secrets['signing_secret']from crypto_simple import encrypt_data, decrypt_data
# Encrypt
data = {
'email_id': '12345',
'risk_score': 85,
'category': 'HIGH_RISK'
}
passphrase = 'my-strong-passphrase'
encrypted_blob = encrypt_data(data, passphrase)
# Decrypt
decrypted_data = decrypt_data(encrypted_blob, passphrase)
print(decrypted_data)from signing import sign_analysis, verify_analysis
# Sign an analysis record
analysis = {
'email_id': '12345',
'risk_score': 85,
'category': 'HIGH_RISK',
'timestamp': '2024-11-02T10:00:00Z'
}
signing_secret = bytes.fromhex('your-hex-secret')
signed_analysis = sign_analysis(analysis, signing_secret)
# signed_analysis now contains 'signature' field
print(signed_analysis['signature'])
# Verify signature
is_valid = verify_analysis(signed_analysis, signing_secret)
print(f"Valid: {is_valid}") # True- Go to 🔐 Security tab
- Load secrets (if not already loaded)
- Choose verification method:
- Paste JSON: Copy/paste signed analysis JSON
- Upload File: Upload a
.jsonfile
- Click 🔍 Verify Signature
- See result: ✅ Valid or ❌ Invalid
- ✅ Use 12+ characters
- ✅ Mix uppercase, lowercase, numbers, symbols
- ✅ Store in password manager
- ❌ Never hardcode in source code
- ❌ Never commit to version control
- ✅
secrets.encis in.gitignore(already configured) - ✅ Backup
secrets.encsecurely (encrypted cloud storage) - ✅ Use different secrets for dev/staging/production
- ❌ Never share
secrets.encvia email or chat - ❌ Never commit
secrets.encto git
- ✅ Auto-generated 256-bit secrets (cryptographically secure)
- ✅ Rotate periodically (every 90 days recommended)
- ✅ Store in encrypted
secrets.enc - ❌ Never use predictable secrets
- ❌ Never reuse across environments
When rotating secrets:
- Create new
secrets.encwith new passphrase - Update signing secret
- Re-sign all existing analysis records (if needed)
- Archive old
secrets.encsecurely - Update passphrase in password manager
from crypto_simple import encrypt_to_base64, decrypt_from_base64
# Encrypt to base64 string
data = {'key': 'value'}
b64_encrypted = encrypt_to_base64(data, passphrase)
# Send via API, store in database, etc.
print(b64_encrypted) # "aGVsbG8gd29ybGQ..."
# Decrypt from base64
decrypted = decrypt_from_base64(b64_encrypted, passphrase)from signing import sign_with_hex_secret, verify_with_hex_secret
# Use hex-encoded secret
hex_secret = 'a1b2c3d4e5f6...' # 64 hex chars = 256 bits
signature = sign_with_hex_secret(record, hex_secret)
is_valid = verify_with_hex_secret(record, signature, hex_secret)from crypto_simple import save_encrypted
import secrets
# Generate signing secret
signing_secret = secrets.token_hex(32) # 256 bits
# Create secrets dict
secrets_data = {
'gemini_api_key': 'your-api-key',
'signing_secret': signing_secret
}
# Encrypt and save
save_encrypted(secrets_data, 'secrets.enc', passphrase)from crypto_simple import encrypt_data, decrypt_data
test_data = {'test': 'data', 'number': 42}
passphrase = 'test-passphrase'
# Encrypt
encrypted = encrypt_data(test_data, passphrase)
print(f"Encrypted size: {len(encrypted)} bytes")
# Decrypt
decrypted = decrypt_data(encrypted, passphrase)
assert decrypted == test_data
print("✅ Encryption test passed")from signing import sign, verify
record = {'email_id': '123', 'score': 85}
secret = b'test-secret-key'
# Sign
signature = sign(record, secret)
print(f"Signature: {signature}")
# Verify
is_valid = verify(record, signature, secret)
assert is_valid
print("✅ Signing test passed")
# Test tampering detection
record['score'] = 90 # Modify data
is_valid = verify(record, signature, secret)
assert not is_valid
print("✅ Tampering detection test passed")- ✅ Check passphrase spelling/capitalization
- ✅ Ensure no extra spaces
- ✅ Verify you're using the correct
secrets.encfile
- ✅ Run
python encrypt_secrets.pyfirst - ✅ Check current working directory
- ✅ Ensure file wasn't accidentally deleted
- ✅ Verify signing secret matches
- ✅ Check if data was modified
- ✅ Ensure JSON format is correct
- ✅ Confirm signature field exists
- ✅ Install:
pip install cryptography - ✅ Activate virtual environment if using one
[16 bytes: salt]
[12 bytes: nonce]
[variable: encrypted JSON + 16-byte GCM tag]
{
"email_id": "12345",
"risk_score": 85,
"category": "HIGH_RISK",
"timestamp": "2024-11-02T10:00:00Z",
"signature": "base64-encoded-hmac-sha256-signature"
}Hybrid Mode allows loading secrets at runtime without restarting the app:
- Start app without secrets loaded
- Navigate to 🔐 Security tab
- Load secrets when needed
- Reload with different passphrase/file anytime
- No app restart required
Use Cases:
- Switch between dev/prod secrets
- Load secrets only when needed
- Test different configurations
- Multi-tenant scenarios
Encrypts a dictionary using AES-256-GCM.
Raises:
ValueError: If passphrase is emptyTypeError: If data cannot be serialized to JSON
Decrypts an encrypted blob back to dictionary.
Raises:
ValueError: If blob format is invalid or passphrase is wrong
Encrypts and saves data to a file.
Loads and decrypts data from a file.
Generates HMAC-SHA256 signature for a record.
Returns: Base64-encoded signature
Verifies HMAC-SHA256 signature for a record.
Returns: True if valid, False otherwise
Signs an analysis JSON and returns a copy with signature field.
Verifies a signed analysis record.
- Created strong master passphrase (12+ characters)
- Stored passphrase in password manager
- Created
secrets.encusingencrypt_secrets.py - Verified
secrets.encis in.gitignore - Backed up
secrets.encsecurely - Tested loading secrets in Streamlit
- Tested signature verification
- Set up key rotation schedule (90 days)
- Documented passphrase recovery process
- Configured different secrets for each environment
For issues or questions:
- Check this guide's troubleshooting section
- Review code comments in
crypto_simple.pyandsigning.py - Test with simple examples first
- Verify all dependencies are installed
This module uses industry-standard cryptographic algorithms:
- AES-256-GCM: NIST-approved authenticated encryption
- scrypt: Memory-hard key derivation function
- HMAC-SHA256: FIPS-approved message authentication
Security Audit Recommendation: For production use, consider a third-party security audit of cryptographic implementations.
Last Updated: November 2024
Version: M3.0
Module: PhishGuard Security