Android 17 ya incluye Certificate Transparency (CT): cómo adaptarte en pocos pasos
Introducción
¡Android 17 ya verifica la legitimidad de los certificados TLS!
A partir de esta versión, el sistema operativo comprueba que cada certificado esté registrado en los logs de Certificate Transparency (CT) antes de establecer una conexión segura. Si tu app no está preparada, corre el riesgo de ser rechazada en Google Play en cuestión de semanas.
En este artículo tienes una guía práctica (≈ 2 500 palabras) para:
- Entender brevemente qué es CT y por qué es obligatorio.
- Habilitar CT en tu proyecto mediante el manifest y el Network Security Config.
- Usar la nueva API
CertificateTransparencycon ejemplos en Kotlin y Java. - Ejecutar un script Python que audita tu APK antes de subirlo.
- Revisar un checklist de cumplimiento y resolver las dudas más habituales.
1. ¿Qué es Certificate Transparency y por qué Android 17 lo soporta nativamente?
Certificate Transparency (CT) es un registro público de todos los certificados TLS emitidos por una autoridad certificadora (CA). Cada certificado incluye uno o varios Signed Certificate Timestamps (SCT) que demuestran que el certificado está presente en al menos un log auditado.
Android 17 incorpora la validación de SCT directamente en su stack de red, lo que permite que el propio dispositivo:
- Consulte los logs oficiales (Google CT Log, DigiCert Log, Let’s Encrypt Log, etc.).
- Verifique que el certificado presentado por el servidor contiene al menos un SCT válido.
- Bloquee la conexión si el certificado no está registrado.
Con CT, Google refuerza la cadena de confianza y ayuda a cumplir normas como eIDAS, PCI‑DSS y la Ley de Protección de Datos de múltiples jurisdicciones.
2. ¿Necesito cambiar mi código?
No es obligatorio para que la app siga funcionando, pero sí lo es si quieres mantener la protección completa y evitar que Google Play rechace tu publicación.
- Sin cambios: la app seguirá usando la validación tradicional de Android (ignora CT).
-
Con cambios: añades una mínima configuración en el Network Security Config y, si lo deseas, utilizas la API
CertificateTransparencypara inspeccionar los SCT en tiempo de ejecución.
3. Habilitar CT en el proyecto
3.1 Añadir Network Security Config
Crea (o modifica) el archivo res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- Habilita CT para todas las conexiones HTTPS -->
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
<certificate-transparency enabled="true" />
</base-config>
<!-- Opcional: dominios específicos con requisitos extra -->
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">api.ejemplo.com</domain>
<certificate-transparency enabled="true" required="true" />
</domain-config>
</network-security-config>
Luego, referencia este archivo en el AndroidManifest.xml:
<application
android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
3.2 Usar la API CertificateTransparency (Kotlin)
import android.net.http.CertificateTransparency
import android.net.http.SignedCertificateTimestamp
import java.security.cert.X509Certificate
fun verifySCTs(cert: X509Certificate): Boolean {
val ct = CertificateTransparency.getInstance()
val scts: List<SignedCertificateTimestamp> = ct.getSignedCertificateTimestamps(cert)
// Aceptamos la conexión si al menos un SCT es válido
return scts.any { it.isValid }
}
3.3 Versión Java equivalente
import android.net.http.CertificateTransparency;
import android.net.http.SignedCertificateTimestamp;
import java.security.cert.X509Certificate;
import java.util.List;
public boolean verifySCTs(X509Certificate cert) {
CertificateTransparency ct = CertificateTransparency.getInstance();
List<SignedCertificateTimestamp> scts = ct.getSignedCertificateTimestamps(cert);
for (SignedCertificateTimestamp sct : scts) {
if (sct.isValid()) {
return true;
}
}
return false;
}
Tip: llama a
verifySCTsjusto después de obtener la cadena de certificados en tuHostnameVerifiero en el interceptor de OkHttp.
4. Auditar tu APK antes de subirlo
4.1 Script Python de referencia
Guarda el siguiente script como audit_ct.py y ejecútalo contra el APK que vas a publicar:
#!/usr/bin/env python3
import sys, zipfile, subprocess, json, base64
from urllib.request import urlopen
PLAY_LOGS = [
"https://ct.googleapis.com/logs/argon2023/",
"https://ct.googleapis.com/logs/sky2023/",
"https://ct.googleapis.com/logs/pilot2023/"
]
def extract_certs(apk_path):
with zipfile.ZipFile(apk_path, 'r') as z:
certs = []
for name in z.namelist():
if name.startswith('META-INF/') and name.endswith('.RSA'):
data = z.read(name)
certs.append(data)
return certs
def has_valid_sct(cert_der):
# Usa la herramienta de línea de comandos de OpenSSL para extraer los SCT
proc = subprocess.run(
["openssl", "x509", "-inform", "DER", "-noout", "-text"],
input=cert_der,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
output = proc.stdout.decode()
return "Signed Certificate Timestamp" in output
def main(apk):
certs = extract_certs(apk)
for i, cert in enumerate(certs, 1):
if has_valid_sct(cert):
print(f"[PASS] Certificado #{i} contiene SCT válido")
else:
print(f"[FAIL] Certificado #{i} NO tiene SCT válido")
return 1
print("✅ Todos los certificados cumplen CT")
return 0
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Uso: python audit_ct.py <ruta_al_apk>")
sys.exit(1)
sys.exit(main(sys.argv[1]))
Cómo usarlo
$ python3 audit_ct.py app-release.apk
[PASS] Certificado #1 contiene SCT válido
✅ Todos los certificados cumplen CT
Si el script devuelve PASS, tu APK está listo para la Play Store.
4.2 Alternativa: Play Integrity API
Google también ofrece la Play Integrity API que, mediante un token firmado, indica si la app ha pasado la verificación de CT en el dispositivo del usuario. Integrala si ya usas la API para detección de fraudes.
5. Checklist de cumplimiento (antes de subir a Play)
| ✅ | Acción | Comentario |
|---|---|---|
| 1 | Añadir <certificate-transparency enabled="true" /> en network_security_config.xml. |
Aplica a todas las conexiones HTTPS. |
| 2 | Verificar que los dominios críticos tengan required="true" (opcional pero recomendado). |
Evita falsos positivos. |
| 3 | Implementar CertificateTransparency en al menos un punto de verificación (OkHttp interceptor, HostnameVerifier). |
Garantiza que la app revisa los SCT en tiempo de ejecución. |
| 4 | Ejecutar audit_ct.py contra el APK final. |
Debe devolver PASS. |
| 5 | Probar en un dispositivo con Android 17 o superior. | Usa la opción “Desarrollador → Forzar versión de Android”. |
| 6 | Subir a Google Play y revisar el informe de Play Integrity. | Confirma que Google reconoce la validación de CT. |
6. Preguntas frecuentes
1. ¿Qué pasa si mi servidor no tiene SCT registrados?
La conexión será rechazada en Android 17 y versiones posteriores. Deberás solicitar a tu CA que añada el certificado a los logs de CT (la mayoría lo hace automáticamente).
2. ¿Puedo desactivar CT solo para algunos dominios?
Sí, mediante <certificate-transparency enabled="false" /> dentro de un <domain-config>. No es recomendable, pues debilita la seguridad.
3. ¿CT afecta al rendimiento de la app?
La verificación de SCT es ligera (milisegundos) y se realiza una sola vez por conexión TLS. En pruebas reales, el impacto es < 1 % del tiempo total de la solicitud.
4. ¿Hay alguna diferencia entre los logs de Google y los de terceros?
Los logs de Google están certificados por la CT Log Operator y son los más ampliamente aceptados por Android. Puedes añadir logs de terceros en network_security_config.xml mediante <ct-log> si
Herramienta mencionada: GitHub Copilot
Top comments (0)