feat(security): SPKI pinning rotation Firebase + Play Integrity/App Attest + freerasp 7.5.1
P0-NEW-21 — SPKI Pinning service avec rotation Firebase Remote Config - Remplace ancien check CN par digest SHA-256 SPKI - Liste pins dynamique depuis Firebase RC (clé 'spki_pins') - Multi-pin (leaf + backup + intermediate) - Câblé dans ApiClient._configureSslPinning() P0-NEW-22 — App Device Integrity (Play Integrity Android + App Attest iOS) - Token attestation court cache 60s - Bypass kDebugMode - Obligatoire audit BCEAO PI-SPI banking-grade pubspec.yaml : - freerasp 7.0.0 → 7.5.1 - +app_device_integrity 1.1.0 - +firebase_core 3.6.0 + firebase_remote_config 5.1.3
This commit is contained in:
@@ -8,6 +8,7 @@ import 'package:injectable/injectable.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import '../../app/app.dart';
|
||||
import '../config/environment.dart';
|
||||
import '../security/spki_pinning_service.dart';
|
||||
import '../di/injection.dart';
|
||||
import '../error/error_handler.dart';
|
||||
import '../utils/logger.dart';
|
||||
@@ -126,22 +127,20 @@ class ApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
/// Configure SSL pinning pour les connexions prod.
|
||||
/// Rejette tout certificat dont le subject/issuer ne correspond pas au CN attendu.
|
||||
/// TODO avant go-live : remplacer le check CN par une vérification de hash de clé publique (SPKI).
|
||||
/// Configure SSL pinning pour les connexions prod (P0-NEW-21, 2026-04-25).
|
||||
///
|
||||
/// Implémente un pinning par digest SHA-256 de SubjectPublicKeyInfo (SPKI), avec rotation
|
||||
/// dynamique via Firebase Remote Config. Conforme aux recommandations 2026 :
|
||||
/// - Plus de pinning de cert statique (rotation cert prod = brick app garanti)
|
||||
/// - SPKI digest survit aux rotations tant que la clé publique reste la même
|
||||
/// - Multi-pin (leaf + backup + intermediate) pour transitions sans downtime
|
||||
///
|
||||
/// Couplé à freeRASP + AppDeviceIntegrityService pour résister aux bypass Frida.
|
||||
void _configureSslPinning() {
|
||||
(_dio.httpClientAdapter as IOHttpClientAdapter).createHttpClient = () {
|
||||
final client = HttpClient();
|
||||
client.badCertificateCallback = (cert, host, port) {
|
||||
// Accepter uniquement si le host correspond à notre domaine prod
|
||||
const allowedHost = 'api.lions.dev';
|
||||
if (!host.endsWith(allowedHost)) {
|
||||
AppLogger.warning(
|
||||
'SSL pinning: hôte inattendu rejeté: $host',
|
||||
tag: 'ApiClient');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return SpkiPinningService.instance.verifyCertificate(cert, host);
|
||||
};
|
||||
return client;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user