Certificate Pinning es un mecanismo de fijación del certificado o clave pública del servidor, mediante el cual la aplicación utiliza una huella previamente conocida para verificar la conexión HTTPS. A diferencia de la cadena de confianza estándar a través de una CA, el pinning garantiza que incluso una autoridad certificadora comprometida no pueda emitir un certificado fraudulento para su dominio. Según OWASP MSTG (2025), Certificate Pinning forma parte de la lista de controles obligatorios para aplicaciones con nivel de protección L2. La implementación incluye el almacenamiento de hashes de certificados en el código y su verificación en cada solicitud.
Puntos Clave
Certificate Pinning es una técnica de seguridad mediante la cual una aplicación almacena la huella digital de un certificado de confianza y la utiliza como único criterio para establecer una conexión HTTPS. En el modelo TLS estándar, el cliente verifica que el certificado del servidor esté firmado por una CA raíz de confianza — cualquiera de los cientos de autoridades certificadoras preinstaladas en el sistema. Certificate Pinning reemplaza esta cadena con una verificación directa: el certificado debe coincidir con la muestra almacenada o contener la clave pública esperada.
El problema del modelo estándar se hizo evidente tras los incidentes de compromiso de CA — DigiNotar (2011), Comodo (2011), TrustCor (2022). Si una CA emite un certificado fraudulento para su dominio, el navegador o la aplicación lo acepta como válido. Certificate Pinning previene este ataque: incluso un certificado fraudulento perfectamente firmado será rechazado porque su huella no coincide con la fijada en la aplicación.
El término pinning proviene de pin — «clavija» o «fijador»: el desarrollador fija un certificado de confianza, y cualquier desviación del mismo bloquea la conexión. Según el estudio de Mitre CWE-295, la validación incorrecta de certificados sigue siendo uno de los 10 errores de seguridad más peligrosos en aplicaciones móviles, y Certificate Pinning es un método directo para evitarlo.
Originalmente, Certificate Pinning se usaba en navegadores mediante el mecanismo HPKP (HTTP Public Key Pinning), estandarizado en RFC 7469. El desarrollador enviaba una cabecera HTTP Public-Key-Pins con los hashes de las claves esperadas, y el navegador las almacenaba por un período determinado. Sin embargo, HPKP resultó peligroso: un solo error de configuración podía bloquear un sitio durante meses. En 2018, Chrome dejó de soportar HPKP, y el estándar actual pasó a ser la implementación del lado del cliente — dentro de una aplicación móvil o extensión del navegador.
El proceso de Certificate Pinning incluye tres etapas clave: cálculo de la huella, verificación de la conexión y manejo de errores. Durante la preparación, el desarrollador obtiene el hash SHA-256 del certificado o clave pública del servidor de producción. Para aplicaciones compatibles con GDPR y PCI DSS, también es necesario fijar las huellas de las CAs intermedias en la cadena.
Con cada solicitud HTTPS, la aplicación intercepta la devolución de llamada de autenticación TLS, extrae el certificado del servidor y calcula su hash SHA-256. Este hash se compara con la lista almacenada de huellas de confianza. Si hay coincidencia — la conexión continúa. Si no — la aplicación debe terminar la conexión e informar del error sin revelar detalles de implementación al atacante.
fun validateCertificate(certificate: X509Certificate,
expectedHash: String): Boolean {
val digest = MessageDigest.getInstance("SHA-256")
val hash = Base64.encodeToString(
digest.digest(certificate.publicKey.getEncoded()),
Base64.DEFAULT
).trim()
return hash == expectedHash
}
La función recibe un objeto X509Certificate del servidor y el hash esperado. Primero extrae la clave pública del certificado, calcula el hash SHA-256 y lo codifica en Base64. El resultado se compara con la huella esperada. En producción, conviene añadir la verificación contra un array de 2–3 huellas para soportar la rotación.
Al implementar el pinning, hay que elegir qué objeto criptográfico fijar. Certificate Pinning se vincula al propio certificado X.509 — su número de serie, período de validez y toda la cadena. Public Key Pinning fija solo la clave pública dentro del certificado, ignorando los demás campos. Esta elección afecta significativamente los costes operativos.
| Criterio | Certificate Pinning | Public Key Pinning |
|---|---|---|
| Objeto de fijación | Certificado X.509 completo | Clave pública RSA/ECDSA |
| Rotación | Requiere actualización en cada reemisión | No cambia al renovar el certificado con la misma clave |
| Seguridad | Vinculación de máxima precisión | Menos sensible a los detalles |
| Flexibilidad | Baja — los certificados cambian cada 1–2 años | Alta — las claves pueden durar 5–10 años |
| Recomendación | Para sistemas críticos con actualizaciones controladas | Para la mayoría de aplicaciones móviles y API |
Public Key Pinning es la opción preferida para la mayoría de proyectos. Las claves públicas de los servidores generalmente permanecen sin cambios al reemitir un certificado — la empresa simplemente firma la clave antigua con un certificado nuevo. Esto significa que la aplicación no requiere una actualización tras un cambio de certificado si el par de claves no ha cambiado. Certificate Pinning, por otro lado, se recomienda para escenarios donde el desarrollador controla completamente tanto el servidor como el código del cliente, como en aplicaciones empresariales con un ciclo de actualización estricto.
TOFU es una estrategia en la que Certificate Pinning no se configura de antemano, sino que recuerda el certificado en la primera conexión al servidor. Este enfoque es útil para aplicaciones que no saben de antemano a qué servidor se conectarán. El inconveniente es la vulnerabilidad ante un ataque inicial: si la primera conexión es interceptada, un certificado fraudulento será aceptado como de confianza. TOFU se utiliza en conexiones SSH y algunos protocolos P2P.
En ambas plataformas, Certificate Pinning se implementa interceptando la conexión TLS a nivel de la pila de red. En iOS se utiliza el delegado URLSession o Alamofire ServerTrustManager. En Android, el método preferido es OkHttp CertificatePinner, que está integrado en clientes HTTP populares y admite la configuración de múltiples huellas para cada dominio.
func validate(serverTrust: SecTrust,
pinnedHash: String) -> Bool {
guard let certificates = SecTrustCopyCertificateChain(serverTrust)
as? [SecCertificate] else { return false }
for certificate in certificates {
let data = SecCertificateCopyData(certificate)
var hash = Data(repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
data.withUnsafeBytes {
CC_SHA256($0.baseAddress,
CC_LONG(data.count), &hash)
}
if hash.base64EncodedString() == pinnedHash {
return true
}
}
return false
}
En la función Swift, se extrae la cadena de certificados de serverTrust, se calcula un hash SHA-256 para cada certificado y el resultado se compara con el esperado. Iterar por todos los certificados de la cadena permite implementar el pinning a nivel de CA intermedia — si un certificado intermedio coincide, la conexión se acepta. Esto proporciona flexibilidad durante la rotación de certificados hoja.
Si la aplicación no utiliza OkHttp, Certificate Pinning se puede implementar mediante un X509TrustManager personalizado. Este método requiere más código, pero ofrece control total sobre el proceso de verificación. El TrustManager sobrescribe el método checkServerTrusted, donde el desarrollador verifica manualmente los certificados del servidor y decide si confiar en ellos. Se recomienda solo para escenarios específicos donde la biblioteca OkHttp no esté disponible.
El error más común es la ausencia de backup pins. El desarrollador incluye una sola huella de certificado y, cuando expira, los usuarios pierden la conexión masivamente. La configuración mínima aceptable son dos huellas: el certificado actual y uno de respaldo. Idealmente tres: el actual, un respaldo y la huella de la CA raíz como fallback.
El segundo error es almacenar los pins en texto plano en el código. Un atacante con acceso a un APK o IPA puede extraer y reemplazar fácilmente las huellas. Se recomienda ofuscar los hashes: dividir la cadena en partes, almacenar en recursos cifrados o calcular en tiempo de ejecución. Para Android, ProGuard con ofuscación de constantes de cadena es efectivo.
El tercer error es fijar al nivel del certificado de desarrollo. Los certificados de desarrollo y producción suelen ser diferentes, pero los desarrolladores a menudo olvidan cambiar los pins al compilar una versión de lanzamiento. El resultado es que la aplicación de producción no puede conectarse al servidor. La solución es configuraciones separadas de pins para debug y release mediante BuildConfig o recursos específicos de flavor.
Preguntas Frecuentes
SSL Pinning es un término general para la vinculación a un certificado SSL/TLS. Certificate Pinning es una implementación concreta que fija el propio certificado X.509, no solo la clave pública. La diferencia está en el objeto de vinculación: certificado vs clave.
Se recomienda almacenar los hashes en recursos con ofuscación mediante ProGuard (Android) o cifrados a través de Keychain (iOS). Evite almacenar pins en texto plano en strings.xml o Info.plist sin cifrado.
Con cada cambio de certificado en el servidor. Se recomienda añadir una nueva huella como backup pin 3–6 meses antes de que expire la actual, y eliminar la antigua tras la rotación. Al menos un backup pin es obligatorio.
Sí, mediante compilación condicional: el pinning está deshabilitado en la compilación de depuración y habilitado en la de lanzamiento. Use BuildConfig.DEBUG en Android o #if DEBUG en iOS para el cambio. Nunca lo haga mediante una bandera en tiempo de ejecución accesible al usuario.
Publique inmediatamente una actualización de la aplicación con nuevas huellas en las tiendas. Use un mecanismo de actualización forzada. Si los backup pins incluían la huella de la CA de respaldo, puede cambiar temporalmente a otro dominio con un certificado diferente.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también