O módulo de embaralhamento alfabético foi concebido para uma proteção adicional de informações secretas transmitidas através de um canal de comunicação. Embora a encriptação de fluxo RC4 que utilizamos nos Extra Systems Cypher Net não apresente vulnerabilidades na nossa implementação, mantém-se a possibilidade teórica de enumeração de chaves com posterior análise lexical das tentativas de desencriptação da informação transmitida. É claro que não estamos a falar das oportunidades que a humanidade tem hoje. Para os sistemas modernos, o tempo para procurar chaves RC4 no nosso caso é muitas ordens de grandeza superior ao tempo de vida do Universo. Estamos a falar daquelas possibilidades hipotéticas que podem surgir no futuro. Com a intenção de nos protegermos contra quaisquer opções concebíveis, adicionámos ao Extra Systems Cypher Net este módulo de embaralhamento do alfabeto, que torna a análise lexical das tentativas de desencriptação, em princípio, impossível e, portanto, priva um atacante de qualquer oportunidade de quebrar este sistema de comunicação encriptado.
A essência deste método é que os códigos de 256 caracteres (o número de opções para um byte de oito bits) são movidos de forma completamente aleatória na tabela, de modo que o texto em qualquer língua se transforma num jargão completo, consistindo em caracteres impressos e não imprimíveis misturados de uma forma completamente imprevisível. Com isto, o método de cracking por enumeração de força bruta de passwords encriptadas, cuja essência é procurar opções quando o texto cifrado se transforma num conjunto de determinados caracteres impressos, perde completamente a sua validade, pois a password correcta, com a nossa abordagem, aqui descrita, transforma-se, como já foi indicado, em abracadabra, que não pode de forma alguma ser confundida com texto normal.
Assim, o cracker Extra Systems Cypher Net não tem a capacidade de adivinhar a palavra-passe, concentrando-se em obter algum texto significativo.
Inicialmente, o sistema cria uma tabela que corresponde à transformação da identidade (ou seja, não faz nada - não altera a informação de codificação de caracteres). O módulo shuffle_init faz isso:
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; }
De seguida, a informação desta tabela é baralhada aleatoriamente (este procedimento pode, e até deve, ser feito mais do que uma vez). Isto é feito pelo 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; }
A aplicação desta chave no sistema Extra Systems Cypher Net é feita pelo módulo shuffle (note-se que o shuffle_decrypt_data é criado “on the fly” com base no shuffle_encrypt_data imediatamente após ser carregado - este facto garante automaticamente uma total consistência entre os algoritmos de codificação e descodificação da informação transmitida), cujo código em C é o seguinte:
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); }
Graças a este rearranjo caótico de letras, o atacante fica completamente privado da capacidade de analisar o texto que obtém ao tentar desencriptar pelo método de força bruta. O ficheiro "shuffle. encrypt" é criado para cada cliente de forma diferente e, além disso, cada cliente, se desejar, está equipado com o programa shuffle_randomize, com o qual pode fazer qualquer número de permutações adicionais neste ficheiro de chaves.
O objetivo dos procedimentos shuffle_rotate_l e shuffle_rotate_r é eliminar as repetições regulares de bytes de chave da codificação UTF8 (que ocorrem quando se utilizam todas as línguas, exceto o inglês - e isto é especialmente típico para o alfabeto cirílico) - uma vez que esta circunstância poderia servir de pista para selecionar a chave RC4 utilizando o método da “força bruta”. A utilização destes procedimentos neste módulo elimina completamente este perigo no nosso produto.
O procedimento shuffle_swap resolve um problema semelhante - a sua função é trocar bits em bytes adjacentes de acordo com uma determinada máscara (SHUFFLE_SWAP_STEP). Selecionámos o tipo específico desta máscara com base no critério de atingir o nível máximo de entropia da sequência final de bytes (previamente encriptada por este módulo). Utilizamos máscaras diferentes para diferentes idiomas. A sua eficiência excede normalmente 7,9 bits de entropia por byte. Não publicamos os valores específicos destas máscaras de bits, uma vez que isso não afeta a força criptográfica do nosso sistema. Esta nossa decisão não viola o princípio de Kerkhoffs, uma vez que os códigos dos algoritmos são aqui publicados na íntegra, e os valores específicos de SHUFFLE_SWAP_STEP não se referem a códigos, mas sim a dados-chave, que o princípio de Kerkhoffs não proíbe ninguém de guardar segredo.
Naturalmente, qualquer par (ou empresa) de subscritores que comunique através do Extra Systems Cypher Net deve ter um ficheiro “shuffle.encrypt” idêntico. Inicialmente, os subscritores recebem estes ficheiros de nós, mas, como mencionado acima, podem eles próprios criá-los e baralhá-los adicionalmente. É apenas importante que neste caso, para garantir a identidade de todos os conjuntos, os transfiram fisicamente para os seus parceiros (em reunião pessoal ou através de um transportador de confiança).
O conteúdo desta página está também disponível em inglês, francês, alemão, espanhol, italiano, ucraniano e russo.
© Extra Systems, 2024 |
|