El módulo de reproducción aleatoria de alfabetos está diseñado para una protección adicional de la información secreta transmitida a través de un canal de comunicación. Aunque el cifrado de flujo RC4 que utilizamos en Extra Systems Cypher Net no tiene vulnerabilidades en nuestra implementación, permanece la posibilidad teórica de enumerar claves con el posterior análisis léxico de los intentos de descifrar la información transmitida. Por supuesto, no estamos hablando de las oportunidades que tiene la humanidad hoy. Para los sistemas modernos, el tiempo para buscar claves RC4 en nuestro caso es muchos órdenes de magnitud más largo que la vida útil del Universo. Hablamos de aquellas hipotéticas posibilidades que puedan aparecer en el futuro. Con la intención de asegurarnos contra cualquier opción imaginable, agregamos a Extra Systems Cypher Net este módulo de mezcla alfabética, que hace que el análisis léxico de los intentos de descifrado sea en principio imposible y, por lo tanto, priva a un atacante de cualquier oportunidad de descifrar este sistema de comunicación cifrado.
La esencia de este método es que los códigos de 256 caracteres (el número de opciones para un byte de ocho bits) se mueven de forma completamente aleatoria en la tabla, de modo que el texto en cualquier idioma se convierte en un completo galimatías, que consiste en caracteres impresos y no imprimibles mezclados de forma completamente impredecible. Como resultado de esto, el método de descifrado mediante enumeración por fuerza bruta de contraseñas cifradas, cuya esencia es buscar opciones cuando el texto cifrado se convierte en un conjunto de ciertos caracteres impresos, pierde por completo su validez, ya que la contraseña correcta, con nuestro enfoque, que se describe aquí, se convierte, como ya se indicó, en abracadabra, que de ninguna manera puede confundirse con un texto normal.
Por lo tanto, el cracker Cypher Net de Extra Systems no tiene la capacidad de adivinar la contraseña, centrándose en obtener un texto significativo.
Inicialmente, el sistema crea una tabla que corresponde a la transformación de identidad (es decir, no hace nada, no cambia la información de codificación de caracteres). El módulo shuffle_init hace esto:
int main(void) { int i,file_handle; unsigned char data[256]; for (i=0; i<256; i++) data[i] = i; file_handle = creat("shuffle.encrypt", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); write(file_handle, data, sizeof(data)); close(file_handle); return 0; }
Luego, la información de esta tabla se baraja aleatoriamente (este procedimiento puede, e incluso debe, realizarse más de una vez). Esto lo hace el módulo shuffle_randomize:
int main(void) { unsigned char src, dst; unsigned char shuffle_encrypt_data[256]; unsigned char random_src[256], random_dst[256]; int i, file_handle; file_handle = open("shuffle.encrypt", O_RDONLY); read(file_handle, shuffle_encrypt_data, sizeof(shuffle_encrypt_data)); close(file_handle); fill_random_buffer(random_src, sizeof(random_src)); fill_random_buffer(random_dst, sizeof(random_dst)); for(i = 0; i < 256; i++) { src = shuffle_encrypt_data[random_src[i]]; dst = shuffle_encrypt_data[random_dst[i]]; shuffle_encrypt_data[random_src[i]] = dst; shuffle_encrypt_data[random_dst[i]] = src; } file_handle = creat("shuffle.encrypt", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); write(file_handle, shuffle_encrypt_data, sizeof(shuffle_encrypt_data)); close(file_handle); return 0; }
La aplicación de esta clave en el sistema Cypher Net de Extra Systems se maneja mediante el módulo shuffle (tenga en cuenta que shuffle_decrypt_data se crea "sobre la marcha" basándose en shuffle_encrypt_data inmediatamente después de su carga; este hecho garantiza automáticamente una coherencia total entre los algoritmos de codificación y decodificación de la información transmitida), cuyo código en C es el siguiente:
unsigned char shuffle_encrypt_data[256], shuffle_decrypt_data[256]; int load_shuffle_data(void) { unsigned char src; int i, file_handle; if((file_handle = open("shuffle.encrypt", O_RDONLY)) == -1) return 0; read(file_handle, shuffle_encrypt_data, sizeof(shuffle_encrypt_data)); close(file_handle); for(i = 0; i < 256; i++) { src = shuffle_encrypt_data[i]; shuffle_decrypt_data[src] = i; } return 1; } void shuffle_rotate_l(unsigned char *buffer_ptr, int buffer_len) { int i; unsigned char x; if (!buffer_len) return; x = buffer_ptr[0]; for(i = 0; i < (buffer_len - 1); i++) buffer_ptr[i] = (buffer_ptr[i] << 4) | (buffer_ptr[i + 1] >> 4); buffer_ptr[buffer_len - 1] = (buffer_ptr[buffer_len - 1] << 4) | (x >> 4); } void shuffle_rotate_r(unsigned char *buffer_ptr, int buffer_len) { int i; unsigned char x; if (!buffer_len) return; x = buffer_ptr[buffer_len - 1]; for(i = (buffer_len - 1); i > 0; i--) buffer_ptr[i] = (buffer_ptr[i] >> 4) | (buffer_ptr[i - 1] << 4); buffer_ptr[0] = (buffer_ptr[0] >> 4) | (x << 4); } void shuffle_twist(unsigned char *buffer_ptr, int buffer_len) { int i; unsigned char x, y; if (buffer_len < 2) return; for(i = 1; i < buffer_len; i++) { x = buffer_ptr[i - 1]; y = buffer_ptr[i]; buffer_ptr[i - 1] = (x & 0xF0) | (y >> 4); buffer_ptr[i] = (y & 0xF) | (x << 4); } } void shuffle_buffer(unsigned char *buffer_ptr, int buffer_len, unsigned char *shuffle_data) { short counter; for(counter = 0; counter < buffer_len; counter++) buffer_ptr[counter] = shuffle_data[buffer_ptr[counter]]; } void shuffle_swap_l(unsigned char *buffer_ptr, int buffer_len, unsigned char swap_old) { int i; unsigned char x, y, swap_new; if (buffer_len < 2) return; swap_new = ~swap_old; for(i = 1; i < buffer_len; i++) { x = buffer_ptr[i - 1]; y = buffer_ptr[i]; buffer_ptr[i - 1] = (x & swap_old) | (y & swap_new); buffer_ptr[i] = (y & swap_old) | (x & swap_new); } } void shuffle_swap_r(unsigned char *buffer_ptr, int buffer_len, unsigned char swap_old) { int i; unsigned char x, y, swap_new; if (buffer_len < 2) return; swap_new = ~swap_old; for(i = (buffer_len - 1); i > 0; i--) { x = buffer_ptr[i - 1]; y = buffer_ptr[i]; buffer_ptr[i - 1] = (x & swap_old) | (y & swap_new); buffer_ptr[i] = (y & swap_old) | (x & swap_new); } } void shuffle_encrypt_buffer(unsigned char *buffer_ptr, int buffer_len) { shuffle_buffer(buffer_ptr, buffer_len, shuffle_encrypt_data); shuffle_swap_l(buffer_ptr, buffer_len, SHUFFLE_SWAP_STEP_1); shuffle_buffer(buffer_ptr, buffer_len, shuffle_encrypt_data); shuffle_rotate_l(buffer_ptr, buffer_len); shuffle_buffer(buffer_ptr, buffer_len, shuffle_encrypt_data); shuffle_twist(buffer_ptr, buffer_len); shuffle_buffer(buffer_ptr, buffer_len, shuffle_encrypt_data); shuffle_swap_l(buffer_ptr, buffer_len, SHUFFLE_SWAP_STEP_2); shuffle_buffer(buffer_ptr, buffer_len, shuffle_encrypt_data); } void shuffle_decrypt_buffer(unsigned char *buffer_ptr, int buffer_len) { shuffle_buffer(buffer_ptr, buffer_len, shuffle_decrypt_data); shuffle_swap_r(buffer_ptr, buffer_len, SHUFFLE_SWAP_STEP_2); shuffle_buffer(buffer_ptr, buffer_len, shuffle_decrypt_data); shuffle_twist(buffer_ptr, buffer_len); shuffle_buffer(buffer_ptr, buffer_len, shuffle_decrypt_data); shuffle_rotate_r(buffer_ptr, buffer_len); shuffle_buffer(buffer_ptr, buffer_len, shuffle_decrypt_data); shuffle_swap_r(buffer_ptr, buffer_len, SHUFFLE_SWAP_STEP_1); shuffle_buffer(buffer_ptr, buffer_len, shuffle_decrypt_data); }
Gracias a esta caótica reordenación de las letras, el atacante queda completamente privado de la capacidad de analizar el texto que obtiene al intentar descifrarlo mediante el método de fuerza bruta. El archivo "shuffle.encrypt" se crea para cada cliente de forma diferente y, además, cada cliente, si lo desea, está equipado con el programa shuffle_randomize, con el que puede realizar cualquier cantidad de permutaciones adicionales en este archivo de clave.
El propósito de los procedimientos shuffle_rotate_l y shuffle_rotate_r es eliminar las repeticiones regulares de bytes clave de codificación UTF8 (que ocurren cuando se usan todos los idiomas excepto el inglés, y esto es especialmente típico del alfabeto cirílico), ya que esta circunstancia podría servir como pista para seleccionar la clave RC4 usando el método de "fuerza bruta". Nuestro uso de estos procedimientos en este módulo elimina por completo dicho peligro en nuestro producto.
El procedimiento shuffle_swap resuelve un problema similar: su trabajo es intercambiar bits en bytes adyacentes según una determinada máscara (SHUFFLE_SWAP_STEP). Seleccionamos el tipo específico de esta máscara en función del criterio de alcanzar el nivel máximo de entropía de la secuencia final de bytes (previamente cifrada por este módulo). Usamos diferentes máscaras para diferentes idiomas. Su eficiencia suele superar los 7,9 bits de entropía por byte. No publicamos los valores específicos de estas máscaras de bits, ya que esto no afecta la solidez criptográfica de nuestro sistema. Esta decisión nuestra no viola el principio de Kerkhoffs, ya que los códigos de los algoritmos se publican íntegramente aquí, y los valores específicos de SHUFFLE_SWAP_STEP no se refieren a códigos, sino a datos clave, que el principio de Kerkhoffs no prohíbe a nadie mantener en secreto.
Naturalmente, cualquier par (o empresa) de suscriptores que se comuniquen entre sí a través de Extra Systems Cypher Net debe tener un archivo "shuffle.encrypt" idéntico. Inicialmente, los suscriptores reciben estos archivos de nuestra parte, pero, como se señaló anteriormente, pueden crearlos ellos mismos y, además, mezclarlos. Sólo es importante que en este caso, para asegurar la identidad de todos los conjuntos, los transfieran físicamente a sus socios (en una reunión personal o a través de un mensajero de confianza).
El contenido de esta página también está disponible en inglés, francés, alemán, portugués, italiano, ucraniano y ruso.
© Extra Systems, 2024 |
|