Información general sobre el código fuente (Ejemplo CNG)

En esta tema se ofrece una descripción general de las interacciones entre los distintos elementos de código del ejemplo de comunicación segura de criptografía de próxima generación (CNG).

Se explican los aspectos siguientes del ejemplo:

  • Aplicaciones

  • Archivos

  • Clases

  • Versiones de seguridad

  • Información general de la sesión

  • Claves criptográficas (versiones 2 a 5)

  • Firmas digitales intercambiadas a través de un canal público (versión 3)

  • Firmas digitales intercambiadas a través de un canal privado (versión 4)

  • Finalización de la sesión (versión 5)

  • Notas adicionales

  • Limitaciones del ejemplo CNG

Aplicaciones

El ejemplo se compone de tres aplicaciones de consola independientes, Alice, Boby Mallory.Cada aplicación se compila en un proyecto diferente de Visual Studio y se compone de un archivo principal y tres archivos compartidos.En la tabla siguiente se muestran las aplicaciones y sus archivos.

Nombre de la aplicación (proyecto)

Archivos

Alice

  • Alice.cs (archivo principal)

  • Utilities.cs

  • ChannelManager.cs

  • Communicator.cs

Bob

  • Bob.cs (archivo principal)

  • Utilities.cs

  • ChannelManager.cs

  • Communicator.cs

Mallory

  • Mallory.cs (archivo principal)

  • Utilities.cs

  • ChannelManager.cs

  • Communicator.cs

Archivos

En las tablas de las secciones siguientes se resumen las clases y métodos que se utilizan en cada aplicación en el orden en el que aparecen en el código fuente.

Alice.cs, Bob.cs y Mallory.cs

Nombre de clase, método o

variable global

Hay que usar

CNG_SecureCommunicationExample

Clase parcial del nivel del proyecto.

MyColor

OtherColor

fDisplaySendMessage

Variables globales.

Main

Punto de entrada del programa de cada aplicación.Este método controla lo siguiente:

  • Cuando lo llama Alice, carga automáticamente Bob.exe y Mallory.exe.

  • Crea un bucle de procesamiento.

  • Llama al método InitConsole para establecer el tamaño, la posición y el título de la consola.

  • Llama al método Run.

Run

Método que llama al método InitializeOptions y crea el escenario de seguridad seleccionado.

Utilities.cs

Nombre de clase, método o

variable global

Hay que usar

CNG_SecureCommunicationExample

Clase parcial del nivel del proyecto.

Version

fVerbose

fMallory

Variables globales.

Autoloader

Método al que Alice llama para cargar las aplicaciones Bob.exe y Mallory.exe.

InitConsole

Método que controla los mensajes en el nivel de la aplicación y el menú de interfaz de usuario.

SplashScreen

Método que proporciona los títulos de ventana de la consola.

ReadALine

Método de utilidad que lee una línea escrita por el usuario en la consola.

ReadAChar

Método de utilidad que muestra una pregunta y solicita al usuario que responda sí o no.

InitializeOptions

Método que muestra las opciones y solicita al usuario que haga una selección.Este método también establece los marcadores globales Version, fVerbose y fMallory.

Display(string s)

El primero de los dos métodos Display.Este método pasa la cadena y la variable MyColor al segundo método Display.

Display(string DisplayString, int color)

El segundo de los dos métodos Display.Este método contiene las instrucciones Console.WriteLine y proporciona la compatibilidad de colores para las líneas de salida.

Para obtener más información sobre estas clases, métodos y variables, vea Análisis de código de las clases de utilidad (Ejemplo CNG).

ChannelManager.cs

Nombre de clase, método o

variable global

Utilice

CNG_SecureCommunicationExample

Clase parcial del nivel del proyecto.

AppControl

Método que proporciona el control sobre las aplicaciones internas y sincroniza las tres aplicaciones de consola.

Alice utiliza este método para enviar las opciones del programa (marcadores Version y fVerbose) a Bob y Mallory.

AppControl no es un método de mensajería.Su contenido no se cifra ni se firma.No llama a la clase Communicator.

SendChannelName

ReceiveChannelName

Métodos que se utilizan para cambiar de la canalización con nombre PublicChannel a las canalizaciones con nombre AliceAndBobChannel1 y AliceAndBobChannel.Estos métodos permiten la infracción de seguridad deliberada que se explica en la información general del ejemplo CNG.

ChannelManager

Clase que proporciona el marco de comunicación entre los procesos de la aplicación.

Para obtener más información sobre estas clases y métodos, vea Análisis de código de la clase ChannelManager (Ejemplo CNG).

Communicator.cs

Nombre de clase, método o

variable global

Utilice

CNG_SecureCommunicationExample

Clase parcial del nivel del proyecto.

Communicator

Clase que encapsula todas las funciones criptográficas.Esta clase procesa todos los mensajes entre Alice, Bob y Mallory.No procesa mensajes enviados por el método ChannelManagerAppControl.

m_DSKey

m_ECDH_Cng

m_ECDH_local_publicKey_XML

m_ECDH_remote_publicKey

ChMgr

Variables de clase.

Communicator

Método que construye un objeto Communicator.

Dispose

Método que libera los recursos retenidos de forma privada.

StoreDSKey

Método que almacena una clave de firma digital.

Send_or_Receive_PublicCryptoKey

Método que proporciona compatibilidad para el intercambio de claves.

iv

ciphertext

signature

Variables de clases privadas que se utilizan para cifrar mensajes de texto simple.Estas variables se declaran cerca del método ReceiveMessage().

ReceiveMessage

Método que recibe los mensajes de texto simple o cifrados, en función de la versión de seguridad.

SendMessage

Método que acepta un mensaje de texto simple y lo manda en formato de texto simple o cifrado, en función de la versión de seguridad.

Para obtener más información sobre estas clases, métodos y variables, vea Análisis de código de la clase Communicator (Ejemplo CNG).

Clases

Cada proyecto contiene tres clases:

  • public partial class CNG_SecureCommunicationExample

    Esta clase se extiende por los cuatro archivos del proyecto incluidos en las aplicaciones Alice, Bob y Mallory.Después de la compilación, la clase CNG_SecureCommunicationExample contiene todas las clases, variables y métodos de los cuatro archivos del proyecto.Para obtener más información acerca de las clases parciales, vea Clases y métodos parciales (Guía de programación de C#).

  • internal sealed class ChannelManager

    Esta clase proporciona compatibilidad con las canalizaciones con nombre.Cada proyecto crea varias instancias de ChannelManager en diferentes momentos durante la ejecución del programa.Puede encontrar información detallada de esta clase en Análisis de código de la clase ChannelManager (Ejemplo CNG).

  • internal sealed class Communicator

    Esta clase proporciona compatibilidad de cifrado y descifrado.Cada proyecto crea varias instancias de Communicator en diferentes momentos durante la ejecución del programa.Puede encontrar información detallada de esta clase en Análisis de código de la clase Communicator (Ejemplo CNG).

Versiones de seguridad

El código fuente admite el escenario de seguridad que se presenta en la información general del ejemplo CNG.Implementa las cinco versiones siguientes, que representan cinco niveles de seguridad, de la herramienta de mensajería instantánea (IM):

  • Versión 1: Utiliza mensajes de texto simple y canalizaciones con nombre.

  • Versión 2: Utiliza mensajes cifrados.

  • Versión 3: Utiliza mensajes cifrados y firmas digitales.

  • Versión 4: Utiliza mensajes cifrados y una firma digital privada.

  • Versión 5: Finaliza la aplicación cuando se producen errores de seguridad.

Nota

De aquí en adelante en este tema, se hará referencia a estas versiones por su número.Asimismo, en función del contexto, los nombres "Alice", "Bob" y "Mallory" pueden hacer referencia a las tres personas implicadas en el escenario del ejemplo o a las tres aplicaciones de Visual Studio.

Información general de la sesión

Alice, Bob y Mallory tienen cada uno un método Main y un método Run.

El método Main sincroniza las aplicaciones y realiza las funciones siguientes:

  • Muestra una pantalla de presentación de inicio.

  • Pide al usuario que elija las opciones de sesión (solo Alice).

  • Envía las opciones de sesión a Bob y Mallory (solo Alice).

  • Recibe las opciones de sesión de Alice (solo Bob y Mallory).

  • Llama al método Run para realizar la sesión de seguridad solicitada.

El método Run ejecuta escenarios de seguridad.

  • En cada sesión se muestra una de las versiones enumeradas en la sección anterior.

  • Una sesión se inicia cuando Alice, Bob y Mallory introducen sus métodos Run y finaliza cuando vuelven a sus métodos Main.

  • Alice, Bob y Mallory ejecutan siempre la misma versión durante una sesión.

  • Alice inicia todas las transacciones que tienen lugar durante una sesión.Mallory responde a Alice e inicia las transacciones con Bob.Bob simplemente responde.

El código fuente de Alice y Bob es muy similar.La principal diferencia es que Alice inicia cada sesión y actúa como servidor de la canalización, mientras que Bob actúa como cliente.El código de Mallory es más complejo porque administra dos canalizaciones independientes: una con Alice y otra con Bob.

Método principal

Alice llama al método InitializeOptions al inicio de su método Main y recibe las opciones de la sesión (Version, fVerbose, fMallory) del usuario.Utiliza su método AppControl para enviar las opciones a Bob y Mallory, que las reciben a través de sus métodos AppControl.Si el usuario decide cerrar la aplicación escribiendo la letra "x", el método AppControl de Alice envía la cadena "exit" a Bob y Mallory en lugar de las opciones de sesión.

Una vez que las tres aplicaciones han recibido las opciones de sesión, llaman a sus métodos Run.

Método Run

Alice, Bob y Mallory ejecutan la sesión solicitada siguiendo estos pasos:

  1. Alice llama el método SendChannelName, que utiliza un canal denominado PublicChannel.Envía a Bob un nuevo nombre de canal (AliceAndBobChannel).

  2. Si el marcador fMallory está establecido en true, Mallory realiza escuchas de PublicChannel e intercepta el nuevo nombre de canal (AliceAndBobChannel) de Alice.A continuación, envía a Bob un nombre de canal diferente (AliceAndBobChannel1).

  3. Alice y Bob crean objetos Communicator con el mismo nombre.Estos objetos se crean dentro de las instrucciones using de C# y se eliminan al final del método Run.

    Alice se inicializa como un servidor de canalización:

    using (Communicator Alice = new Communicator("server", NewChannelName))
    

    Bob se inicializa como un cliente de la canalización:

    using (Communicator Bob = new Communicator("client", NewChannelName))
    

    Mallory crea dos objetos Communicator, MalloryAlice y MalloryBob.Mallory se inicializa como cliente de la canalización con Alice:

    using (Communicator MalloryAlice = new Communicator("client", AliceChannelName))
    

    Mallory se inicializa como servidor de la canalización con Bob:

    using (Communicator MalloryBob = new Communicator("server", BobChannelName"))
    
  4. El constructor de clases Communicator acepta el nombre del canal y crea un objeto ChannelManager público de larga duración denominado ChMgr:

    ChMgr = new ChannelManager(mode, ChannelName);
    
  5. El constructor ChannelManager acepta el nombre del canal y crea una canalización con el nombre correspondiente.

    Nota

    En este punto, Alice y Mallory se comunican a través de una canalización denominada AliceAndBobChannel, mientras que Mallory y Bob se comunican a través de una canalización denominada AliceAndBobChannel1.

    AliceAndBobChannel y AliceAndBobChannel1 son canales de larga duración que permanecen abiertos hasta el final del escenario de seguridad (es decir, hasta el final del método Run).

  6. Los valores del marcador fVersion (que controla la versión de seguridad) y el marcador fMallory (que controla la implicación de Mallory) determinan lo que ocurrirá a continuación:

    En la versión 3, Alice envía una clave de firma digital a Bob a través de PublicChannel.Utilizan esta clave de firma digital para firmar claves y mensajes.Si fMallory es true, Mallory intercepta la clave de firma digital y la utiliza para firmar las claves y los mensajes que envía a Alice y Bob.

    En las versiones 4 y 5, Alice envía dos claves de firma digital a Bob.La clave 1 de la firma digital es la misma clave que Alice envió en la versión 3.La clave 2 de la firma digital es una clave de firma digital secreta que Mallory no conoce.

  7. Alice y Bob intercambian claves criptográficas públicas para las versiones 2 a 5.Si fMallory es true, Mallory intercepta sus claves públicas y las sustituye por sus propias claves.

  8. Alice y Bob intercambian mensajes.Si fMallory es true, Mallory intercepta, cambia y reenvía los mensajes de Alice y Bob.

  9. Una vez que Alice y Bob terminan la comunicación entre ellos, se le pedirá que envíe sus propios mensajes.De esta forma, podrá ver el modo en que se cifran sus mensajes y qué hace Mallory para modificarlos.Cuando termine, presione ENTRAR para transferir el control de nuevo a Alice.

  10. Alice finaliza la sesión.Los métodos Run de Alice, Bob y Mallory devuelven el control a sus métodos Main y el ejemplo se reinicia.

Claves criptográficas (versiones 2 a 5)

Las versiones 2 a 5 cifran los mensajes utilizando el algoritmo del estándar de cifrado avanzado (AES).El intercambio de claves criptográficas se implementa en los métodos Run de Alice, Bob y Mallory después de la instrucción de código siguiente:

if (2 <= Version)

El objeto ChannelManager público de larga duración (ChMgr) que creó el constructor de clases Communicator envía la clave criptográfica.

Las dos instrucciones de código siguientes muestran cómo Alice envía la clave criptográfica y Bob la recibe:

Alice.Send_or_Receive_PublicCryptoKey("send", MyColor);
Bob.Send_or_Receive_PublicCryptoKey("receive", OtherColor);

El segundo parámetro define el color que la aplicación receptora deberá utilizar cuando muestre el contenido de la clave criptográfica.

Se considera que matemáticamente es poco factible interrumpir las implementaciones de AES.Sin embargo, AES no ofrece protección contra un ataque de tipo "Man in the middle".Puede parecer contradictorio que Mallory puede descifrar los mensajes de Alice y Bob cuando AES proporciona este tipo de cifrado de alta seguridad.Esto es posible porque Mallory tiene acuerdos confidenciales que comparte con Alice y Bob.La interceptación y sustitución de claves de Mallory hace que el cifrado de AES de alta seguridad sea poco útil.

Si se utilizan claves criptográficas sin autenticación, se obtiene una falsa apariencia de seguridad.Alice y Bob creen que tienen un esquema de transmisión de mensajes seguro con la versión 2.De hecho, se pone en peligro la seguridad antes de enviar su primer mensaje.

La compañía de Alice y Bob no sabe si los ataques proceden del interior o del exterior de la empresa.Diseñan la versión 3 de la herramienta IM para detectar el origen de los ataques.

Firmas digitales intercambiadas a través de un canal público (versión 3)

La versión 3 intenta corregir el error de seguridad de la versión 2 utilizando una firma digital para firmar las claves y los mensajes.El intercambio de claves de firma digital se implementa en los métodos Run de Alice, Bob y Mallory después de la instrucción de código siguiente:

if (3 <= Version)

La clave de firma digital se envía a través del mismo canal público de larga duración que el de las claves criptográficas.El código siguiente es responsable de enviar la clave de firma digital:

Alice.ChMgr.SendMessage(dsKeyBlob);

Nota

La instancia de ChannelManager (ChMgr) que envía la clave de firma digital es miembro del objeto Communicator de Alice.

Alice y Bob almacenan la clave de firma digital como miembro privado de sus objetos Communicator:

Alice.StoreDSKey(DSKey);
Bob.StoreDSKey(DSKey);

Desgraciadamente, Mallory copia fácilmente la firma digital de PublicChannel y la guarda:

Mallory.StoreDSKey(DSKey);

Cuando Alice y Bob reciben mensajes firmados entre ellos, las firmas digitales coinciden perfectamente con los mensajes.Esto se debe a que Mallory los firmó con la misma clave de firma digital que utilizaron Alice y Bob.

En la versión 3, las claves criptográficas y la firma digital se intercambian en un canal público a través de la red corporativa.La compañía en la que Alice y Bob trabajan sospecha que alguien de dentro de la compañía esta realizando los robos.La compañía crea la versión 4 para comprobar esta tesis.

Firmas digitales intercambiadas a través de un canal privado (versión 4)

La versión 4 utiliza dos claves de firma digital: la clave que se utilizó en la versión 3 y una segunda clave confidencial que se envía a través de un canal privado.La primera clave se utiliza ahora como una clave digital falsa para atrapar al ladrón.Alice y Bob utilizan la segunda clave para firmar digitalmente sus claves criptográficas y sus mensajes.

La versión 4 del software IM únicamente se proporciona a Alice y Bob.Mallory sigue usando la versión 3.Por tanto, Mallory nunca descubre que la firma digital que usa no es válida.Sin embargo, la herramienta IM de Alice y Bob muestra una advertencia de seguridad por cada clave y mensaje que recibe.

La versión 4 también muestra que se están interceptando claves criptográficas y mensajes.Esto indica que se está produciendo un ataque de tipo "Man in the middle" y que este ataque se inicia antes incluso de que se envíen las claves criptográficas.Por consiguiente, un empleado de la compañía que tiene el acceso al objeto PublicChannel corporativo debe estar iniciando sesión antes que Bob.Un uso hábil de la clave de firma digital confidencial revela las actividades secretas de Mallory.

La transmisión de claves de firma digital confidenciales se implementa en los métodos Run de Alice y Bob después de la instrucción de código siguiente:

if (4 <= Version)

Las instrucciones de código siguientes son responsables de crear instancias del objeto ChannelManager privado de Alice y Bob:

ChannelManager ChMgr2 = new ChannelManager("server", "PrivateChannel")
ChannelManager ChMgr2 = new ChannelManager("client", "PrivateChannel")

El canal privado que Alice y Bob utilizan (ChMgr2) no es miembro de sus objetos Communicator.Puede verlo si compara las dos instrucciones de código siguientes:

Alice.ChMgr.SendMessage(dsKeyBlob); // Public channel - fake key
ChMgr2.SendMessage(dsKeyBlob);      // Private channel - real key

La primera instrucción utiliza la instancia de ChannelManager de larga duración (ChMgr) que se crea al comienzo del método Run.Esta instancia se mantiene como un miembro público de los objetos Communicator de Alice, Bob y Mallory (vea el paso 3 de la sección Información general de la sesión ) hasta el final de la sesión.La segunda instrucción utiliza un objeto temporal que solo existe el tiempo suficiente para enviar y recibir la clave.Este objeto se elimina inmediatamente después de su uso.

Una vez que Alice envía la clave de firma digital confidencial, Bob la recibe utilizando la siguiente instrucción:

DSKey = ChMgr2.ReadMessage();

Alice y Bob almacenan la clave como miembro privado de sus objetos Communicator:

Alice.StoreDSKey(DSKey);
Bob.StoreDSKey(DSKey);

Estas instrucciones también sobrescriben la clave de firma digital falsa.

En la versión 4, Alice y Bob utilizan la clave de firma digital confidencial en lugar de la clave de firma digital falsa para firmar claves y mensajes.En la versión 4 también se firman las claves criptográficas y se muestran las advertencias de seguridad cada vez que la firma digital de un mensaje no coincide con el mensaje.

Finalización de la sesión (versión 5)

La versión 5 es idéntica a la versión 4, salvo porque finaliza la sesión tras el primer error.Alice experimenta el primer error cuando recibe la clave criptográfica pública de Bob y detecta una firma digital no válida.Bob experimenta el primer error cuando recibe la clave criptográfica pública de Alice y también detecta una firma digital no válida.

Notas adicionales

  • Eliminación de objetos: Las instrucciones using de C# proporcionan mayor seguridad.Se utilizan para abarcar a todos los objetos Communicator y ChannelManager.Cuando estos objetos salen del ámbito, se llama inmediatamente a sus métodos Dispose y se liberan todos los recursos retenidos internamente.

  • Métodos de codificación : Siempre que se transmiten datos cifrados, debe codificarlos como UTF8 o Unicode, pero nunca como ASCII.

Limitaciones del ejemplo CNG

El objetivo del ejemplo de comunicaciones seguras de CNG es demostrar las funciones administradas de CNG.Por ello, se ha omitido cierta funcionalidad, incluida la siguiente:

  • Validación de parámetros de todos los métodos.

  • Uso extensivo de bloques try/catch.

  • Detección de desconexión de canalizaciones sólidas.

  • Registro de la salida a pantalla en un archivo.

  • Configurabilidad dinámica del algoritmo de cifrado.

  • Configurabilidad dinámica del algoritmo de firma digital.

  • Un mecanismo distinto para transmitir la clave de firma digital a Bob.El objeto PrivateChannel de la canalización con nombre podría constituir una solución sencilla, aunque existen otros métodos más sofisticados.

  • Persistencia, almacenamiento y recuperación de claves

  • Uso de claves de firma digital generadas por el sistema operativo.

  • Uso de claves proporcionadas por una infraestructura de clave pública (PKI).

Estas características implican una complejidad de código adicional y están fuera del ámbito de este ejemplo.

Vea también

Conceptos

Ejemplo de comunicación segura de criptografía de próxima generación (CNG)

Intercambio de mensajes y claves paso a paso (Ejemplo CNG)

Resultado esperado (Ejemplo CNG)