Code Signing (firma del codice) è un meccanismo di firma digitale per file eseguibili che garantisce l'autenticità dello sviluppatore e l'integrità dell'applicazione. Su Android, ogni file APK deve essere firmato con un certificato prima dell'installazione su un dispositivo o della pubblicazione su Google Play. Secondo Google, 2024, Android supporta quattro generazioni di schemi di firma: dalla v1 basata su JAR alla v4 per l'installazione in streaming.
Punti chiave
Code Signing è un processo crittografico in cui lo sviluppatore firma il codice eseguibile con il proprio certificato digitale. La firma viene creata utilizzando la crittografia asimmetrica: la chiave privata dello sviluppatore genera una firma digitale e la chiave pubblica viene incorporata nel certificato. Chiunque può verificare la firma utilizzando la chiave pubblica, ma modificare il codice senza rompere la firma è impossibile.
Nello sviluppo mobile, la firma del codice svolge tre funzioni. Prima — autenticazione: l'utente e la piattaforma possono identificare lo sviluppatore dell'applicazione. Seconda — integrità: qualsiasi modifica all'APK dopo la firma invalida la firma. Terza — aggiornamento affidabile: la piattaforma consente di aggiornare un'applicazione solo con APK firmati con lo stesso certificato della versione installata.
La firma digitale delle applicazioni Android ha rilevanza legale. Secondo la legislazione russa (63-FZ) e il regolamento europeo eIDAS, una firma elettronica qualificata equivale a una firma autografa. Tuttavia, firmare un APK con un certificato auto-firmato (pratica comune in Android) non è qualificato — conferma l'integrità, ma non l'identità dello sviluppatore dal punto di vista legale.
Android supporta quattro schemi di firma APK, ognuno risolve i problemi della versione precedente e aggiunge nuove funzionalità. Tutti gli schemi possono coesistere in un singolo APK — questo è necessario per la compatibilità con le versioni precedenti di Android.
Lo schema v1 (JAR signing) è apparso in Android 1.0. Firma singoli file all'interno dell'archivio APK utilizzando voci in META-INF/MANIFEST.MF. Lo svantaggio: un utente malintenzionato può modificare l'APK (aggiungere o rimuovere file) e firmare nuovamente solo quelli modificati senza toccare il resto. Questo rende v1 vulnerabile a determinati attacchi. Lo schema v2 (APK Signature Scheme), introdotto in Android 7.0, firma l'intero file APK nel suo insieme, inclusi tutti i byte tranne la firma stessa, eliminando la possibilità di modifica selettiva.
| Schema | Android | Caratteristica | Rotazione chiave |
|---|---|---|---|
| v1 (JAR) | 1.0+ | Firma per file | No |
| v2 | 7.0+ | Firma completa APK | No |
| v3 | 9.0+ | Firma + rotazione | Sì |
| v4 | 11.0+ | Streaming + ADB | Sì |
Lo schema v3, introdotto in Android 9.0, risolve un problema di vecchia data: cosa fare se la chiave di firma è compromessa o scaduta? In precedenza, cambiare la chiave di firma significava che l'applicazione veniva trattata come nuova — non poteva essere installata sopra una esistente. v3 aggiunge un meccanismo di rotazione: l'APK può includere una prova di rotazione (proof-of-rotation), firmata dalla vecchia chiave. Il sistema verifica la catena e consente l'aggiornamento dell'applicazione firmata con la nuova chiave.
Keystore è un contenitore sicuro che contiene chiavi private e certificati per firmare le applicazioni. Nello sviluppo Android, viene utilizzato il formato JKS (Java KeyStore) o PKCS12. Il keystore viene creato con l'utilità keytool, che fa parte del JDK. Ogni chiave nell'archivio è identificata da un alias e protetta da una password.
Il certificato in un keystore contiene la chiave pubblica e le informazioni del proprietario: nome dell'organizzazione, paese, periodo di validità. Per le applicazioni Android, il certificato può essere auto-firmato — Google non richiede un'autorità di certificazione (CA), il che distingue Android da iOS. Tuttavia, la validità del certificato deve essere di almeno 25 anni, poiché l'applicazione verrà aggiornata con la stessa chiave.
# Creazione di un nuovo keystore per la firma
keytool -genkey -v -keystore my-release.keystore \
-alias my-app-alias \
-keyalg RSA \
-keysize 2048 \
-validity 10000
# Visualizzazione del contenuto del keystore
keytool -list -v -keystore my-release.keystore
Android supporta due algoritmi per le chiavi di firma: RSA e ECDSA. RSA con una dimensione della chiave di 2048 bit è lo standard de facto, supportato da tutte le versioni di Android. ECDSA (algoritmo di firma digitale a curva ellittica) con la curva P-256 fornisce la stessa forza crittografica con una dimensione della chiave inferiore. Da Android 9.0, si raccomanda ECDSA perché è più veloce nella verifica sui dispositivi mobili.
Nel Android Gradle Plugin, la firma viene configurata tramite il blocco signingConfigs nel build.gradle a livello di modulo. Per le build di debug, Android Studio crea automaticamente un keystore di debug con password note. Per le build di release, lo sviluppatore specifica il percorso del proprio keystore, l'alias della chiave e le password. Si consiglia di memorizzare le password in file di configurazione separati, esclusi dal controllo versione.
Una pratica moderna è la gestione centralizzata della firma tramite CI/CD. Jenkins, GitLab CI o GitHub Actions possono memorizzare il keystore come artefatto protetto e le password come segreti di ambiente. Ciò impedisce la fuga di chiavi attraverso il repository e semplifica la rotazione delle chiavi quando necessario.
// build.gradle (livello app) — configurazione della firma
android {
signingConfigs {
release {
storeFile file("my-release.keystore")
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD")
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
Per la massima compatibilità, un APK dovrebbe essere firmato con tutti e tre gli schemi (v1 + v2 + v3). Android Gradle Plugin include tutti gli schemi per impostazione predefinita. Gli APK firmati solo con v2 non verranno installati su Android 6.0 e versioni precedenti. Gli APK solo con v1 non riceveranno i vantaggi di integrità di v2 su Android 7.0+. Includere tutti gli schemi non aumenta le dimensioni dell'APK di oltre l'1–2% e garantisce la compatibilità con qualsiasi dispositivo.
Play App Signing è un servizio Google Play che gestisce centralmente le chiavi di firma delle applicazioni. Lo sviluppatore carica un APK firmato con una chiave di upload (upload key) su Google Play Console e Google Play lo firma nuovamente con una chiave di distribuzione (distribution key) prima di consegnarlo agli utenti. Questo protegge la chiave di distribuzione da perdita o compromissione.
Vantaggi di Play App Signing: sicurezza — la chiave di distribuzione è conservata nell'archivio protetto di Google; rotazione — è possibile richiedere un cambio di chiave tramite la console; recupero — se la chiave di upload viene persa, è possibile generarne una nuova. Svantaggio: per le applicazioni che esistevano prima dell'introduzione di Play App Signing, la migrazione richiede la creazione di una nuova applicazione, poiché la vecchia chiave di distribuzione è già in uso.
# Ottenimento dell'impronta del certificato (SHA-256)
keytool -list -v -keystore my-release.keystore \
-alias my-app-alias | grep "SHA256"
# Verifica della firma APK con apksigner
apksigner verify --verbose app-release.apk
Se la chiave di firma viene persa e Play App Signing non viene utilizzato, è impossibile ripristinare la possibilità di aggiornare l'applicazione — sarà necessario creare una nuova applicazione con un nuovo nome del pacchetto. Questa è una delle ragioni principali per utilizzare Play App Signing. Google consiglia di conservare una copia di backup del keystore in un archivio offline sicuro (unità USB crittografata, cassetta di sicurezza bancaria).
Durante l'installazione di un APK, Android esegue la verifica della firma in diverse fasi. Prima — controllo del certificato: se la validità è scaduta e il formato è corretto. Seconda — verifica della firma: se la firma crittografica corrisponde al contenuto dell'APK. Terza — confronto del certificato con la versione installata: se l'applicazione esiste già sul dispositivo, il certificato deve corrispondere, altrimenti l'installazione viene bloccata.
Il sistema di verifica è integrato in PackageManagerService. Durante l'elaborazione di una richiesta di installazione, PMS estrae la firma dall'APK, la verifica utilizzando la classe android.util.PackageParser e la confronta con la firma memorizzata dell'applicazione installata (se esiste). In caso di mancata corrispondenza, l'utente riceve l'errore “INSTALL_FAILED_UPDATE_INCOMPATIBLE”. Questo meccanismo previene gli attacchi di sostituzione (il malware non può sostituire un'applicazione legittima con la propria versione).
Uno sviluppatore può verificare autonomamente la firma dell'APK utilizzando l'utilità apksigner dagli Android SDK Build Tools. Il comando apksigner verify --verbose app.apk mostra con quali schemi è firmato l'APK, se i certificati sono validi e se le firme corrispondono al contenuto. Per la verifica programmatica della firma di un'applicazione installata, si utilizza PackageManager.getPackageInfo() con il flag GET_SIGNATURES.
// Verifica programmatica della firma di un'applicazione installata
fun getAppSignature(context: Context, packageName: String): String? {
val pm = context.packageManager
val info = pm.getPackageInfo(
packageName,
PackageManager.GET_SIGNATURES
)
return info.signatures?.firstOrNull()?.toCharsString()
}
La sicurezza della chiave di firma è un aspetto critico dello sviluppo Android. La compromissione della chiave consente a un utente malintenzionato di firmare gli aggiornamenti della tua applicazione con il proprio codice. Le regole principali: non conservare mai la chiave in un repository, non utilizzare la stessa chiave per applicazioni diverse, non trasferire la chiave attraverso canali non sicuri (email, messaggeri).
La pratica raccomandata è la separazione delle chiavi. Utilizza una chiave separata per ogni applicazione e una chiave separata per il caricamento su Google Play (upload key). Per le build di debug, Android Studio crea un debug.keystore condiviso — non deve essere utilizzato per le build di release. La validità del certificato dovrebbe essere di 25–30 anni (standard attuale, confermato da Google).
| Pratica | Raccomandazione |
|---|---|
| Archiviazione della chiave | Supporto crittografato, segreti CI/CD |
| Validità del certificato | Almeno 25 anni |
| Algoritmo | RSA 2048+ o ECDSA P-256 |
| Separazione | Chiave separata per applicazione |
| Backup | Copia offline del keystore |
Controlla regolarmente l'integrità della catena di firma. Quando i dipendenti con accesso alle chiavi lasciano l'azienda, aggiorna la chiave di upload tramite Google Play Console. Utilizza strumenti come Google Play Integrity API per verificare che la tua applicazione non sia stata manomessa sui dispositivi degli utenti. L'API restituisce dati sulla firma e l'integrità, inviandoli al server per la verifica.
Domande frequenti
Code Signing è una firma digitale di un file APK che conferma che l'applicazione è stata creata da uno sviluppatore specifico e non è stata modificata dopo la firma. Senza firma, l'APK non verrà installato su un dispositivo.
Utilizza l'utilità keytool del JDK: keytool -genkey -v -keystore my-release.keystore -alias my-alias -keyalg RSA -keysize 2048 -validity 10000. Specifica il keystore risultante in build.gradle nel blocco signingConfigs.
Se la chiave viene persa e non utilizzi Play App Signing, l'aggiornamento dell'applicazione diventa impossibile. Dovrai creare una nuova applicazione su Google Play con un nuovo nome del pacchetto. Utilizza Play App Signing per proteggerti dalla perdita della chiave.
v1 firma ogni file all'interno dell'APK individualmente — un utente malintenzionato può modificare un file e firmare nuovamente solo quello. v2 firma l'intero APK nel suo insieme — qualsiasi modifica invalida la firma, fornendo un livello di sicurezza più elevato.
Play App Signing è un servizio Google Play che conserva centralmente la chiave di distribuzione delle applicazioni. Lo sviluppatore carica un APK firmato con una chiave di upload e Google lo firma nuovamente prima di consegnarlo agli utenti, proteggendo la chiave da perdita o furto.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche