Salut Recuperer sur Foro Estudios Digtales Algorithme Seca2 Auteur du message FERES 24/09/02 Pour ce que je me suis informer ceci est l'algo utiliser par le Seca2 Je m'en suis mis jusqu'aux narines a l'analizer pour le tester J'aimerais partager cette information avec quelqu'un qui si entend plus que moi et qui pourrais me donner un coup de main En y jetant un coup d'oeil rapide il me semble que ces l'algo utiliser par Seca1 mais je n'en suis pas sur On va voir si on ressort quelque chose J'ai simplifier l'algorithme tous en maintenant son fonctionnement j'ai utiliser M_K_F pour verifier que l'algo continu a marcher comme l'original Il en est resorti un code source beaucoup plus simple et qui est equivalant a l'original. Le resultat est que maintenant on peut comprendre et dire que il est facile de voir la relation entre l' encryption et la desencryption et que la desencryption est le processus inverse de l'encryption Note: pour moi il est evident que l'algo se dessine originalement suivant les pas que je vais d'ecrire plus bas et que c'est pas son vraiment simple L'apparante complexite de l'algo decrit par John Mackdonald se doit au processus de reverse ingenering et qu'il a ete publier tel quel sans voir ce qu'il y avait au fond de cet algo. Description Dans cet algo il y a deux routines publiees la routine encrypt et la routine decrypt, pretendu une l'inverse de l'autre ces routines recevant comme premier parametre une clees de 16 bits puis le second parametre une de 8 bits codifie/decodifie La premiere chose que fontt ces routines sont de preparees la clee le processus est le meme dans chaque routine Cette preparation se base a obtenir a partir de la clee de 16 bit une nouvelle clee de 64 bit cette clee et celle utilisee pour encrypter/desencrypter Pour ceci dans le code plus bas la clee doit se situer dans les premier 16 bit d'un buffer de 80 bit la preparation de la clee utilisera les 64 bit restants du buffer Note: a partir de maintenant je nommerais 'clave' les 64 bits //----------------------------------------------- void encript(unsigned char *k,unsigned char *d) { prepara_clave(k);//a partir de 16bit, genere 64. k += 16; //note le commencement de la clee 64 bits. for(int i=0 ; i menor_que 16 ; ++ i) { //parcours les 64 bits de 4 en 4 nucleo(k, d); swap_4bytes(d); k += 4; } swap_4bytes(d); //casse l'ultime swap } //----------------------------------------------- void decript(unsigned char *k,unsigned char *d) { prepara_clave(k); //a partir de 16bit, genere 64. k += 80; //note le commencement de la clee 64 bits for(int i=0 ; i menor_que 16 ; ++ i) { //parcours les 64 bits de 4 en 4 k -= 4; nucleo(k, d); swap_4bytes(d); } swap_4bytes(d); //casse l'ultime swap } //----------------------------------------------- Comme vous pouvez le voir dans le code la preparation de la clee est indentique ( meme fonction ) dans chaque routines L'application de la clee est tres similere pour encrypter se recupere du debut de la clee jusqu'a la fin pour desencrypter de la fin de la clee jusqu'au debut Dans chaque cas il y a 16 iteracion et dans chaque iteration s'utilise 4bits de la clee On voit clairement qu'un processus et l'inverse de l'autre Autant pour encrypter que pour desencrypter dans chaque pas ça s'applique sur la sequence de 8bits ( DW ou CW respectivement) la fonction 'nucleo' et apres s'interchange les quatre bit haut et les quatre bit bas de la dite sequence (function swap_4bytes) Note: maintenant j'appelerais 'dato' les 8byts de la sequence CW ou DW La premiere chose qui attire l'attention c'est que la fonction 'nucleo' est la meme autant pour encrypter que pour desencrypter d'ou l'on peut deduire que la fonction 'nucleo' appliquer deux fois sur un 'dato' revient au meme 'dato' Si nucleo(A)=B alors nucleo(B)=A Mais dans chaque pas apres 'nucleo' se fait un swap ceci provoque que le dato evolue A1 -> A2-> A3 Ou bien si l'on dit que nucleo(A1)=B1 et swap(B1)=A2,...... ça donnerais A1->B1->A2->B2->A3->B3->A4->B4->,..... C'est a dire : paso 1: A1->B1->A2 paso 2: A2->B2->A3 ......... Comme dans le dernier pas il ne se fait pas le swap (plus concretement se fait et ce defait) l'operation se termine avec B16 (non avec A17) Donc au decrypt : nucleo(B16)=A16 et swap(A16)=B15,..... le chemin inverse jusqu'a A1 Si on met le code d'encrypt et decrypt a la suite l'un de l'autre (considerant prepare la clee) on voit que les 16 pas de decrypt sont exactement les memes pas que l'encrypt pris a l'envers //--------------------------------- for(i=0; i menor_que 16 ; ++ i) { nucleo(k, d); swap_4bytes(d); k += 4; } swap_4bytes(d); for(i=0 ; i menor_que 16 ; ++ i) { k -= 4; nucleo(k, d); swap_4bytes(d); } //--------------------------------- Voyons la fonction nucleo cette fonction transforme une donne de 8bit, utilisant une clee (une portion de clee) de quatre bit Plus concretement la fonction nucleo utilise les quatres bit haut de la donnee et les quatre bits de la clee pour modifier les quatre bits bas de la donnee La fonction clee ne modifie pas les quatre bits haut de la donnee //----------------------------------------------------- static void nucleo(unsigned char *k, unsigned char *d) { unsigned int D[4]; D[0] = T1[d[4] ^ k[0] ]; D[1] = T1[d[5] ^ k[1]]; D[2] = T1[d[6] ^ k[2]]; D[3] = T1[d[7] ^ k[3]]; D[0] ^= D[3]; D[2] = T2[SN(D[3])+D[2]]; D[3] ^= D[2]; D[1] = T2[SN(D[2])+D[1]]; D[2] ^= D[1]; D[0] = T2[SN(D[1])+D[0] ]; D[1] ^= D[0] ; D[3] = T1[SN(D[0] )+D[3]]; D[0] ^= D[3]; D[2] = T1[SN(D[3])+D[2]]; D[3] ^= D[2]; D[1] = T1[SN(D[2])+D[1]]; D[2] ^= D[1]; D[1] ^= D[0] ; d[0] ^= T2[D[1]]; d[1] ^= T2[D[3]]; d[2] ^= T2[D[0] ]; d[3] ^= T2[D[2]]; } //---------------------------------------------------- Comme l'on voit la fonction modifie seulement d[0]....... d[3] et le fait dans les quatres derniere instruction avec un xor Mais on sait que si XOR(A)=B donc XOR(B)=A et ceci est indispensable pour que la fonction clee soit reversible Si on reecrit la fonction nucleo ainsi: void nucleo(unsigned char *k, unsigned char *d) { d[0] ^= f1(k,d[4-7]); d[1] ^= f2(k,d[4-7]); d[2] ^= f3(k,d[4-7]); d[3] ^= f4(k,d[4-7]); } L'algorithme fonctionnera bien les fonctions encrypt et decrypt seront chacune l'inverse de l'autre independament de la nature des fonctions f1..f4 De ceci nous deduisons que le contenue de T1 etT2 nous importe peu ni si l'existence de ces tables est necessaire Quelque soit l'algo qui combine quatre bit de la clee et quatre bit de la donnee et obtient a partir de cela quatre autre bit est un processus pseudoaleatoire ( apparament aleatoire mais reproductible) aurait la meme effectivite et serait pratiquement inataquable Pour completer l'information j'ai copie les codes des fonctions auxiliaires //----------------------------------------------- #define SN(b) (((b shift_der 4)&15) | ((b shift_izq 4)&15)) static void prepara_clave(unsigned char * k) { int i, C; for(C=0 ; C menor_que 16 ; ++C ){ for(i=4;i-- { k[16] = k[0] ^ T1[k[15] ^ k[1] ^ C]; k += 1; } } } void swap_4bytes(unsigned char *d) { unsigned char temp[4]; memcpy(temp, d, 4); memcpy(d, d + 4, 4); memcpy(d + 4, temp, 4); } //----------------------------------------------- De plus a la fonction nucleo il faut ajouter un & 255 avant d'indexer les tables T1 etT2 ... T2[(SN(D[3])+D[2]) & 255]; ... T2[(SN(D[2])+D[1]) & 255]; ........ Avec ça ces codes sont parfaitement utilisable A partir du document original de john macdonnald ////////////////////////////////////////////////////// // DECLARACIONES ////////////////////////////////////////////////////// /* MODULO SECAES, desarrollado por: gabino gabinoes : Junio 2002. Modulo para encriptar y desencriptar a alta velocidad. Usa este módulo tal cual está, no realices ningún cambio sin comprobar cómo afecta a la velocidad. Compila con Visual C++ Usa las siguientes opciones de compilación: - Optimiza velocidad Maximize speed (por defecto en Release). - Inline expansion: Any Suitable (no la pone por defecto) - Excepcion handling: Disable (no la pone por defecto) */ #ifndef _SECAES_H_ #define _SECAES_H_ /*____________________________________________________________ rutina que inicializa tablas Llama a esta rutina una sola vez, al comienzo del programa. */ void initabs(); /*____________________________________________________________ rutina de encriptacion k=clave de 128 bits (16 bytes), no modifica la clave d=datos de 64 bits (8 bytes) (entrada y salida) ATENCION : el array que contine la clave debe tener un tamaño mínimo de 80 bytes, en los 16 primeros se situa la clave, el resto son usados por esta funcion. ATENCION : el array que contine la CW/DW debe tener un tamaño mínimo de 80 bytes, en los 8 primeros se situa la CW/DW, el resto son usados por esta funcion. unsigned char k[80] => clave primaria+secundaria unsigned char d[80] => en la llamada DW, tras el retorno CW */ void encript(unsigned char *k,unsigned char *d); /*____________________________________________________________ rutina de desencriptado k=clave de 128 bits (16 bytes), deja la clave intacta d=datos de 64 bits (8 bytes) (entrada y salida) ATENCION : el array que contine la clave debe tener un tamaño mínimo de 80 bytes, en los 16 primeros se situa la clave, el resto son usados por esta funcion. ATENCION : el array que contine CW/DW debe tener un tamaño mínimo de 80 bytes, en los 8 primeros se situa la CW/DW, el resto son usados por esta funcion. unsigned char k[80] => clave primaria+resundaria unsigned char d[80] => en la llamada CW, tras el retorno DW */ void decript(unsigned char *k,unsigned char *d); /*____________________________________________________________ rutina de encriptado doble k=clave de 128 bits (16 bytes), deja la clave intacta d=datos de 64 bits (8 bytes) (entrada y salida) ATENCION : el array que contine la clave debe tener un tamaño mínimo de 80 bytes, en los 16 primeros se situa la clave, el resto son usados por esta funcion. ATENCION : el array que contine la CW/DW debe tener un tamaño mínimo de 80 bytes, en los 8 primeros se situa la CW/DW, el resto son usados por esta funcion. unsigned char k[80] => clave primaria+resundaria unsigned char d[80] => en la llamada DW, tras el retorno CW */ void encript2(unsigned char *k,unsigned char *d); /*____________________________________________________________ rutina de desencriptado doble k=clave de 128 bits (16 bytes), deja la clave intacta d=datos de 64 bits (8 bytes) (entrada y salida) ATENCION : el array que contine la clave debe tener un tamaño mínimo de 80 bytes, en los 16 primeros se situa la clave, el resto son usados por esta funcion. ATENCION : el array que contine la CW/DW debe tener un tamaño mínimo de 80 bytes, en los 8 primeros se situa la CW/DW, el resto son usados por esta funcion. unsigned char k[80] => clave primaria+resundaria unsigned char d[80] => en la llamada CW, tras el retorno DW */ void decript2(unsigned char *k,unsigned char *d); #endif //_SECAES_H_ ////////////////////////////////////////////////////// // IMPLEMENTACION ////////////////////////////////////////////////////// #include "stdafx.h" #include "secaes.h" //--------------------------------------------------- // IMPLEMENTACION //SN solo se aplica sobre unsigned char //#define SN(b) ((b shift_der 4) | (b shift_izq 4)) #define SN(c) tab_sn[c] //no usado, de momento. void initabs() { } /* ATENCION: La funcion swap nibles (SN) usa una tabla de 256 bytes. Esto evita tener que usar los desplazamientos de bits, que son bastante lentos. Las tablas T1 y T2 se encuentrán aquí duplicadas. Es decir que cada tabla contine 512 bytes, siendo los primeros 256 bytes iguales a los siguientes 256. Esto se hace así para ahorrar operaciones & 0xFF] */ static const unsigned char tab_sn[]={ 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF }; //*/ static const unsigned char T1[]={ 0x2a,0xe1,0x0b,0x13,0x3e,0x6e,0x32,0x48, 0xd3,0x31,0x08,0x8c,0x8f,0x95,0xbd,0xd0, 0xe4,0x6d,0x50,0x81,0x20,0x30,0xbb,0x75, 0xf5,0xd4,0x7c,0x87,0x2c,0x4e,0xe8,0xf4, 0xbe,0x24,0x9e,0x4d,0x80,0x37,0xd2,0x5f, 0xdb,0x04,0x7a,0x3f,0x14,0x72,0x67,0x2d, 0xcd,0x15,0xa6,0x4c,0x2e,0x3b,0x0c,0x41, 0x62,0xfa,0xee,0x83,0x1e,0xa2,0x01,0x0e, 0x7f,0x59,0xc9,0xb9,0xc4,0x9d,0x9b,0x1b, 0x9c,0xca,0xaf,0x3c,0x73,0x1a,0x65,0xb1, 0x76,0x84,0x39,0x98,0xe9,0x53,0x94,0xba, 0x1d,0x29,0xcf,0xb4,0x0d,0x05,0x7d,0xd1, 0xd7,0x0a,0xa0,0x5c,0x91,0x71,0x92,0x88, 0xab,0x93,0x11,0x8a,0xd6,0x5a,0x77,0xb5, 0xc3,0x19,0xc1,0xc7,0x8e,0xf9,0xec,0x35, 0x4b,0xcc,0xd9,0x4a,0x18,0x23,0x9f,0x52, 0xdd,0xe3,0xad,0x7b,0x47,0x97,0x60,0x10, 0x43,0xef,0x07,0xa5,0x49,0xc6,0xb3,0x55, 0x28,0x51,0x5d,0x64,0x66,0xfc,0x44,0x42, 0xbc,0x26,0x09,0x74,0x6f,0xf7,0x6b,0x4f, 0x2f,0xf0,0xea,0xb8,0xae,0xf3,0x63,0x6a, 0x56,0xb2,0x02,0xd8,0x34,0xa4,0x00,0xe6, 0x58,0xeb,0xa3,0x82,0x85,0x45,0xe0,0x89, 0x7e,0xfd,0xf2,0x3a,0x36,0x57,0xff,0x06, 0x69,0x54,0x79,0x9a,0xb6,0x6c,0xdc,0x8b, 0xa7,0x1f,0x90,0x03,0x17,0x1c,0xed,0xd5, 0xaa,0x5e,0xfe,0xda,0x78,0xb0,0xbf,0x12, 0xa8,0x22,0x21,0x3d,0xc2,0xc0,0xb7,0xa9, 0xe7,0x33,0xfb,0xf1,0x70,0xe5,0x17,0x96, 0xf8,0x8d,0x46,0xa1,0x86,0xe2,0x40,0x38, 0xf6,0x68,0x25,0x16,0xac,0x61,0x27,0xcb, 0x5b,0xc8,0x2b,0x0f,0x99,0xde,0xce,0xc5, // repetimos 0x2a,0xe1,0x0b,0x13,0x3e,0x6e,0x32,0x48, 0xd3,0x31,0x08,0x8c,0x8f,0x95,0xbd,0xd0, 0xe4,0x6d,0x50,0x81,0x20,0x30,0xbb,0x75, 0xf5,0xd4,0x7c,0x87,0x2c,0x4e,0xe8,0xf4, 0xbe,0x24,0x9e,0x4d,0x80,0x37,0xd2,0x5f, 0xdb,0x04,0x7a,0x3f,0x14,0x72,0x67,0x2d, 0xcd,0x15,0xa6,0x4c,0x2e,0x3b,0x0c,0x41, 0x62,0xfa,0xee,0x83,0x1e,0xa2,0x01,0x0e, 0x7f,0x59,0xc9,0xb9,0xc4,0x9d,0x9b,0x1b, 0x9c,0xca,0xaf,0x3c,0x73,0x1a,0x65,0xb1, 0x76,0x84,0x39,0x98,0xe9,0x53,0x94,0xba, 0x1d,0x29,0xcf,0xb4,0x0d,0x05,0x7d,0xd1, 0xd7,0x0a,0xa0,0x5c,0x91,0x71,0x92,0x88, 0xab,0x93,0x11,0x8a,0xd6,0x5a,0x77,0xb5, 0xc3,0x19,0xc1,0xc7,0x8e,0xf9,0xec,0x35, 0x4b,0xcc,0xd9,0x4a,0x18,0x23,0x9f,0x52, 0xdd,0xe3,0xad,0x7b,0x47,0x97,0x60,0x10, 0x43,0xef,0x07,0xa5,0x49,0xc6,0xb3,0x55, 0x28,0x51,0x5d,0x64,0x66,0xfc,0x44,0x42, 0xbc,0x26,0x09,0x74,0x6f,0xf7,0x6b,0x4f, 0x2f,0xf0,0xea,0xb8,0xae,0xf3,0x63,0x6a, 0x56,0xb2,0x02,0xd8,0x34,0xa4,0x00,0xe6, 0x58,0xeb,0xa3,0x82,0x85,0x45,0xe0,0x89, 0x7e,0xfd,0xf2,0x3a,0x36,0x57,0xff,0x06, 0x69,0x54,0x79,0x9a,0xb6,0x6c,0xdc,0x8b, 0xa7,0x1f,0x90,0x03,0x17,0x1c,0xed,0xd5, 0xaa,0x5e,0xfe,0xda,0x78,0xb0,0xbf,0x12, 0xa8,0x22,0x21,0x3d,0xc2,0xc0,0xb7,0xa9, 0xe7,0x33,0xfb,0xf1,0x70,0xe5,0x17,0x96, 0xf8,0x8d,0x46,0xa1,0x86,0xe2,0x40,0x38, 0xf6,0x68,0x25,0x16,0xac,0x61,0x27,0xcb, 0x5b,0xc8,0x2b,0x0f,0x99,0xde,0xce,0xc5 }; static const unsigned char T2[]={ 0xbf,0x11,0x6d,0xfa,0x26,0x7f,0xf3,0xc8, 0x9e,0xdd,0x3f,0x16,0x97,0xbd,0x08,0x80, 0x51,0x42,0x93,0x49,0x5b,0x64,0x9b,0x25, 0xf5,0x0f,0x24,0x34,0x44,0xb8,0xee,0x2e, 0xda,0x8f,0x31,0xcc,0xc0,0x5e,0x8a,0x61, 0xa1,0x63,0xc7,0xb2,0x58,0x09,0x4d,0x46, 0x81,0x82,0x68,0x4b,0xf6,0xbc,0x9d,0x03, 0xac,0x91,0xe8,0x3d,0x94,0x37,0xa0,0xbb, 0xce,0xeb,0x98,0xd8,0x38,0x56,0xe9,0x6b, 0x28,0xfd,0x84,0xc6,0xcd,0x5f,0x6e,0xb6, 0x32,0xf7,0x0e,0xf1,0xf8,0x54,0xc1,0x53, 0xf0,0xa7,0x95,0x7b,0x19,0x21,0x23,0x7d, 0xe1,0xa9,0x75,0x3e,0xd6,0xed,0x8e,0x6f, 0xdb,0xb7,0x07,0x41,0x05,0x77,0xb4,0x2d, 0x45,0xdf,0x29,0x22,0x43,0x89,0x83,0xfc, 0xd5,0xa4,0x88,0xd1,0xf4,0x55,0x4f,0x78, 0x62,0x1e,0x1d,0xb9,0xe0,0x2f,0x01,0x13, 0x15,0xe6,0x17,0x6a,0x8d,0x0c,0x96,0x7e, 0x86,0x27,0xa6,0x0d,0xb5,0x73,0x71,0xaa, 0x36,0xd0,0x06,0x66,0xdc,0xb1,0x2a,0x5a, 0x72,0xbe,0x3a,0xc5,0x40,0x65,0x1b,0x02, 0x10,0x9f,0x3b,0xf9,0x2b,0x18,0x5c,0xd7, 0x12,0x47,0xef,0x1a,0x87,0xd2,0xc2,0x8b, 0x99,0x9c,0xd3,0x57,0xe4,0x76,0x67,0xca, 0x3c,0xfb,0x90,0x20,0x14,0x48,0xc9,0x60, 0xb0,0x70,0x4e,0xa2,0xad,0x35,0xea,0xc4, 0x74,0xcb,0x39,0xde,0xe7,0xd4,0xa3,0xa5, 0x04,0x92,0x8c,0xd9,0x7c,0x1c,0x7a,0xa8, 0x52,0x79,0xf2,0x33,0xba,0x1f,0x30,0x9a, 0x00,0x50,0x4c,0xff,0xe5,0xcf,0x59,0xc3, 0xe3,0x0a,0x85,0xb3,0xae,0xec,0x0b,0xfe, 0xe2,0xab,0x4a,0xaf,0x69,0x6c,0x2c,0x5d, // repetimos 0xbf,0x11,0x6d,0xfa,0x26,0x7f,0xf3,0xc8, 0x9e,0xdd,0x3f,0x16,0x97,0xbd,0x08,0x80, 0x51,0x42,0x93,0x49,0x5b,0x64,0x9b,0x25, 0xf5,0x0f,0x24,0x34,0x44,0xb8,0xee,0x2e, 0xda,0x8f,0x31,0xcc,0xc0,0x5e,0x8a,0x61, 0xa1,0x63,0xc7,0xb2,0x58,0x09,0x4d,0x46, 0x81,0x82,0x68,0x4b,0xf6,0xbc,0x9d,0x03, 0xac,0x91,0xe8,0x3d,0x94,0x37,0xa0,0xbb, 0xce,0xeb,0x98,0xd8,0x38,0x56,0xe9,0x6b, 0x28,0xfd,0x84,0xc6,0xcd,0x5f,0x6e,0xb6, 0x32,0xf7,0x0e,0xf1,0xf8,0x54,0xc1,0x53, 0xf0,0xa7,0x95,0x7b,0x19,0x21,0x23,0x7d, 0xe1,0xa9,0x75,0x3e,0xd6,0xed,0x8e,0x6f, 0xdb,0xb7,0x07,0x41,0x05,0x77,0xb4,0x2d, 0x45,0xdf,0x29,0x22,0x43,0x89,0x83,0xfc, 0xd5,0xa4,0x88,0xd1,0xf4,0x55,0x4f,0x78, 0x62,0x1e,0x1d,0xb9,0xe0,0x2f,0x01,0x13, 0x15,0xe6,0x17,0x6a,0x8d,0x0c,0x96,0x7e, 0x86,0x27,0xa6,0x0d,0xb5,0x73,0x71,0xaa, 0x36,0xd0,0x06,0x66,0xdc,0xb1,0x2a,0x5a, 0x72,0xbe,0x3a,0xc5,0x40,0x65,0x1b,0x02, 0x10,0x9f,0x3b,0xf9,0x2b,0x18,0x5c,0xd7, 0x12,0x47,0xef,0x1a,0x87,0xd2,0xc2,0x8b, 0x99,0x9c,0xd3,0x57,0xe4,0x76,0x67,0xca, 0x3c,0xfb,0x90,0x20,0x14,0x48,0xc9,0x60, 0xb0,0x70,0x4e,0xa2,0xad,0x35,0xea,0xc4, 0x74,0xcb,0x39,0xde,0xe7,0xd4,0xa3,0xa5, 0x04,0x92,0x8c,0xd9,0x7c,0x1c,0x7a,0xa8, 0x52,0x79,0xf2,0x33,0xba,0x1f,0x30,0x9a, 0x00,0x50,0x4c,0xff,0xe5,0xcf,0x59,0xc3, 0xe3,0x0a,0x85,0xb3,0xae,0xec,0x0b,0xfe, 0xe2,0xab,0x4a,0xaf,0x69,0x6c,0x2c,0x5d }; //--------------------------------------------------------- //Esto te va a parecer raro, pero así es más rápido, esta //curiosa division de funciones ayuda a la optimización que //hace Visual C++, V6 (no se ha probado con otras versiones) //--------------------------------------------------------- // modifica 4 bytes en D con 4 bytes de clave en k static unsigned int D[4]; static void fase() { D[0] ^= D[3]; D[3] ^= D[2] = T2[SN(D[3])+D[2]]; D[2] ^= D[1] = T2[SN(D[2])+D[1]]; D[1] ^= D[0] = T2[SN(D[1])+D[0]]; D[0] ^= D[3] = T1[SN(D[0])+D[3]]; D[3] ^= D[2] = T1[SN(D[3])+D[2]]; D[2] ^= D[1] = T1[SN(D[2])+D[1]]; D[1] ^= D[0]; } static void fase(unsigned char *k, unsigned int *D, unsigned char *d) { D[0] = T1[d[4] ^ k[0]]; D[1] = T1[d[5] ^ k[1]]; D[2] = T1[d[6] ^ k[2]]; D[3] = T1[d[7] ^ k[3]]; fase(); d[8] = d[0] ^ T2[D[1]]; d[9] = d[1] ^ T2[D[3]]; d[10] = d[2] ^ T2[D[0]]; d[11] = d[3] ^ T2[D[2]]; } static void fase(unsigned char *k,unsigned char *d) { fase(k, D, d); } //----------------------------------------------- //trabaja sobre un buffer de 80 bytes, usa la //clave de 16 bytes para generar otra de 64 static void prepara_clave(unsigned char * k) { int i, C; for(C = 0 ; C menor_que 16 ; ++C) { for(i=4;i-- { k[16] = k[0] ^ T1[k[15] ^ k[1] ^ C]; k += 1; } } } //----------------------------------------------- //funcion pública void encript(unsigned char *k,unsigned char *d) { int i; prepara_clave(k); k += 16; for(i=0 ; i menor_que 16 ; ++ i) { fase(k, d); k += 4; d += 4; } d -= 64; ((DWORD*)d)[0] = ((DWORD*)d)[0x11]; ((DWORD*)d)[1] = ((DWORD*)d)[0x10]; } //----------------------------------------------- //funcion pública void decript(unsigned char *k,unsigned char *d) { int i; prepara_clave(k); k += 80; for(i=0 ; i menor_que 16 ; ++ i) { k -= 4; fase(k, d); d += 4; } d -= 64; ((DWORD*)d)[0] = ((DWORD*)d)[0x11]; ((DWORD*)d)[1] = ((DWORD*)d)[0x10]; } //----------------------------------------------- //funcion pública void decript2(unsigned char *k,unsigned char *d) { int i; prepara_clave(k); //solo una vez ! k += 80; for(i=0 ; i menor_que 16 ; ++ i) { k -= 4; fase(k, d); d += 4; } d -= 64; ((DWORD*)d)[0] = ((DWORD*)d)[0x11]; ((DWORD*)d)[1] = ((DWORD*)d)[0x10]; k += 64; for(i=0 ; i menor_que 16 ; ++ i) { k -= 4; fase(k, d); d += 4; } d -= 64; ((DWORD*)d)[0] = ((DWORD*)d)[0x11]; ((DWORD*)d)[1] = ((DWORD*)d)[0x10]; } //----------------------------------------------- //funcion pública void encript2(unsigned char *k,unsigned char *d) { int i; prepara_clave(k); //solo una vez ! k += 16; for(i=0 ; i menor_que 16 ; ++ i) { fase(k, d); k += 4; d += 4; } d -= 64; ((DWORD*)d)[0] = ((DWORD*)d)[0x11]; ((DWORD*)d)[1] = ((DWORD*)d)[0x10]; k -= 64; for(i=0 ; i menor_que 16 ; ++ i) { fase(k, d); k += 4; d += 4; } d -= 64; ((DWORD*)d)[0] = ((DWORD*)d)[0x11]; ((DWORD*)d)[1] = ((DWORD*)d)[0x10]; } Traduit a la volee, des fois je me melange les pinceaux entre les deux langues Sorry A+ Mabuse