280 lines
9.3 KiB
Markdown
280 lines
9.3 KiB
Markdown
# Security Practices — Kordant Android
|
|
|
|
> **Last updated:** 2026-06-01
|
|
> **Package:** `com.kordant.android`
|
|
> **Purpose:** Document security practices for Play Store Data Safety form and user transparency
|
|
|
|
---
|
|
|
|
## 1. Encryption in Transit
|
|
|
|
### TLS Configuration
|
|
|
|
All network communication between the Kordant Android app and backend servers is encrypted using **TLS 1.2 or higher**.
|
|
|
|
**Implementation:**
|
|
- `network_security_config.xml` enforces `cleartextTrafficPermitted="false"` for all domains
|
|
- Debug builds allow cleartext for local development via `<debug-overrides>`
|
|
- API base URL uses HTTPS (`https://api.kordant.com`)
|
|
|
|
### Certificate Pinning
|
|
|
|
The Android app implements **SHA-256 certificate pinning** for production and staging domains:
|
|
|
|
| Domain | Pin 1 (Primary) | Pin 2 (Backup) |
|
|
|--------|----------------|----------------|
|
|
| `api.kordant.com` | Primary SHA-256 hash | Backup SHA-256 hash |
|
|
| `staging.api.kordant.com` | Staging SHA-256 hash | Staging backup SHA-256 hash |
|
|
|
|
**File:** `res/xml/network_security_config.xml`
|
|
|
|
**Rotation:** Pins include a backup for graceful certificate rotation. Update pins before certificate expiry. Expiration set to 2027-06-01.
|
|
|
|
### TLS Enforcement Points
|
|
|
|
| Component | Enforcement |
|
|
|-----------|------------|
|
|
| OkHttpClient | HTTPS URLs only (BuildConfig.API_BASE_URL) |
|
|
| AUTH interceptor | All auth requests via HTTPS |
|
|
| API service | Retrofit base URL uses HTTPS |
|
|
| Image loading | Coil via OkHttp with TLS |
|
|
|
|
---
|
|
|
|
## 2. Encryption at Rest
|
|
|
|
### EncryptedSharedPreferences
|
|
|
|
All sensitive data is stored in **EncryptedSharedPreferences** using:
|
|
|
|
| Property | Value |
|
|
|----------|-------|
|
|
| **Key encryption** | AES256-SIV (deterministic, allows key lookup) |
|
|
| **Value encryption** | AES256-GCM (authenticated encryption) |
|
|
| **Master key** | Android Keystore (`MasterKey.Builder` with `KeyScheme.AES256_GCM`) |
|
|
| **Library** | `androidx.security:security-crypto` |
|
|
|
|
### Data Stored Encrypted
|
|
|
|
| Data | Key | File |
|
|
|------|-----|------|
|
|
| Access token | `access_token` | `SecureStorageManager.kt` |
|
|
| Refresh token | `refresh_token` | `SecureStorageManager.kt` |
|
|
| User profile (PII) | `user_profile_json` | `SecureStorageManager.kt` |
|
|
| FCM device token | `fcm_device_token` | `SecureStorageManager.kt` |
|
|
| Biometric preference | `biometric_enabled` | `SecureStorageManager.kt` |
|
|
|
|
### Non-Sensitive Data (Unencrypted)
|
|
|
|
User preferences that do not contain PII are stored in Android's standard **Preferences DataStore**:
|
|
|
|
- Theme selection (system/light/dark)
|
|
- Language/locale
|
|
- Notification preferences (alerts/marketing/system toggles)
|
|
- Onboarding completion status
|
|
- App version for migration tracking
|
|
- Background sync toggle
|
|
- Last sync timestamp
|
|
|
|
### Spam Database (Hashed)
|
|
|
|
Phone numbers in the local SQLite spam database are **SHA-256 hashed** before storage.
|
|
|
|
| Field | Storage |
|
|
|-------|---------|
|
|
| `number_hash` | SHA-256 hash of normalized phone number |
|
|
| `pattern` | Wildcard pattern (e.g., `+1-800-*`) |
|
|
| `action` | `block`, `flag`, `allow` |
|
|
| `category` | `scam`, `telemarketer`, `robocall`, `spam` |
|
|
| `spam_score` | 0-100 confidence score |
|
|
|
|
Raw phone numbers are **never written to disk** in the spam database.
|
|
|
|
---
|
|
|
|
## 3. Secure Deletion
|
|
|
|
### Overwrite-Then-Remove
|
|
|
|
The app implements **secure deletion** for sensitive keys to mitigate forensic recovery:
|
|
|
|
```
|
|
secureOverwriteAndRemove(key) {
|
|
for (i in 0 until 3) {
|
|
overwrite with random data → apply()
|
|
}
|
|
remove(key) → apply()
|
|
}
|
|
```
|
|
|
|
### Deletion Methods
|
|
|
|
| Method | What It Clears | Use Case |
|
|
|--------|---------------|----------|
|
|
| `clearAllAuthData()` | Access token, refresh token, user profile | Logout |
|
|
| `clearAllData()` | All encrypted preferences including biometric | Account deletion (GDPR) |
|
|
| `clearAll()` (DataStore) | All user preferences | Reset to defaults |
|
|
| `clearAll()` (CacheManager) | API response cache | Logout / cache clear |
|
|
| `clearAll()` (SpamDatabase) | Spam numbers + call logs | Full resync / account deletion |
|
|
|
|
---
|
|
|
|
## 4. Root Detection & Anti-Tampering
|
|
|
|
### Detection Methods
|
|
|
|
| Check | Detection Target |
|
|
|-------|-----------------|
|
|
| SU binary paths | `/system/bin/su`, `/system/xbin/su`, `/data/local/su`, etc. |
|
|
| Busybox paths | `/system/xbin/busybox`, `/data/local/bin/busybox` |
|
|
| Dangerous props | `ro.debuggable=1`, `ro.secure=0` |
|
|
| Build tags | `test-keys`, `dev-keys` |
|
|
| Magisk indicators | `/sbin/.magisk`, `/data/adb/magisk`, Magisk packages |
|
|
| Root management packages | Magisk, SuperSU, KingRoot, LuckyPatcher, etc. |
|
|
| SU command execution | `su -c id` — checks if uid=0 |
|
|
| App signature verification | SHA-256 hash of signing certificate |
|
|
| Debugger detection | `android.os.Debug.isDebuggerConnected()` |
|
|
| ADB over network | `service.adb.tcp.port` system property |
|
|
| Emulator detection | Known properties, model, manufacturer, fingerprint |
|
|
| Installer source verification | Play Store, Amazon App Store, Samsung Galaxy Store |
|
|
|
|
### Response to Detection
|
|
|
|
| Detection | Behavior |
|
|
|-----------|----------|
|
|
| Root detected | Features degraded; reported to backend and Crashlytics |
|
|
| Tampering detected | Biometric and payment features disabled |
|
|
| Emulator detected | Features may be restricted |
|
|
| Untrusted install | Warning logged, security restrictions applied |
|
|
|
|
---
|
|
|
|
## 5. Log Sanitization
|
|
|
|
All network logs are sanitized before writing to prevent PII exposure:
|
|
|
|
| Pattern | Redacted To |
|
|
|---------|-------------|
|
|
| `Bearer <token>` | `Bearer [REDACTED]` |
|
|
| `\b\d{10,15}\b` (phone numbers) | `[PHONE_REDACTED]` |
|
|
| Email addresses | `[EMAIL_REDACTED]` |
|
|
| Refresh tokens in bodies | `"refreshToken":"[REDACTED]"` |
|
|
| Access tokens in bodies | `"accessToken":"[REDACTED]"` |
|
|
| ID tokens in bodies | `"idToken":"[REDACTED]"` |
|
|
| Passwords in bodies | `"password":"[REDACTED]"` |
|
|
|
|
**Implementation:** `NetworkModule.kt` → `provideLoggingInterceptor()`
|
|
|
|
**Log levels:**
|
|
- **Debug builds:** Full headers + sanitized bodies
|
|
- **Release builds:** Headers only (no body logging)
|
|
|
|
---
|
|
|
|
## 6. Token Refresh Security
|
|
|
|
### Automatic Silent Refresh
|
|
|
|
| Property | Value |
|
|
|----------|-------|
|
|
| **Trigger** | HTTP 401 Unauthorized |
|
|
| **Mechanism** | `AuthInterceptor.intercept()` → `refreshAccessToken()` |
|
|
| **Concurrency** | Synchronized via `refreshLock` to prevent race conditions |
|
|
| **Fallback** | Clears tokens on refresh failure → user re-authenticates |
|
|
|
|
### Token Storage
|
|
|
|
| Token | Storage | Encryption |
|
|
|-------|---------|------------|
|
|
| Access token | EncryptedSharedPreferences | AES256-GCM |
|
|
| Refresh token | EncryptedSharedPreferences | AES256-GCM |
|
|
|
|
---
|
|
|
|
## 7. Network Security
|
|
|
|
### OkHttp Configuration
|
|
|
|
| Property | Value |
|
|
|----------|-------|
|
|
| Connect timeout | 30 seconds |
|
|
| Read timeout | 30 seconds |
|
|
| Write timeout | 30 seconds |
|
|
| TLS enforcement | Platform default (TLS 1.2+) |
|
|
| Certificate pinning | SHA-256 pins for api.kordant.com |
|
|
|
|
### Retrofit API Configuration
|
|
|
|
| Property | Value |
|
|
|----------|-------|
|
|
| Base URL | `https://api.kordant.com/` (production) |
|
|
| Converter | Kotlinx Serialization JSON |
|
|
| Headers | `X-Request-ID`, `X-Client-Version`, `X-Client-Platform` |
|
|
|
|
---
|
|
|
|
## 8. Biometric Authentication
|
|
|
|
| Property | Value |
|
|
|----------|-------|
|
|
| **Library** | `androidx.biometric:biometric` |
|
|
| **Storage** | Preference flag in EncryptedSharedPreferences |
|
|
| **Root check** | Biometric disabled on rooted/tampered devices |
|
|
| **Fallback** | Device credentials (PIN/pattern/password) |
|
|
|
|
---
|
|
|
|
## 9. Data Collection Compliance
|
|
|
|
### Data Minimization
|
|
|
|
The app collects only the data necessary for its core functionality:
|
|
|
|
| Feature | Minimum Data Required |
|
|
|---------|----------------------|
|
|
| Authentication | Email, password (or Google account ID), name |
|
|
| Call Screening | Incoming phone number (temporary, hashed for storage) |
|
|
| VoicePrint | Voice recording samples |
|
|
| DarkWatch | Watchlist items (email, phone, name to monitor) |
|
|
| Analytics | Device info, app version (no personal identifiers) |
|
|
| Crash reporting | Crash stack trace, device model, OS version |
|
|
|
|
### User Consent
|
|
|
|
| Data Type | Consent Mechanism |
|
|
|-----------|------------------|
|
|
| Account creation | Explicit signup form |
|
|
| Google Sign-In | OAuth consent screen |
|
|
| Voice recordings | `RECORD_AUDIO` permission + in-app rationale |
|
|
| Call screening | `READ_PHONE_STATE` permission + in-app rationale |
|
|
| Notifications | `POST_NOTIFICATIONS` (Android 13+) + in-app toggles |
|
|
| Crash reporting | Crashlytics opt-out (configured in manifest) |
|
|
| Marketing communications | Explicit opt-in via notification settings |
|
|
|
|
---
|
|
|
|
## 10. Independent Security Review
|
|
|
|
**Status:** ⚠️ Pending
|
|
|
|
An independent third-party security audit is planned before the production launch.
|
|
The audit will cover:
|
|
- Penetration testing of the mobile application
|
|
- API security assessment
|
|
- Cryptographic implementation review
|
|
- Privacy compliance review
|
|
|
|
---
|
|
|
|
## 11. Compliance Standards
|
|
|
|
| Standard | Status | Notes |
|
|
|----------|--------|-------|
|
|
| **GDPR** | ✅ Compliant | Data deletion, portability, consent, breach notification |
|
|
| **CCPA** | ✅ Compliant | Right to know, delete, opt-out, non-discrimination |
|
|
| **COPPA** | ✅ Compliant | No children under 13 data collection |
|
|
| **Play Store Data Safety** | ✅ Complete | All data types accurately declared |
|
|
| **Android Target API 36** | ✅ Compliant | No deprecated API usage |
|
|
| **TLS 1.2/1.3** | ✅ Enforced | Cleartext traffic blocked |
|
|
| **OWASP MASVS** | ⚠️ Partial | Security audit planned for full certification |
|