Demostración de actualización automática escrita en C++. Incluye el cargador, el cliente, el servidor y las herramientas de firma para entregar de forma segura actualizaciones automáticas para aplicaciones de escritorio Win32.
Las aplicaciones de escritorio nativas Win32 no tienen el lujo de contar con un administrador de paquetes integrado en el sistema para manejar las actualizaciones automáticas. Este marco proporciona una demostración práctica de cómo entregar y procesar actualizaciones de forma segura y eficiente.
Un sistema de actualización automática debe satisfacer los objetivos de seguridad de integridad y autenticidad. Este marco utiliza claves RSA de 4096 bits para firmar y verificar la firma SHA-256 para los datos de actualización. La clave pública está integrada en el binario del cliente para su verificación. Suponiendo que la entrega inicial del software se realiza a través de una fuente confiable, los únicos emisores válidos para las actualizaciones son aquellos con acceso a la clave privada.
Los datos de actualización se transmiten a través de UDP. El factor principal en esta decisión fue reducir la sobrecarga de memoria del servidor debido a las conexiones TCP (con una carga de CPU reducida como beneficio adicional). La sobrecarga de memoria esperada es aproximadamente:
(Update File Size) + (Max Connections) * 80 bytes
Los datos de actualización se almacenan directamente en la memoria para evitar el acceso al disco. El cliente y el servidor verifican la propiedad de la IP mediante el intercambio de tokens criptográficos de 64 bits. A cada conexión se le asigna una cantidad limitada de ancho de banda de red antes de limitarla. Cada dirección IP está limitada a un número máximo de conexiones simultáneas. Estas características mitigan una serie de ataques de red comunes:
La prevención de ataques de intermediario se basa en las garantías de autenticidad del sistema de actualización.
No es necesario ejecutar funciones criptográficas pesadas en el servidor (como en HTTPS), ya que la confidencialidad no es un objetivo de seguridad para las actualizaciones de software: los datos de actualización no son confidenciales.
No se realizan esfuerzos por parte del cliente para limitar la velocidad de descarga. La integración en su aplicación debe esforzarse por ajustar dinámicamente la velocidad de envío en función de los paquetes descartados y la latencia de la conexión.
La arquitectura del servidor de demostración se ejecuta en un único puerto/un único subproceso. Se podrían ejecutar varias instancias de servidor por subproceso en diferentes puertos o diferentes sistemas (cuya negociación se produciría en un equilibrador de carga al que el cliente se conectaría primero (para la entrega de actualizaciones a gran escala).
Los datos de actualización se envían para un único archivo tal cual. Si necesita soporte para parches de múltiples archivos, actualizaciones delta o compresión, debe entregar un ejecutable con las utilidades y los datos para manejar estas funciones (y desacoplarlo del propio sistema de actualización).
Las garantías de seguridad sólo son válidas mientras la clave privada permanezca segura. No se incluye ningún método de revocación de claves con el marco (ya que requeriría verificación externa y confianza de otro proveedor).
updater.sln
.Release
.client.dll
a update.dll
signtool.exe
para generar pub.h
, pub.key
, pri.key
y update.sig
.public_key
en client_updater.cpp
con el contenido del pub.h
generado.server.exe
y loader.exe
para demostrar la actualización.