DEV Community

LeoJulieta
LeoJulieta

Posted on

Android 17 y Certificate Transparency: adapta tu app en 3 pasos

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 CertificateTransparency con 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:

  1. Consulte los logs oficiales (Google CT Log, DigiCert Log, Let’s Encrypt Log, etc.).
  2. Verifique que el certificado presentado por el servidor contiene al menos un SCT válido.
  3. 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 CertificateTransparency para 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>
Enter fullscreen mode Exit fullscreen mode

Luego, referencia este archivo en el AndroidManifest.xml:

<application
    android:networkSecurityConfig="@xml/network_security_config"
    ... >
    ...
</application>
Enter fullscreen mode Exit fullscreen mode

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 }
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

Tip: llama a verifySCTs justo después de obtener la cadena de certificados en tu HostnameVerifier o 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]))
Enter fullscreen mode Exit fullscreen mode

Cómo usarlo

$ python3 audit_ct.py app-release.apk
[PASS] Certificado #1 contiene SCT válido
✅ Todos los certificados cumplen CT
Enter fullscreen mode Exit fullscreen mode

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)