Le module de brassage alphabétique est conçu pour une protection supplémentaire des informations secrètes transmises via un canal de communication. Bien que le cryptage de flux RC4 que nous utilisons dans Extra Systems Cypher Net ne présente aucune vulnérabilité dans notre implémentation, la possibilité théorique d'énumérer des clés avec une analyse lexicale ultérieure des tentatives de décryptage des informations transmises demeure. Nous ne parlons bien entendu pas des opportunités dont dispose aujourd’hui l’humanité. Pour les systèmes modernes, le temps nécessaire pour rechercher les clés RC4 dans notre cas est plusieurs fois plus long que la durée de vie de l’Univers. Nous parlons de ces possibilités hypothétiques qui pourraient apparaître dans le futur. Dans le but de nous assurer contre toutes les options imaginables, nous avons ajouté à Extra Systems Cypher Net ce module de brassage alphabétique, qui rend en principe impossible l'analyse lexicale des tentatives de décryptage, et prive ainsi un attaquant de toute possibilité de cracker ce système de communication crypté.
L'essence de cette méthode est que les codes de 256 caractères (le nombre d'options pour un octet de huit bits) sont déplacés de manière complètement aléatoire dans le tableau, de sorte que le texte dans n'importe quelle langue se transforme en charabia complet, composé de caractères imprimés et non imprimables mélangés de manière totalement imprévisible. En conséquence, la méthode de piratage par énumération par force brute des mots de passe de cryptage, dont l'essence est de rechercher des options lorsque le texte chiffré se transforme en un ensemble de certains caractères imprimés, perd complètement sa validité, puisque le mot de passe correct, avec notre approche, qui est décrite ici, se transforme, comme déjà indiqué, en abracadabra, qui ne peut en aucun cas être confondu avec du texte normal.
Ainsi, le cracker Extra Systems Cypher Net n'a pas la capacité de deviner le mot de passe, se concentrant sur l'obtention d'un texte significatif.
Initialement, le système crée une table qui correspond à la transformation d'identité (c'est-à-dire qu'il ne fait rien – il ne modifie pas les informations de codage des caractères). Le module shuffle_init fait ceci:
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; }
Ensuite, les informations de ce tableau sont mélangées de manière aléatoire (cette procédure peut, et même doit, être effectuée plusieurs fois). Ceci est fait par le module 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; }
L'application de cette clé dans le système Extra Systems Cypher Net est gérée par le module shuffle (notez que shuffle_decrypt_data est créé «à la volée» sur la base de shuffle_encrypt_data immédiatement après son chargement - ce fait garantit automatiquement une cohérence totale entre les algorithmes de codage et de décodage des informations transmises), dont le code en C est le suivant:
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); }
Grâce à ce réarrangement chaotique des lettres, l'attaquant est complètement privé de la capacité d'analyser le texte qu'il obtient en essayant de déchiffrer par force brute. Le fichier «shuffle.encrypt» est créé différemment pour chaque client et, de plus, chaque client, s'il le souhaite, est équipé du programme shuffle_randomize, à l'aide duquel il peut effectuer un certain nombre de permutations supplémentaires dans ce fichier de clé.
Le but des procédures shuffle_rotate_l et shuffle_rotate_r est d'éliminer les répétitions régulières des octets clés du codage UTF8 (qui se produisent lors de l'utilisation de toutes les langues sauf l'anglais - et ceci est particulièrement typique de l'alphabet cyrillique) - car cette circonstance pourrait servir d'indice pour sélectionner la clé RC4 en utilisant la méthode de la «force brute». Notre utilisation de ces procédures dans ce module élimine complètement un tel danger dans notre produit.
La procédure shuffle_swap résout un problème similaire : son travail consiste à échanger les bits dans les octets adjacents selon un certain masque (SHUFFLE_SWAP_STEP). Nous sélectionnons le type spécifique de ce masque en fonction du critère d'atteinte du niveau maximum d'entropie de la séquence finale d'octets (précédemment chiffrée par ce module). Nous utilisons différents masques pour différentes langues. Leur efficacité dépasse généralement 7,9 bits d’entropie par octet. Nous ne publions pas les valeurs spécifiques de ces masques de bits, car cela n'affecte pas la force cryptographique de notre système. Cette décision de notre part ne viole pas le principe de Kerkhoffs, puisque les codes des algorithmes sont entièrement publiés ici et que les valeurs spécifiques de SHUFFLE_SWAP_STEP ne font pas référence à des codes, mais plutôt à des données clés, que le principe de Kerkhoffs n'interdit à personne de garder secrètes.
Naturellement, toute paire (ou entreprise) d'abonnés communiquant entre eux via Extra Systems Cypher Net doit avoir un fichier «shuffle.encrypt» identique. Initialement, les abonnés reçoivent ces fichiers de notre part, mais, comme indiqué ci-dessus, ils peuvent les créer eux-mêmes et les mélanger. Il est seulement important que dans ce cas, pour garantir l'identité de tous les ensembles, ils les transfèrent physiquement à leurs partenaires (lors d'une réunion personnelle ou par l'intermédiaire d'un coursier de confiance).
Le contenu de cette page est également disponible en anglais, allemand, portugais, espagnol, italien, ukrainien et en russe.
© Extra Systems, 2024 |
|