Firma de código en macOS: Lo que los Desarrolladores han de saber, Parte 2

Desde el punto de vista Apple sobre el firmado de código con certificados, ya sabemos que el certificado Root requerido, y que actúa como el ancla base en la cadena de confianza, está instalado por omisión en el Llavero Sistema Raíz de tu Mac.

Pero antes de que lleguemos a los certificados de desarrollador “hoja”… también necesitamos contar con los certificados Intermedios de Desarrollador instalados en nuestro llavero; por lo general en el llavero Inicio, aunque también es posible encontrar estos certificados en los llaveros Sistema o Sistema Raíz.

Instalando los Certificados Intermedios de Desarrollador

A partir de Xcode 11.4.1 dichos certificados se pueden descargar e instalar automáticamente en el Llavero pero, si no es ese el caso, dichos certificados intermedios también se pueden descargar desde la página web PKI de Apple. Aquellos en los que estamos interesados son:

  • Developer ID – G2
  • Worldwide Developer Relations – G2
  • Worldwide Developer Relations – G3
  • Worldwide Developer Relations – G4
  • Worldwide Developer Relations – G5
  • Worldwide Developer Relations – G6

Mientras que el certificado intermedio “Developer ID – G2” equivale a “Developer ID Certification Authority“, aquellos que comienzan por “Worldwide Developer Relations” equivalen al certificado intermedio “Apple Worldwide Developer Relations Certification Authority” (WWDR, abreviado).

Como puedes ver en el anterior listado, existen varias versiones (o generaciones) en el caso de los certificados intermedios WWDR; de modo que, ¿cuál deberías descargar en el caso de que debas hacerlo? La respuesta corta es: depende.

El 7 de Febrero de 2023 expiraron los certificados intermedios WWDR existentes; de modo que Apple decidió desplegar una versión renovada que caduca el 20 de Febrero de 2030. Como parte de dicha actualización, Apple desplegó certificados intermedios adicionales para segmentar de mejor forma el propósito de diferentes certificados:

  • G2: Firma ECDSA para Apple Pay.
  • G3: Firma de software y Servicios.
  • G4: Características soportadas por el servicio de Notificaciones Push de Apple.
  • G5: Firma de App Store y Servicios.
  • G6: Firma ECDSA de software y Servicios.

De forma que, probablemente las versiones G3, G5 y G6 de estos certificados sean buenas elecciones para la mayoría de los casos.

Certificados de Desarrollador: ¡El objetivo final!

Para enfocarnos en el asunto, ¿qué tipo de certificados de desarrollador hoja se crean a partir de estos tipos de certificados intermedios? El siguiente esquema será de ayuda:

Tal y como puedes ver en este diagrama, hay cuatro tipos diferentes de certificados hoja que podremos usar para firmar nuestras apps macOS, basándonos en sus prefijos:

  • Developer ID Application. Utiliza este para el firmado de código correspondiente a una app macOS distribuida de forma directa, fuera de la Mac App Store.
  • Developer ID Installer. Utiliza este para firmar el código de un Instalador, archivo DMG o .pkg, correspondiente a una app macOS distribuida de forma directa, fuera de la Mac App Store.
  • Apple Distribution. Este es el certificado requerido para firmar código de una app macOS enviada a AppStore Connect para que sea distribuida en la Mac App Store.
  • 3rd Party Mac Developer Installer. Este es el certificado requerido para el firmado de código correspondiente al paquete de una app enviada a la AppStore Connect. Por ejemplo, cuando se utiliza la característica Publish desde el IDE de Xojo.

Crear e Instalar Certificados de Desarrollador

Como se dijo en el primer artículo de esta serie, has de ser miembro de pago del Apple Developer Program. Una vez que esto sea así, la forma más sencilla de instalar los certificados requeridos en el Llavero de tu Mac es mediante Xcode.

Para ello, y si es la primera vez que necesitas instalarlos en cualquiera de tus Mac, sólo has de hacer lo siguiente:

  1. Dirigete a Xcode > Preferences.
  2. Selecciona Apple Accounts.
  3. Utiliza tus credenciales de desarrollador para conectarte a tu cuenta de desarrollo, o bien selecciónala en el listado en el caso de que ya estuvieses logado.
  4. Selecciona el Team (equipo) en el listado.
  5. Haz clic en el botón “Manage Certificates…”
  6. Haz clic en el menú desplegable “+” situado en la esquina inferior izquierda de la ventana resultante, y selecciona el certificado de desarrollador que quieras instalar (todos ellos si es la primera vez que los instalas).

Nota: Bajo el capó, Xcode sigue el mismo proceso descrito a continuación, donde se indica cómo instalar los certificados de desarrollador de forma manual.

Si prefieres hacerlo de forma manual:

  1. Accede al Sitio de Desarrollador de Apple.
  2. En el apartado Certificates, Identifiers & Profiles, haz clic en Certificates en la barra lateral.
  3. En la esquina superior izquierda, haz clic sobre el botón Add (+).
  4. Bajo Software, selecciona Developer ID, luego haz clic en Continue.
    • Developer ID Application: Este es el certificado que se utiliza para firma el código de tu app para su distribución directa, fuera de la Mac App Store.
    • Developer ID Installer: Este es el certificado que se usa para firmar el paquete de instalación de tu app cuando se distribuye de forma directa, fuera de la Mac App Store.
    • Apple Development: Utilizado para ejecutar y depurar apps en macOS durante la fase de desarrollo.
    • Apple Distribution: Usado para firmar las apps que se envíen a la App Store Connect.
    • Mac App Distribution: Utilizado para firmar apps macOS que se vayan a distribuir a través de la Mac App Store.
    • Mac Installer Distribution: Usado para envar la app macOS a App Store Connect para TestFlight o su distribución en la Mac App Store.
  5. Sigue las instrucciones para crear uns solicitud de certificado de firmado (CSR, por sus siglas en inglés).
  6. Haz clic en Choose File.
  7. En el diálogo resultante, selecciona el archivo de solicitud de certificado (un archivo con la extensión de archivo .certSigningRequest); luego, haz clic en Choose.
  8. Haz clic en Continue.
  9. Haz clic en Download.
  10. El archivo de certificado (un archivo con la extensión .cer) aparecerá en tu carpeta Descargas.
  11. Para instalar el certificado en el llavero de tu Mac, haz doble clic en el archivo de certificado descargado.

El certificado aparece en la categoría Mis Certificados de Acceso a Llaveros.

¡Se trata de las Identidades!

Si bien los certificados Intermedios y Raíz sólo cuentan con la clave pública, de modo que puedan verificar otros certificados “hoja”, los certificados hoja instalados en el llavero de tu Mac se comportan de un modo ligeramente distinto. Veamos como.

Tanto si utilizas Xcode o creas la solicitud CSR de forma manual para generar los certificados de desarrollo, en ambos casos se creará y almacenará una llave privada localmente en tu llavero como parte del proceso. Sólo la sección correspondiente a la clave pública de dicha clave privada será la que se envíe a los servidores de Apple, de modo que pueda incluirse en el certificado de desarrollador generado. Una vez que cualquiera de los posibles certificados de desarrollador se haya descargado e instalado en el llavero, dicho certificado tendrá asociada la llave privada con él:

El par compuesto por el certificado de desarrollador y su clave privada es lo que se denomina una Identidad.

Firma de Código con Certificados de Desarrollador

De hecho, si bien estamos acostumbrados a escuchar con frecuencia, o decir nosotros mismo, “firma de código con certificados”, lo cierto es que el firmado real de las apps se realiza utilizando la clave privada asociada con dicho certificado, mientras que el certificado propiamente dicho (y por tanto la sección correspondiente a la clave pública de dicha clave privada), es la que se incluye como parte del proceso de firmado. De este modo puede macOS puede verificarla cada vez que el usuario intente ejecutar la app.

¿Recuerdas el diagrama que mostraba como funcionaba el firmado de código “Ad-Hoc”? Comparémoslo con el mismo proceso cuando se utiliza el certificado “Developer ID Application”… y, lo más importante, la clave privada asociada:

Como puedes ver, en este caso los datos se cifran mediante el uso de la clave privada correspondiente al certificado de desarrollo y, luego, se incorpora el propio certificado como parte de la firma de la app. Así, si por ejemplo compilamos una app Desktop utilizando el certificado Developer ID Application, y abrimos el archivo CodeResources resultante en un editor de textos veremos algo distinto en comparación con la versión de firma “Ad-Hoc”:

En este caso el campo de requerimiento asociado con cada archivo y el valor de hash es bastante más estricto. De hecho, hace referencia a la cadena de confianza que ha de seguir y validar Gatekeeper. En castellano plano, las líneas resaltadas vienen a decir algo como:

  • ¡Hey! Asegúrate de que haya un certificado del tipo Developer ID Application (atributo de extensión Apple -OID- 1.2.840.113635.100.6.1.13 en el estándar de certificados X.509), para el desarrollador cuyo TeamID sea BW7PU32485.
  • Luego, verifica que dicho certificado haya sido emitido por “Apple Developer ID Certificate Authority” (otra de las extensiones X.509 específicas de Apple, atributo o OID; en este caso: 1.2.840.113635.100.6.2.6).
  • Y por último, ve por la cadena de confianza y verifica el anterior con el certificado ancla (Apple Root CA, ¿recuerdas?).

Muy bien, pero… ¿cómo podemos saber si dicha app respeta dichos requerimientos y los certificados propiamente dichos? Bieno, fácil de comprobar ambos aspectos con la herramienta codesign.

Abre una ventana del Terminal y escribe el siguiente comando:

codesign --verify -vvv "MyApp.app"

La salida será algo similar a esto:

Como puedes ver en las líneas destacadas… sí, satisface los Requerimientos Designados que hemos visto en nuestro archivo CodeResources. De igual modo, la anterior línea también confirma que la app es válida en disco, lo que significa que:

  • Están presentes todos los archivos esperados.
  • No hay archivos adicionales.
  • Ninguno de los archivos ha sido modificado.
  • Se ha realizado con éxito una evaluación básica de confianza sobre el certificado hoja.
  • Y también satisface sus propios Requerimientos Designados (DR).

Incluso es posible ver la Cadena de Confianza sobre la firma de código mediante:

codesign --display -vv "MyApp.app"

Y si tienes más curiosidad, incluso es posible extraer los certificados embebidos, contenidos en la estructura CMS de la firma de código:

codesign --display --extract-certificates "MyApp.app"

Como resultado se generarán tres archivos por lo general. Echa un vistazo con atención a las líneas “Issuer” y “Subject”; especialmente al valor OU de la línea Subject (Organizative Unit o, utilizando los términos de Apple, el TeamID) en el archivo codesign0. ¿Recuerdas los datos “leaf[subject.OU=BW7PU32485]” en el archivo CodeResources?:

codesign0. Este es el archivo correspondiente al certificado hoja; en nuestro ejemplo “Developer ID Application”.

codesign1. Este se corresponde con el Certificado Intermedio; en nuestro ejemplo “Apple Developer ID Certificate Authority”.

codesign2. Este es el Certificado Ancla; en nuestro ejemplo “Apple Root CA”.

Como puedes ver en la línea Issuer del archivo codesign0 para nuestro “Developer ID Application” apunta al siguiente (previous) certificado en la cadena de confianza. Esto es, el “Developer ID Certification Authority”. Luego, el archivo codesign1 correspondiente al certificado extraído (Developer ID Certification Authority) apunta a “Apple Certification Authority” como su campo Issuer (Emisor). Por último, el certificado codesign2 apunta sobre sí mismo porque, bueno, es el Certificado Raíz o ancla en la cadena de confianza.

Conclusiones

En este segundo artículo hemos comenzado a ver en mayor profundidad como funcionan los Certificados de Desarrollador de Apple, también como se firma una app ya sea como Ad-Hoc o bien usando un certificado específico de desarrollador; y también cómo se realiza el proceso de validación mediante las características de seguridad de macOS cada vez que el usuario ejecuta una aplicación.

En el siguiente artículo veremos más detalles relacionados con la firma de aplicaciones para los dos tipos principales de distribución: distribución directa y en la Mac App Store. También veremos qué ocurre cuando un certificado expira, y como resolver los problemas más frecuentes relacionados con dichos certificados.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *