IDEA算法c语言实现

原文:http://blog.csdn.net/sdccyong/article/details/6289410

[cpp]  view plain copy
  1. /* IDEA.h */  
  2. #ifndef IDEA_H  
  3. #define IDEA_H  
  4.   
  5. /* define return status */  
  6. #define IDEA_SUCCESS        0  
  7. #define IDEA_ERROR          1  
  8.   
  9. /* define data length */  
  10. #define IDEA_KEY_LEN        128  
  11. #define IDEA_BLOCK_SIZE     64  
  12. #define IDEA_SUB_BLOCK_SIZE 16  
  13.   
  14. /* define global variable */  
  15. #define IDEA_ADD_MODULAR    65536  
  16. #define IDEA_MP_MODULAR     65537  
  17.   
  18. /* define operation mode */  
  19. #define ECB 0  
  20. #define CBC 1  
  21. #define CFB 2  
  22. #define OFB 3  
  23.   
  24. /* define data type */  
  25. //typedef bool            bit_t, status_t;  
  26. typedef unsigned char   byte_t, uint8_t;  
  27. typedef unsigned short  word_t, uint16_t;  
  28. typedef unsigned int    dword_t, uint32_t, status_t;  
  29. typedef unsigned long long uint64_t;  
  30.   
  31. /* declare fuction */  
  32. status_t idea_encrypt(uint64_t plaintext, uint16_t key[8], uint64_t *ciphertext);  
  33. status_t idea_decrypt(uint64_t ciphertext, uint16_t key[8], uint64_t *plaintext);  
  34. status_t idea_round(uint16_t X[4], uint16_t Z[6], uint16_t out[4]);  
  35. status_t MA(uint16_t ma_in[2], uint16_t sub_key[2],uint16_t ma_out[2]);  
  36. status_t subkey_generation(uint16_t key[8], uint16_t sub_key[52]);  
  37. status_t subdkey_generation(uint16_t key[8], uint16_t sub_dkey[52]);  
  38. status_t extended_eucild(uint16_t d, uint32_t k, uint32_t *result);  
  39.   
  40. #endif  
[c-sharp]  view plain copy
  1. /* IDEA(International Data Encryption Algorithm), refer to http://www.quadibloc.com/crypto/co040302.htm 
  2.  * IDEA.c, an IDEA encryption and decryption program. 
  3.  * Author shenyang 
  4.  * Mar. 4th, 2011 
  5.  * TODO: Fault analysis on IDEA, defence of fault analysis on IDEA. 
  6.  */  
  7.  
  8. #ifndef IDEA_H  
  9. #include "IDEA.h"  
  10. #endif  
  11.  
  12. #include   
  13. #include   
  14.   
  15. /* define operation */  
  16. static uint16_t add_mod(uint16_t a, uint16_t b);  
  17. static uint16_t mp_mod(uint16_t a,uint16_t b);  
  18. static uint16_t XOR(uint16_t a, uint16_t b);  
  19. static status_t left_shift(uint16_t key[8], int num);  
  20. static void swap(uint16_t *a, uint16_t *b);  
  21.   
  22. /* addition and mod 65536 */  
  23. static uint16_t add_mod(uint16_t a, uint16_t b)  
  24. {  
  25.     uint32_t tmp = a+b;  
  26.     uint16_t ret = tmp % IDEA_ADD_MODULAR;  
  27.     return ret;  
  28. }  
  29.   
  30. /* multiply and mod 65537 */  
  31. static uint16_t mp_mod(uint16_t a,uint16_t b)  
  32. {  
  33.     /* Note: In IDEA, for purposes of multiplication, a 16 bit word containing all zeroes is considered to represent the number 65,536; 
  34.      * other numbers are represented in conventional unsigned notation, and multiplication is modulo the prime number 65,537 
  35.      */  
  36.     uint64_t tmp, tmp_a, tmp_b; //if both a and b are 2^16, the result will be 2^32 which will exceed a 32-bit int  
  37.     tmp_a = a==0 ? (1<<16) : a;  
  38.     tmp_b = b==0 ? (1<<16) : b;  
  39.     tmp = (tmp_a * tmp_b) % IDEA_MP_MODULAR;  
  40.     return (uint16_t)(tmp);  
  41. }  
  42.   
  43. /* XOR */  
  44. static uint16_t XOR(uint16_t a, uint16_t b)  
  45. {  
  46.     return a^b;  
  47. }  
  48.   
  49. static void swap(uint16_t *a, uint16_t *b)  
  50. {  
  51.     uint16_t c = 0;  
  52.     c = *a;  
  53.     *a = *b;  
  54.     *b = c;  
  55. }  
  56.   
  57. /* IDEA encryption */  
  58. status_t idea_encrypt(uint64_t plaintext, uint16_t key[8], uint64_t *ciphertext)  
  59. {  
  60.     uint16_t X[4], sub_key[52], out[4];  
  61.     status_t st;  
  62.     int i, j;  
  63.       
  64.     /* cut 64-bit plaintext into 4 16-bit sub blocks */  
  65.     for(i = 0; i < 4; i++)  
  66.         X[i] = (plaintext >> (48-i*16)) & 0xffff;  
  67.       
  68.     /* generate sub keys */  
  69.     st = subkey_generation(key, sub_key);  
  70.       
  71.     for(i = 0; i < 8; i++)  
  72.     {  
  73.         idea_round(X, &(sub_key[i*6]), out);  
  74.         for(j = 0; j < 4; j++)  
  75.             X[j] = out[j];  
  76.     }  
  77.       
  78.     /* round 9, do output transform */  
  79.     //Note that the swap of B and C is not performed after round 8. So we swap them again.  
  80.     swap(&(out[1]), &(out[2]));  
  81.     out[0] = mp_mod(out[0], sub_key[48]);  
  82.     out[1] = add_mod(out[1], sub_key[49]);  
  83.     out[2] = add_mod(out[2], sub_key[50]);  
  84.     out[3] = mp_mod(out[3], sub_key[51]);  
  85.     *ciphertext = out[0];  
  86.     for(i = 1; i <= 3; i++)  
  87.         *ciphertext = ((*ciphertext)<<16)|out[i];  
  88.       
  89.     return st;  
  90. }  
  91.   
  92. /* IDEA decryption */  
  93. status_t idea_decrypt(uint64_t ciphertext, uint16_t key[8], uint64_t *plaintext)  
  94. {  
  95.     status_t st;  
  96.     uint16_t X[4], sub_dkey[52], out[4];  
  97.     int i, j;  
  98.       
  99.     for(i = 0; i < 4; i++)  
  100.         X[i] = (ciphertext >> (48-i*16)) & 0xffff;  
  101.       
  102.     /* generate sub keys for decryption*/  
  103.     st = subdkey_generation(key, sub_dkey);  
  104.     if(st != IDEA_SUCCESS)  
  105.         return st;  
  106.       
  107.     for(i = 0; i < 8; i++)  
  108.     {  
  109.         idea_round(X, &(sub_dkey[i*6]), out);  
  110.         for(j = 0; j < 4; j++)  
  111.             X[j] = out[j];  
  112.     }  
  113.       
  114.     out[0] = mp_mod(out[0], sub_dkey[48]);  
  115.     out[1] = add_mod(out[1], sub_dkey[49]);  
  116.     out[2] = add_mod(out[2], sub_dkey[50]);  
  117.     out[3] = mp_mod(out[3], sub_dkey[51]);  
  118.     swap(&(out[1]), &(out[2]));     //Note that the unswap in decryption is called after transform, that is different from the encryption.  
  119.       
  120.     *plaintext = out[0];  
  121.     for(i = 1; i <= 3; i++)  
  122.         *plaintext = ((*plaintext)<<16) | out[i];  
  123.           
  124.     return st;  
  125. }  
  126.   
  127. status_t idea_round(uint16_t X[4], uint16_t Z[6], uint16_t out[4])  
  128. {  
  129.     status_t st;  
  130.     uint16_t tmp[4], ma_in[2], ma_out[2];  
  131.     tmp[0] = mp_mod(X[0], Z[0]);    //step 1. multiply X1 by 1st sub key  
  132.     tmp[1] = add_mod(X[1], Z[1]);   //step 2. add X2 to 2nd sub key  
  133.     tmp[2] = add_mod(X[2], Z[2]);   //step 3. add X3 to 3rd sub key  
  134.     tmp[3] = mp_mod(X[3], Z[3]);    //step 4. multiply X4 by 4th sub key  
  135.       
  136.     ma_in[0] = XOR(tmp[0], tmp[2]); //step 5. XOR results in step 1 and step 3  
  137.     ma_in[1] = XOR(tmp[1], tmp[3]); //step 6. XOR results in step 2 and step 4  
  138.       
  139.     st = MA(ma_in, &Z[4], ma_out);  //step 7. MA diffusion  
  140.       
  141.     /* step 8. generate the output*/  
  142.     out[0] = XOR(tmp[0], ma_out[1]);  
  143.     out[1] = XOR(tmp[1], ma_out[0]);  
  144.     out[2] = XOR(tmp[2], ma_out[1]);  
  145.     out[3] = XOR(tmp[3], ma_out[0]);  
  146.     swap(&(out[1]), &(out[2]));  
  147.       
  148.     return st;  
  149. }  
  150.   
  151. /* MA diffusion */  
  152. status_t MA(uint16_t ma_in[2], uint16_t sub_key[2],uint16_t ma_out[2])  
  153. {  
  154.     uint16_t tmp[2];  
  155.       
  156.     tmp[0] = mp_mod(ma_in[0], sub_key[0]);  
  157.     tmp[1] = add_mod(ma_in[1], tmp[0]);  
  158.     ma_out[1] = mp_mod(tmp[1], sub_key[1]);  
  159.     ma_out[0] = add_mod(tmp[0], ma_out[1]);  
  160.       
  161.     return IDEA_SUCCESS;  
  162. }  
  163.   
  164. /* sub keys generation */  
  165. status_t subkey_generation(uint16_t key[8], uint16_t sub_key[52])  
  166. {  
  167.     int i, j;  
  168.     uint16_t tmp_key[8];  
  169.     for(i = 0; i < 8; i++)  
  170.         tmp_key[i] = key[i];  
  171.     for(i = 0; i < 6; i++)  
  172.     {  
  173.         for(j = 0; j < 8; j++)  
  174.             sub_key[i*8+j] = tmp_key[j];  
  175.         left_shift(tmp_key, 25);  
  176.     }  
  177.     for(i = 0; i < 4; i++)  
  178.         sub_key[48+i] = tmp_key[i];  
  179.     return IDEA_SUCCESS;  
  180. }  
  181.   
  182. /* sub dkeys generation 
  183.  *  
  184.  *The decryption key schedule is: 
  185.  * 
  186.  *The first four subkeys for decryption are: 
  187.  * 
  188.  *KD(1) = 1/K(49) 
  189.  *KD(2) =  -K(50) 
  190.  *KD(3) =  -K(51) 
  191.  *KD(4) = 1/K(52) 
  192.  * 
  193.  *and they do not quite follow the same pattern as the remaining subkeys which follow. 
  194.  * 
  195.  *The following is repeated eight times, adding 6 to every decryption key's index and subtracting 6 from every encryption key's index: 
  196.  * 
  197.  *KD(5)  =   K(47) 
  198.  *KD(6)  =   K(48) 
  199.  * 
  200.  *KD(7)  = 1/K(43) 
  201.  *KD(8)  =  -K(45) 
  202.  *KD(9)  =  -K(44) 
  203.  *KD(10) = 1/K(46) 
  204.  *  
  205.  */  
  206. status_t subdkey_generation(uint16_t key[8], uint16_t sub_dkey[52])  
  207. {  
  208.     status_t st;  
  209.     int i;  
  210.     uint16_t sub_key[52];  
  211.     uint32_t tmp;  
  212.       
  213.     st = subkey_generation(key, sub_key);  
  214.       
  215.     st = extended_eucild(sub_key[48], IDEA_MP_MODULAR, &tmp);  
  216.     if(st != IDEA_SUCCESS)  
  217.     {  
  218.         printf("subdkey_generation error!/n");  
  219.         return st;  
  220.     }  
  221.     sub_dkey[0] = tmp == 65536 ? 0 : (uint16_t)tmp;  
  222.     sub_dkey[1] = (IDEA_ADD_MODULAR - sub_key[49]) % IDEA_ADD_MODULAR;  
  223.     sub_dkey[2] = (IDEA_ADD_MODULAR - sub_key[50]) % IDEA_ADD_MODULAR;  
  224.     st = extended_eucild(sub_key[51], IDEA_MP_MODULAR, &tmp);  
  225.     if(st != IDEA_SUCCESS)  
  226.     {  
  227.         printf("subdkey_generation error!/n");  
  228.         return st;  
  229.     }  
  230.     sub_dkey[3] = tmp == 65536 ? 0 : (uint16_t)tmp;  
  231.       
  232.     for(i = 0; i < 8; i++)   //This is awful?!...May be I should make a table.  
  233.     {  
  234.         sub_dkey[4+i*6] = sub_key[52-(i+1)*6];  
  235.         sub_dkey[4+i*6+1] = sub_key[52-(i+1)*6+1];  
  236.         st = extended_eucild(sub_key[52-(i+1)*6-4], IDEA_MP_MODULAR, &tmp);  
  237.         if(st != IDEA_SUCCESS)  
  238.         {  
  239.             printf("subdkey_generation error!/n");  
  240.             return st;  
  241.         }  
  242.         sub_dkey[4+i*6+2] = tmp == 65536 ? 0 : (uint16_t)tmp;  
  243.         sub_dkey[4+i*6+3] = (IDEA_ADD_MODULAR - sub_key[52-(i+1)*6-2]) % IDEA_ADD_MODULAR;  
  244.         sub_dkey[4+i*6+4] = (IDEA_ADD_MODULAR - sub_key[52-(i+1)*6-3]) % IDEA_ADD_MODULAR;  
  245.         st = extended_eucild(sub_key[52-(i+1)*6-1], IDEA_MP_MODULAR, &tmp);  
  246.         if(st != IDEA_SUCCESS)  
  247.         {  
  248.             printf("subdkey_generation error!/n");  
  249.             return st;  
  250.         }  
  251.         sub_dkey[4+i*6+5] = tmp == 65536 ? 0 : (uint16_t)tmp;  
  252.     }  
  253.     return IDEA_SUCCESS;  
  254. }  
  255.   
  256. /* left shift */  
  257. static status_t left_shift(uint16_t key[8], int num)  
  258. {  
  259.     uint16_t copy_key[8];  
  260.     int i;  
  261.     for(i = 0; i < 8; i++)  
  262.         copy_key[i] = key[i];  
  263.     for(i = 0; i < 8; i++)  
  264.         key[i] = (copy_key[(i+num/16)%8]<<(num%16)) | (copy_key[(i+num/16+1)%8]>>(16-num%16));  
  265.     return IDEA_SUCCESS;  
  266. }  
  267.   
  268. /* Extended Eucild Algorithm to caculate d^-1 mod k*/  
  269. status_t extended_eucild(uint16_t d, uint32_t k, uint32_t *result)  
  270. {  
  271.     int x[4], y[4], t[4], q;  
  272.     int i;  
  273.     x[1] = x[2] = 0;  
  274.     x[3] = k;  
  275.     y[1] = 0, y[2] = 1;  
  276.     y[3] = d == 0 ? (1<<16) : d;  
  277.       
  278.     while(y[3] > 1)  
  279.     {  
  280.         q = x[3] / y[3];  
  281.         for(i = 1; i <= 3; i++)  
  282.             t[i] = x[i] - q*y[i];  
  283.         for(i = 1; i <= 3; i++)  
  284.             x[i] = y[i];  
  285.         for(i = 1; i <= 3; i++)  
  286.             y[i] = t[i];  
  287.     }  
  288.     if(y[3] == 1)  
  289.     {  
  290.         if(y[2] < 0)  
  291.             y[2] += k;  
  292.         *result = y[2];  
  293.         return IDEA_SUCCESS;  
  294.     }  
  295.     else  
  296.         return IDEA_ERROR;  
  297. }  
[c-sharp]  view plain copy
  1. /* a simple test program of IDEA encryption and decryption.  
  2.  * Author shenyang 
  3.  * */  
  4. #include   
  5. #include   
  6. #include "IDEA.h"  
  7.   
  8. void usage()  
  9. {  
  10.     printf("Usage: IDEA [-e(encrypt)|-d(decrypt)]/n");  
  11. }  
  12.   
  13. void encrypt()  
  14. {  
  15.     uint16_t key[8];  
  16.     uint64_t plaintext[1024], ciphertext[1024];  
  17.     char str[1024];  
  18.     int block_cnt = 0, i = 0, len;  
  19.     printf("/ninput plaintext(in hex):");  
  20.     scanf("%s", str);  
  21.     len = strlen(str);  
  22.     for(; len%16 != 0; len++)//fill the text with '0' such that it can be cut into 64-bit blocks.  
  23.         str[len] = '0';  
  24.     str[len] = '/0';  
  25.       
  26.     while(sscanf(str+block_cnt*16, "%016llx", &(plaintext[block_cnt]))!=EOF)//4x16=64  
  27.         block_cnt++;  
  28.       
  29.     /*while(sscanf(str+block_cnt*4, "%04hx", &(tmp[block_cnt]))!=EOF) 
  30.         block_cnt++; 
  31.     for(i = 0; i*4 < block_cnt; i++) 
  32.     { 
  33.         plaintext[i] = tmp[i*4]; 
  34.         for(j = 1; j < 4; j++) 
  35.             plaintext[i] = (plaintext[i]<<16)|tmp[i*4+j]; 
  36.     } 
  37.     block_cnt /= 4;*/  
  38.       
  39.     printf("/ninput 128-bit secret key(in hex):");  
  40.     scanf("%s", str);  
  41.     len = strlen(str);  
  42.     if(len > 32)  
  43.     {  
  44.         printf("/nsecret key too long");  
  45.         return ;  
  46.     }  
  47.     for(; len < 32; len++)  
  48.         str[len] = '0';  
  49.     str[len] = '/0';  
  50.       
  51.     for(i = 0; i < 8; i++)  
  52.         sscanf(str+i*4, "%04hx", &key[i]);  
  53.   
  54.     printf("/nciphertext = ");  
  55.     for(i = 0; i < block_cnt; i++)  
  56.     {  
  57.         idea_encrypt(plaintext[i], key, &(ciphertext[i]));  
  58.         printf("%016llx", ciphertext[i]);  
  59.     }  
  60.     printf("/n");  
  61. }  
  62.   
  63. void decrypt()  
  64. {  
  65.     uint16_t key[8];  
  66.     uint64_t plaintext[1024], ciphertext[1024];  
  67.     char str[1024];  
  68.     int block_cnt = 0, i = 0, len;  
  69.     printf("/ninput ciphertext(in hex):");  
  70.     scanf("%s", str);  
  71.     len = strlen(str);  
  72.     for(; len%16 != 0; len++)  
  73.         str[len] = '0';  
  74.     str[len] = '/0';  
  75.       
  76.     while(sscanf(str+block_cnt*16, "%016llx", &(ciphertext[block_cnt]))!=EOF)  
  77.         block_cnt++;  
  78.     /*while(sscanf(str+block_cnt*4, "%04hx", &(tmp[block_cnt]))!=EOF) 
  79.         block_cnt++; 
  80.     for(i = 0; i*4 < block_cnt; i++) 
  81.     { 
  82.         ciphertext[i] = tmp[i*4]; 
  83.         for(j = 1; j < 4; j++) 
  84.             ciphertext[i] = (ciphertext[i]<<16)|tmp[i*4+j]; 
  85.     } 
  86.     block_cnt /= 4;*/  
  87.       
  88.     printf("/ninput 128-bit secret key(in hex):");  
  89.     scanf("%s", str);  
  90.     len = strlen(str);  
  91.     if(len > 32)  
  92.     {  
  93.         printf("/nsecret key too long");  
  94.         return ;  
  95.     }  
  96.     for(; len < 32; len++)  
  97.         str[len] = '0';  
  98.     str[len] = '/0';  
  99.       
  100.     for(i = 0; i < 8; i++)  
  101.         sscanf(str+i*4, "%04hx", &key[i]);  
  102.   
  103.     printf("/nplaintext = ");  
  104.     for(i = 0; i < block_cnt; i++)  
  105.     {  
  106.         idea_decrypt(ciphertext[i], key, &(plaintext[i]));  
  107.         printf("%016llx", plaintext[i]);  
  108.     }  
  109.     printf("/n");  
  110. }  
  111.   
  112. int main(int argc, char **argv)  
  113. {  
  114.     if(argc < 2)  
  115.     {  
  116.         usage();  
  117.         return 1;  
  118.     }  
  119.     if(argv[1][0] != '-')  
  120.     {  
  121.         usage();  
  122.         return 1;  
  123.     }  
  124.     switch(argv[1][1])  
  125.     {  
  126.         case 'e':  
  127.         case 'E':   
  128.             encrypt();  
  129.             break;  
  130.         case 'd':  
  131.         case 'D':  
  132.             decrypt();  
  133.             break;  
  134.         default:  
  135.             usage();  
  136.             return 1;  
  137.     }  
  138.     return 0;  
  139. }  

要注意的是不同环境下读64位整数的方式不同,可能要把%llx改成%I64x.

<script type="text/javascript"> </script>
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页