Firma de Código
La firma de código es una parte esencial de la distribución de aplicaciones. En Windows, las aplicaciones sin firmas de código son frecuentemente marcadas como virus. En OSX, la firma de código y la Notarización son requeridas antes de que los usuarios puedan ejecutar su aplicación.
En ambas plataformas, la firma debe ser realizada por Velopack, esto se debe a que los binarios de Velopack (como Update y Setup) necesitan ser firmados en diferentes puntos del proceso de construcción del paquete.
SmartScreen y Antivirus
En Windows, las aplicaciones sin firma son frecuentemente marcadas por SmartScreen y el software antivirus, y los usuarios pueden ver una advertencia antes de poder ejecutar su aplicación. La forma más confiable de evitar esto es firmar con código su aplicación (ver más abajo), pero la firma por sí sola no siempre es inmediata — las advertencias de SmartScreen se basan en la reputación, que se acumula con el tiempo a medida que más usuarios ejecutan sus binarios firmados.
Aquí está la regla general para las advertencias de Windows Defender / SmartScreen:
- No firma su código. Lanza MyApp-v1.exe. Las personas reciben advertencias de SmartScreen durante un tiempo hasta que la reputación de ese archivo aumenta. Lanza MyApp-v2.exe. Las personas reciben advertencias nuevamente hasta que MyApp-v2.exe acumula suficiente reputación.
- Firma su código con un certificado OV. Lanza MyApp-v1.exe. Las personas reciben advertencias de SmartScreen durante un tiempo hasta que la reputación de ese certificado aumenta. Lanza MyApp-v2.exe. Las personas no reciben advertencias porque el certificado ya tiene buena reputación. Eventualmente su certificado expira y llega el momento de lanzar MyApp-v47.exe. Renueva su certificado, y las personas reciben advertencias nuevamente hasta que el nuevo certificado acumule reputación.
- Firma su código con un certificado EV (Extended Validation). Las personas nunca reciben advertencias, porque los certificados EV reciben reputación instantánea de SmartScreen.
En resumen: firme su código, prefiera un certificado EV (o Azure Artifact Signing) para reputación instantánea, y espere un breve período de construcción de reputación para los certificados OV.
Firma en Windows
Adquirir un certificado de firma de código
Azure Artifact Signing
A partir de abril de 2024, la forma más efectiva de firmar con código su producto es a través de Azure Artifact Signing (anteriormente conocido como Azure Trusted Signing).
- Cuesta USD$10/mes (o USD$120/año), lo cual es comparable o más barato que los certificados de firma de código de otros emisores.
- Solución completamente en la nube / No requiere ningún hardware físico (HSM) enviado a usted.
- La firma puede automatizarse (p.ej. en su pipeline de CI)
- Los certificados de Artifact Signing obtienen reputación instantánea incorporada para SmartScreen y Defender.
Artifact Signing se puede usar siguiendo la documentación de Microsoft para usar Artifact Signing con signtool.exe, y luego leyendo nuestra documentación a continuación sobre cómo configurar signtool.exe con Velopack.
Otros proveedores de certificados
Si en cambio desea comprar un certificado de firma de código de un proveedor diferente, Microsoft enumera los siguientes emisores de confianza en su documentación:
También existen revendedores que pueden tener certificados de emisores autorizados a precios más bajos, pero el riesgo añadido es que no recibirá soporte oficial para esos certificados y los procedimientos de verificación de identidad pueden ser más complicados.
Tenga en cuenta que desde el 1 de junio de 2023 ha habido un cambio de política, lo que significa que ya no es posible descargar su certificado de firma de código. Debe almacenarse en un HSM de nube autorizado o se le enviará un HSM USB. Muchas de estas soluciones requerirán pasos manuales y no serán compatibles con la automatización / CI. Por favor, revise cuidadosamente antes de comprar.
Firma mediante Azure Artifact Signing
Azure Artifact Signing (anteriormente Trusted Signing) es un servicio de firma administrado de Microsoft y una de las formas más rentables de firmar su aplicación.
Para información detallada sobre Azure Artifact Signing, consulte la documentación oficial.
La firma depende de signtool.exe que solo es compatible con Windows. Si está usando un sistema operativo diferente, deberá firmar sus binarios en una máquina Windows antes de desplegarlos.
- Primero deberá crear una cuenta de Azure en: https://azure.microsoft.com/pricing/purchase-options/azure-account. Esta cuenta deberá tener una suscripción activa.
- Registre el proveedor de recursos de Azure Artifact Signing. Esto se puede hacer en el portal de Azure o a través de la CLI de Azure siguiendo estas instrucciones.
- Cree el recurso de Azure Artifact Signing siguiendo estas instrucciones. Tenga en cuenta el nombre y la región que seleccione, ya que usará estos valores más adelante para los valores
CodeSigningAccountNameyEndpointrespectivamente, en el archivo JSON de configuración de firma. - Cree una solicitud de validación de identidad siguiendo estas instrucciones. Este paso debe realizarse en el Portal de Azure. La validación de identidad puede realizarse para una Organización o para un desarrollador Individual. Este proceso puede tomar un tiempo ya que la información de identidad es verificada por Microsoft. Regrese a estos pasos después de que se complete el proceso de validación de identidad.
- Cree un perfil de certificado siguiendo estas instrucciones. Hay múltiples modelos de confianza compatibles. El modelo de Confianza Pública es el más común y es adecuado para la mayoría de las aplicaciones. Tenga en cuenta el nombre del perfil de certificado, ya que usará este valor más adelante como
CertificateProfileNameen el archivo JSON de configuración de firma. - Velopack incluye una versión de signtool.exe (x64) y el paquete dlib compatible con Azure Artifact Signing. Estos componentes requieren el Runtime de .NET 8.0 instalado en la máquina que realizará la firma. Puede encontrar la última versión del runtime de .NET 8.0 aquí.
- Configure la autenticación con Azure Artifact Signing.
signtool.exeutiliza la clase común DefaultAzureCredentials para autenticarse con Azure. Esta clase admite autenticación de diversas maneras, incluyendo la CLI de Azure. Después de instalar la CLI de Azure, ejecuteaz login. Esto proporcionará a signtool.exe la autenticación que necesita cuandovpklo invoque. Si está ejecutando dentro de GitHub Actions o Azure DevOps, hay soporte integrado que maneja la autenticación necesaria. - Cree el archivo JSON de metadatos de firma. Este archivo tiene tres parámetros requeridos y un CorrelationId opcional. El archivo debe verse así:
Los valores de cada uno de estos se pueden encontrar en los pasos anteriores donde creó el recurso de Azure Artifact Signing y el perfil de certificado. El archivo debe guardarse con codificación UTF-8 (sin BOM). Aunque no es obligatorio, suele llamarse{"Endpoint": "<Artifact Signing account endpoint>","CodeSigningAccountName": "<Artifact Signing account name>","CertificateProfileName": "<Certificate profile name>"}
metadata.json. Los detalles completos se pueden ver aquí. - Pase el archivo JSON de metadatos. Al llamar a
vpk packusando--azureTrustedSignFile <path to json file>.vpkpasará el archivo asigntool.exepara firmar los activos necesarios.
Firma mediante signtool.exe
Normalmente la firma se realiza a través de signtool.exe. Si ya utiliza esta herramienta para firmar su aplicación, puede pasar sus parámetros de firma directamente a Velopack (sin el comando 'sign').
Por ejemplo, si su comando de firma era:
signtool.exe sign /td sha256 /fd sha256 /f yourCert.pfx /tr http://timestamp.comodoca.com
Entonces ahora con --signParams sería:
vpk pack ... --signParams "/td sha256 /fd sha256 /f yourCert.pfx /tr http://timestamp.comodoca.com"
Siempre debe pasar rutas absolutas en sus argumentos de firma, ya que no hay garantía de que signtool se ejecute en el mismo directorio de trabajo que vpk.
Si es nuevo en el uso de signtool.exe, puede consultar la referencia de línea de comandos aquí. Recomiendo hacer que la firma funcione en un solo binario primero, usando signtool.exe, antes de intentar que funcione con la CLI de Velopack.
Si está usando un USB / HSM y tiene el siguiente error de firma Error: SignerSign() failed." (-2147023673/0x800704c7), esto significa que le falta una contraseña / token de desbloqueo. Esto se puede agregar a su comando de firma con los parámetros /csp /k. [Leer más]
Tenga cuidado al proporcionar parámetros con espacios. Debe envolver todo lo que contenga espacios entre comillas y escaparlos con una barra invertida. Por ejemplo, --signParams "/n \"My Cert Name\"". Si está usando una tarea MSBuild <Exec> o similar, necesitará usar " en su lugar.
De forma predeterminada, Velopack firmará 10 archivos por llamada a signtool.exe, para acelerar la firma y reducir el número de veces que necesita interactuar con la consola si está usando algún tipo de método de firma interactivo. Esto se puede deshabilitar con el argumento --signParallel 1.
Comandos y herramientas de firma personalizados
Si tiene requisitos de firma más avanzados, como una herramienta de firma personalizada (p.ej. AzureSignTool.exe), puede proporcionar una plantilla de comando en su lugar, donde {{file}} es el binario que Velopack sustituirá y firmará:
vpk pack ... --signTemplate "AzureSignTool.exe sign ... {{file}}"
Lo anterior firmará un archivo a la vez, pero si su herramienta de firma admite la firma por lotes de múltiples archivos a la vez, puede especificar {{file...}} en su lugar.
Firma Multiplataforma
JSign es una herramienta de firma de código versátil que se ejecuta en Linux, macOS y Windows. Admite una amplia gama de algoritmos de firma y servicios de marca de tiempo.
Para usarlo con Velopack, haga lo siguiente:
- Siga los pasos anteriores para configurar Azure Artifact Signing
- Descargue la última versión de JSign desde https://ebourg.github.io/jsign/#files
- Instale la CLI de Azure e inicie sesión con
az login - Obtenga un token de acceso ejecutando
az account get-access-token --resource https://codesigning.azure.net - Use la opción
--signTemplatepara firmar sus archivos.
vpk pack ... --signTemplate "jsign --storetype TRUSTEDSIGNING --keystore <region> --storepass <api-access-token> --alias <account>/<profile> {{file}}"
Firma y Notarización en OSX
La firma de código y la Notarización son requeridas antes de que los usuarios puedan ejecutar su aplicación, por lo tanto es un paso obligatorio antes de desplegar su aplicación.
Crear certificados de firma de código
- Primero, deberá crear una cuenta en https://developer.apple.com, pagar la cuota anual de desarrollador y aceptar cualquier acuerdo de licencia.
- Navegue a sus certificados: https://developer.apple.com/account/resources/certificates
- Haga clic en el icono (+) para crear nuevos certificados. Necesita crear tanto un certificado
Developer ID Installercomo un certificadoDeveloper ID Applicationpara la distribución de aplicaciones de Velopack fuera de la Mac App Store.
- Abra ambos certificados haciendo clic en ellos, presione Descargar, y luego haga doble clic en el archivo ".cer" para instalarlo en su llavero local.
Si sus certificados aparecen como no confiables en Acceso a Llaveros, o recibe una advertencia como "Warning: unable to build chain to self-signed root for signer "Developer ID Application: YourName", probablemente le falta un certificado de desarrollo en su máquina que puede descargarse desde aquí: https://www.apple.com/certificateauthority/
Configurar un perfil de NotaryTool
- Cree una contraseña específica de la aplicación: https://support.apple.com/en-us/102654. Esta contraseña solo se le mostrará una vez, así que guárdela o escríbala en algún lugar.
- Encuentre su ID de equipo de Apple: https://developer.apple.com/account#MembershipDetailsCard
- Almacene las credenciales de su cuenta de Apple en un nuevo perfil de NotaryTool:
xcrun notarytool store-credentials \--apple-id "yourapple@account.com" \--team-id "your-located-team-id" \--password "your-generated-app-specific-password" \"your-local-profile-name-here"
Uniendo todo
Ahora que tiene su perfil de NotaryTool y los certificados de firma de código instalados, puede agregar los siguientes parámetros a su comando pack:
vpk pack \
...
--signAppIdentity "Developer ID Application: Your Name" \
--signInstallIdentity "Developer ID Installer: Your Name" \
--notaryProfile "your-local-profile-name-here" \
Cuando estos parámetros se especifican y son válidos, Velopack firmará y notarizará automáticamente su aplicación y los paquetes de instalación.
Velopack usará codesign y xcrun notarytool para firmar y notarizar su aplicación. De forma predeterminada, usarán el llavero predeterminado en su dispositivo para descubrir certificados y el perfil de notarización.
Si desea usar un llavero diferente, debe instalar sus certificados y crear su perfil de notarización en ese llavero y usar el argumento --keychain {path} de Velopack
para especificar que Velopack debe descubrir certificados desde un llavero no predeterminado.
Si no proporciona un archivo de permisos para el runtime reforzado, se le proporcionará automáticamente uno adecuado para la mayoría de las aplicaciones dotnet. Si su aplicación requiere
permisos especiales y los predeterminados no son adecuados, debe proporcionar sus propios permisos de firma usando --signEntitlements {path}. Tenga en cuenta que el permiso de App
Sandbox de macOS (com.apple.security.app-sandbox) no es compatible con Velopack — consulte la nota de limitaciones de macOS para más detalles.
De forma predeterminada, Velopack realiza una firma "profunda" de todos los binarios dentro de su paquete. Si prefiere pre-firmar sus propios binarios y que Velopack los omita,
puede pasar --signDisableDeep.
Aunque su certificado pueda aparecer como Developer ID Application: Your Name (TeamName) en Acceso a Llaveros, no debe especificar el nombre del equipo como parte de
sus argumentos --signAppIdentity o --signInstallIdentity. Su certificado debe ser simplemente Developer ID Application: Your Name sin equipo.
Automatizar la firma en CI/CD (Github Actions)
También es posible almacenar sus certificados y credenciales de notarización como Secretos de Action y firmar su código durante las compilaciones de CI.
- Github Actions
- Azure DevOps
-
Abra Acceso a Llaveros y abra el panel "Mis Certificados".
-
Seleccione cada certificado (uno a la vez), haga clic derecho y seleccione "Exportar". Guárdelo como archivo p12 y anote la contraseña. Puede usar la misma contraseña para ambos certificados.
tipSi no puede ver la opción de exportar, o exportar como
.p12está deshabilitado, es posible que necesite cambiar qué llavero o pestaña está viendo. Debe estar en la pestaña "Mis Certificados". Consulte https://stackoverflow.com/questions/15662377/unable-to-export-apple-production-push-ssl-certificate-in-p12-format para más información. -
Copie el contenido del certificado al portapapeles en base64, por ejemplo:
base64 -i CERT.p12 | pbcopy -
Cree 7 Secretos de Github para sus flujos de trabajo de Actions
BUILD_CERTIFICATE_BASE64(b64 de su certificado de aplicación)INSTALLER_CERTIFICATE_BASE64(b64 de su certificado de instalador)P12_PASSWORD(contraseña para los certificados)APPLE_ID(su nombre de usuario de Apple)APPLE_PASSWORD(su contraseña específica de la aplicación del paso de notarización anterior)APPLE_TEAM(su ID de equipo del paso de notarización anterior)KEYCHAIN_PASSWORD(puede ser cualquier cadena aleatoria, se usará para crear un nuevo llavero)
-
Agregue un paso a su flujo de trabajo que instale los certificados y el perfil de llavero. Aquí hay un ejemplo:
name: App build & signon: pushjobs:build_with_signing:runs-on: macos-lateststeps:- name: Checkout repositoryuses: actions/checkout@v4- name: Install Apple certificates and notary profileenv:BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}INSTALLER_CERTIFICATE_BASE64: ${{ secrets.INSTALLER_CERTIFICATE_BASE64 }}P12_PASSWORD: ${{ secrets.P12_PASSWORD }}APPLE_ID: ${{ secrets.APPLE_ID }}APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}APPLE_TEAM: ${{ secrets.APPLE_TEAM }}KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}run: |# create variables for file pathsCERT_BUILD_PATH=$RUNNER_TEMP/build_certificate.p12CERT_INSTALLER_PATH=$RUNNER_TEMP/installer_certificate.p12KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db# import certificates from secretsecho -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERT_BUILD_PATHecho -n "$INSTALLER_CERTIFICATE_BASE64" | base64 --decode -o $CERT_INSTALLER_PATH# create temporary keychainsecurity create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATHsecurity set-keychain-settings -lut 21600 $KEYCHAIN_PATHsecurity unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH# import certificates to keychainsecurity import $CERT_BUILD_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATHsecurity import $CERT_INSTALLER_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATHsecurity list-keychain -d user -s $KEYCHAIN_PATH# create notarytool profilexcrun notarytool store-credentials --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM" --password "$APPLE_PASSWORD" velopack-profile- name: Compile your app...- name: Create Velopack Releaserun: |dotnet tool install -g vpkvpk pack ... \--signAppIdentity "Developer ID Application: Your Name" \--signInstallIdentity "Developer ID Installer: Your Name" \--notaryProfile "velopack-profile" \--keychain $RUNNER_TEMP/app-signing.keychain-db# Or use dnx instead of installing globally:# - name: Create Velopack Release# run: |# dnx vpk --version 1.0.0 pack ... \# --signAppIdentity "Developer ID Application: Your Name" \# --signInstallIdentity "Developer ID Installer: Your Name" \# --notaryProfile "velopack-profile" \# --keychain $RUNNER_TEMP/app-signing.keychain-db# Replace 1.0.0 with your Velopack package version# Learn more: https://learn.microsoft.com/dotnet/core/tools/dotnet-tool-exec?WT.mc_id=DT-MVP-5003472- name: Clean up keychainif: ${{ always() }}run: security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
La documentación aquí para Azure DevOps es proporcionada por la comunidad y no ha sido verificada por el equipo de Velopack.
-
Abra Acceso a Llaveros y abra el panel "Mis Certificados".
-
Seleccione cada certificado (uno a la vez), haga clic derecho y seleccione "Exportar". Guárdelo como archivo p12 y anote la contraseña. Puede usar la misma contraseña para ambos certificados.
tipSi no puede ver la opción de exportar, o exportar como
.p12está deshabilitado, es posible que necesite cambiar qué llavero o pestaña está viendo. Debe estar en la pestaña "Mis Certificados". Consulte https://stackoverflow.com/questions/15662377/unable-to-export-apple-production-push-ssl-certificate-in-p12-format para más información. -
Copie el contenido del certificado al portapapeles en base64, por ejemplo:
base64 -i CERT.p12 | pbcopy -
Cree 7 secretos en Azure Key Vault y expóngalos a Azure DevOps bajo el grupo de variables "Apple signing". Tenga en cuenta que usamos Key Vault en lugar de secretos de DevOps porque nuestros certificados son demasiado grandes (más de 4K) para almacenarlos en secretos de DevOps.
P12-PASSWORD(contraseña para los certificados)APPLE-ID(su nombre de usuario de Apple)APPLE-PASSWORD(su contraseña específica de la aplicación del paso de notarización anterior)APPLE-TEAM(su ID de equipo del paso de notarización anterior)KEYCHAIN-PASSWORD(puede ser cualquier cadena aleatoria, se usará para crear un nuevo llavero)BUILD-CERTIFICATE-BASE64(base64 de su certificado de aplicación)INSTALLER-CERTIFICATE-BASE64(base64 de su certificado de instalador)
-
Agregue pasos a su pipeline para cargar los secretos, firmar y limpiar:
El YAML para configurar:
variables:- group: Apple signingsteps:- bash: |# create variables for file pathsCERT_BUILD_PATH=$AGENT_TEMPDIRECTORY/build_certificate.p12CERT_INSTALLER_PATH=$AGENT_TEMPDIRECTORY/installer_certificate.p12KEYCHAIN_PATH=$AGENT_TEMPDIRECTORY/app-signing.keychain-db# import certificates from secretsecho -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERT_BUILD_PATHecho -n "$INSTALLER_CERTIFICATE_BASE64" | base64 --decode -o $CERT_INSTALLER_PATH# create temporary keychainsecurity create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATHsecurity set-keychain-settings -lut 21600 $KEYCHAIN_PATHsecurity unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH# import certificates to keychainsecurity import $CERT_BUILD_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATHsecurity import $CERT_INSTALLER_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATHsecurity list-keychain -d user -s $KEYCHAIN_PATH# create notarytool profilexcrun notarytool store-credentials --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM" --password "$APPLE_PASSWORD" --keychain $KEYCHAIN_PATH velopack-profileenv:BUILD_CERTIFICATE_BASE64: $(BUILD-CERTIFICATE-BASE64)INSTALLER_CERTIFICATE_BASE64: $(INSTALLER-CERTIFICATE-BASE64)P12_PASSWORD: $(P12-PASSWORD)APPLE_ID: $(APPLE-ID)APPLE_PASSWORD: $(APPLE-PASSWORD)APPLE_TEAM: $(APPLE-TEAM)KEYCHAIN_PASSWORD: $(KEYCHAIN-PASSWORD)displayName: 🛠️ Install Apple certs and notary profilePara limpiar:
- bash: security delete-keychain $AGENT_TEMPDIRECTORY/app-signing.keychain-dbdisplayName: 🧹 Clean up keychaincondition: always()Firmar en Mac (asumiendo un script de PowerShell):
# Add signing parametersif ($IsMacOS) {$vpkCommand += @('--signAppIdentity','Developer ID Application: Your Name','--signInstallIdentity','Developer ID Installer: Your Name','--notaryProfile','velopack-profile','--keychain','$(Agent.TempDirectory)/app-signing.keychain-db')}