Skip to content

Commit 1e058c1

Browse files
authored
Merge pull request #72 from SliDeeN/security-key
Security : Verify signature
2 parents 5a82630 + da30841 commit 1e058c1

2 files changed

Lines changed: 34 additions & 24 deletions

File tree

‎app/src/main/java/com/mg4/control/update/ApkInstaller.kt‎

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,14 @@ object ApkInstaller {
3131
return "APK manquant ou vide : ${apkFile.absolutePath}"
3232
}
3333

34-
// [DÉSACTIVÉ 2026-08-05] Contrôle de signature (T-901) mis en pause : il refusait
35-
// TOUTE mise à jour OTA sur AAOS 9, y compris avec un APK signé de la même clé
36-
// plateforme en v1+v2+v3. Cause non encore élucidée (getPackageArchiveInfo ne
37-
// remonte probablement pas la signature de l'archive sur cette ROM).
38-
// Garde-fous restants : Android refuse une MAJ signée d'une autre clé, et
39-
// ApkUrlPolicy restreint toujours l'origine du téléchargement (github/gitlab, https).
40-
// Pour réactiver : décommenter le bloc ci-dessous.
41-
// if (!ApkSignatureVerifier.matchesRunningApp(context, apkFile)) {
42-
// apkFile.runCatching { delete() }
43-
// return "Signature non conforme — APK rejeté et supprimé"
44-
// }
34+
// [RÉACTIVÉ 2026-08-05] Contrôle de signature (T-901). Les échecs précédents ont eu
35+
// lieu avec une app installée signée à la main (v1 seul) face à un APK CI (v2/v3) :
36+
// on retente avec les DEUX côtés produits par la CI, donc signés à l'identique.
37+
// L'app tourne en uid.system : on n'installe que ce qui est signé par notre clé.
38+
if (!ApkSignatureVerifier.matchesRunningApp(context, apkFile)) {
39+
apkFile.runCatching { delete() }
40+
return "Signature non conforme — APK rejeté et supprimé"
41+
}
4542

4643
// ── Stratégie 1 : pm install depuis le stockage externe ───────────────
4744
val extDir = context.getExternalFilesDir(null)

‎app/src/main/java/com/mg4/control/update/UpdateDialogManager.kt‎

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,20 @@ object UpdateDialogManager {
172172
.substringBefore('?')
173173
.ifBlank { "MG4Control-${info.versionName}.apk" }
174174

175+
// DownloadManager n'écrase JAMAIS un fichier existant : si "…-2.6.5.apk" est déjà là
176+
// (téléchargement précédent de la même version), il écrit "…-2.6.5-1.apk". Or le code
177+
// relit ensuite le nom d'origine → il vérifierait/installerait l'ANCIEN fichier.
178+
// On supprime donc la cible avant d'enfiler la requête, pour garantir que le fichier
179+
// téléchargé, le fichier vérifié et le fichier installé soient bien le même.
180+
val target = File(
181+
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
182+
fileName
183+
)
184+
if (target.exists()) {
185+
val deleted = target.runCatching { delete() }.getOrDefault(false)
186+
Log.i(TAG, "Ancien APK homonyme trouvé (${target.name}) → suppression=$deleted")
187+
}
188+
175189
val request = DownloadManager.Request(Uri.parse(info.apkUrl)).apply {
176190
setTitle("MG4Control ${info.versionName}")
177191
setDescription(activity.getString(R.string.update_downloading))
@@ -210,19 +224,18 @@ object UpdateDialogManager {
210224
when (status) {
211225
DownloadManager.STATUS_SUCCESSFUL -> {
212226
progressBar.progress = 100
213-
// [DÉSACTIVÉ 2026-08-05] Contrôle de signature (T-901) mis en pause :
214-
// il refusait TOUTE mise à jour OTA sur AAOS 9, même avec un APK
215-
// signé de la même clé plateforme en v1+v2+v3. Voir ApkInstaller.
216-
// Pour réactiver : décommenter le bloc ci-dessous.
217-
// val downloaded = File(
218-
// Environment.getExternalStoragePublicDirectory(
219-
// Environment.DIRECTORY_DOWNLOADS), fileName)
220-
// if (!ApkSignatureVerifier.matchesRunningApp(activity, downloaded)) {
221-
// downloaded.runCatching { delete() }
222-
// tvStatus.setText(R.string.update_error_signature)
223-
// btnCancel.setText(R.string.update_close)
224-
// break
225-
// }
227+
// [RÉACTIVÉ 2026-08-05] Contrôle de signature (T-901) — voir ApkInstaller.
228+
// L'APK est dans un dossier public : on vérifie qu'il est signé
229+
// par NOTRE clé avant d'inviter l'utilisateur à l'installer.
230+
val downloaded = File(
231+
Environment.getExternalStoragePublicDirectory(
232+
Environment.DIRECTORY_DOWNLOADS), fileName)
233+
if (!ApkSignatureVerifier.matchesRunningApp(activity, downloaded)) {
234+
downloaded.runCatching { delete() }
235+
tvStatus.setText(R.string.update_error_signature)
236+
btnCancel.setText(R.string.update_close)
237+
break
238+
}
226239
// Nettoie les anciens APK dans Téléchargements (garde les 5 plus récents)
227240
ApkCleanup.cleanIfNeeded()
228241
// Ouvre le dossier Téléchargements dans le gestionnaire AAOS

0 commit comments

Comments
 (0)