有限域GF(2^8)内乘法代码实现以及原理

      在密码学中经常用到有限域的乘法,一般在AES中用到的是GF(2^8)有限域内乘法。什么是有限域呢?有限域通俗的讲就是函数的运算结果全都包含在一个域中,不同于实数域,有限域有一个最大值,所有超过这个最大值的数都会经过一定的方法使他回到这个域中,在密码学中应用很广泛,2^8意味着这个域的最大值是256.

       以下代码是GF(2^8)有限域内乘法的C代码实现:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. unsigned char XTIME(unsigned char x) {  
  2.     return ((x << 1) ^ ((x & 0x80) ? 0x1b : 0x00));  
  3. }  
  4. unsigned char multiply(unsigned char a, unsigned char b) {  
  5.     unsigned char temp[8] = { a };  
  6.     unsigned char tempmultiply = 0x00;  
  7.     int i = 0;  
  8.     for (i = 1; i < 8; i++) {  
  9.         temp[i] = XTIME(temp[i - 1]);  
  10.     }  
  11.     tempmultiply = (b & 0x01) * a;  
  12.     for (i = 1; i <= 7; i++) {  
  13.         tempmultiply ^= (((b >> i) & 0x01) * temp[i]);  
  14.     }  
  15.     return tempmultiply;  
  16. }  

以下讲一下乘法的原理:

          在二进制中,所有的数都能用0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80异或得到,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80的二进制表示如下:


       后一个分别是前一个的2倍。假设任意一个数a,他的二进制表示为10101101,可以由以下组合组成:


       而任何一个数x和a相乘都可以表示为


所以只要计算出

一切乘法的结果都可以得到。

         XTIME函数的含义是求一个数x与0x02的乘积,一般求一个数的2倍,都是作移一位,在有限域内,要计算有限域的乘法,必须先确定一个GF上的8次不可约多项式,Rijndael密码中,这个多项式确定为x^8+x^4+x^3+x+1,如果最高位是1的话,左移一位的同时要异或0x1B,是因为最高位是1的话,再继续左移会超出域的最大值,这个时候需要取除以同余式,也就是异或0x1B。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. for (i = 1; i < 8; i++) {  
  2.     temp[i] = XTIME(temp[i - 1]);  
  3. }  
经过这个循环可以得到一串包含8个字符的数组,分别是0x01*x,0x02*x,0x04*x,0x08*x,0x10*x,0x20*x,0x40*x,,0x80*x,放在temp这个数组内。接下来通过这个循环

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. for (i = 1; i <= 7; i++) {  
  2.     tempmultiply ^= (((b >> i) & 0x01) * temp[i]);  
  3. }  

另一个乘数b右移一位和0x01与运算,分别和这8个字符相乘,再把相乘的结果异或。就得到了a和b相乘的结果。

接下来举个例子:

求0x3a*0x24?

        首先0x3a=00111010,分别求



0x24=00100100,所以0x3a*0x24=0x3a*00100100=0x04*0x3a^0x20*0x3a=0xe8^0x01=0xe9.

是正确结果。


如果要提高算法的计算效率,还可以这么做。

如果一个乘数的二进制可以表示为


一个乘数表示为


那么a的倍数关系可表示为:


那么他的乘积可以表示为


其中


所以乘法可以表示为


所以还有一种计算方法,那就是按照上面这个矩阵乘法。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4.   
  5. void print_bit(bool *hexbit, int len) {  
  6.     int i = 0;  
  7.     for (i = 0; i < len; i++) {  
  8.         printf("%x ", hexbit[i]);  
  9.     }  
  10. }  
  11.   
  12. void print_matrix(bool matrix[8][8]) {  
  13.     int i = 0;  
  14.     for (i = 0; i < 8; i++) {  
  15.         print_bit(matrix[i], 8);  
  16.         printf("\n");  
  17.   
  18.     }  
  19. }  
  20.   
  21. void convertto_bit(unsigned char cipher, bool *hexbit, int len) {  
  22.   
  23.     len = 8;  
  24.     int i = 0;  
  25.     for (i = 0; i < 8; i++) {  
  26.         if (cipher & 0x80) {  
  27.             hexbit[i] = true;  
  28.         }  
  29.         cipher = cipher << 1;  
  30.     }  
  31. }  
  32. void convertto_matrix(bool hexbit[8], bool matrix[8][8]) {  
  33.   
  34.     matrix[0][0] = hexbit[0];  
  35.     matrix[0][1] = hexbit[1];  
  36.     matrix[0][2] = hexbit[2];  
  37.     matrix[0][3] = hexbit[3];  
  38.     matrix[0][4] = hexbit[0] ^ hexbit[4];  
  39.     matrix[0][5] = hexbit[0] ^ hexbit[1] ^ hexbit[5];  
  40.     matrix[0][6] = hexbit[1] ^ hexbit[2] ^ hexbit[6];  
  41.     matrix[0][7] = hexbit[0] ^ hexbit[2] ^ hexbit[3] ^ hexbit[7];  
  42.   
  43.     matrix[1][0] = hexbit[1];  
  44.     matrix[1][1] = hexbit[2];  
  45.     matrix[1][2] = hexbit[3];  
  46.     matrix[1][3] = matrix[0][4];  
  47.     matrix[1][4] = matrix[0][5];  
  48.     matrix[1][5] = matrix[0][6];  
  49.     matrix[1][6] = hexbit[0] ^ hexbit[2] ^ hexbit[3] ^ hexbit[7];  
  50.     matrix[1][7] = hexbit[1] ^ hexbit[3] ^ hexbit[4];  
  51.   
  52.     matrix[2][0] = hexbit[2];  
  53.     matrix[2][1] = hexbit[3];  
  54.     matrix[2][2] = matrix[1][3];  
  55.     matrix[2][3] = matrix[1][4];  
  56.     matrix[2][4] = matrix[1][5];  
  57.     matrix[2][5] = matrix[1][6];  
  58.     matrix[2][6] = matrix[1][7];  
  59.     matrix[2][7] = hexbit[2] ^ hexbit[4] ^ hexbit[5];  
  60.   
  61.     matrix[3][0] = hexbit[3];  
  62.     matrix[3][1] = matrix[2][2];  
  63.     matrix[3][2] = matrix[2][3];  
  64.     matrix[3][3] = matrix[2][4];  
  65.     matrix[3][4] = matrix[2][5];  
  66.     matrix[3][5] = matrix[2][6];  
  67.     matrix[3][6] = matrix[2][7];  
  68.     matrix[3][7] = hexbit[0] ^ hexbit[3] ^ hexbit[5] ^ hexbit[6];  
  69.   
  70.     matrix[4][0] = hexbit[4];  
  71.     matrix[4][1] = hexbit[0] ^ hexbit[5];  
  72.     matrix[4][2] = hexbit[1] ^ hexbit[6];  
  73.     matrix[4][3] = hexbit[0] ^ hexbit[2] ^ hexbit[7];  
  74.     matrix[4][4] = hexbit[0] ^ hexbit[1] ^ hexbit[3];  
  75.     matrix[4][5] = hexbit[0] ^ hexbit[1] ^ hexbit[2] ^ hexbit[4];  
  76.     matrix[4][6] = hexbit[0] ^ hexbit[1] ^ hexbit[2] ^ hexbit[3] ^ hexbit[5];  
  77.     matrix[4][7] = hexbit[0] ^ hexbit[1] ^ hexbit[2] ^ hexbit[3] ^ hexbit[4]  
  78.             ^ hexbit[6];  
  79.   
  80.     matrix[5][0] = hexbit[5];  
  81.     matrix[5][1] = hexbit[6];  
  82.     matrix[5][2] = hexbit[0] ^ hexbit[7];  
  83.     matrix[5][3] = hexbit[0] ^ hexbit[1];  
  84.     matrix[5][4] = hexbit[1] ^ hexbit[2];  
  85.     matrix[5][5] = hexbit[2] ^ hexbit[3];  
  86.     matrix[5][6] = hexbit[0] ^ hexbit[3] ^ hexbit[4];  
  87.     matrix[5][7] = hexbit[1] ^ hexbit[4] ^ hexbit[5];  
  88.   
  89.     matrix[6][0] = hexbit[6];  
  90.     matrix[6][1] = matrix[5][2];  
  91.     matrix[6][2] = matrix[5][3];  
  92.     matrix[6][3] = matrix[5][4];  
  93.     matrix[6][4] = matrix[5][5];  
  94.     matrix[6][5] = matrix[5][6];  
  95.     matrix[6][6] = matrix[5][7];  
  96.     matrix[6][7] = hexbit[0] ^ hexbit[2] ^ hexbit[5] ^ hexbit[6];  
  97.   
  98.     matrix[7][0] = hexbit[7];  
  99.     matrix[7][1] = hexbit[0];  
  100.     matrix[7][2] = hexbit[1];  
  101.     matrix[7][3] = hexbit[2];  
  102.     matrix[7][4] = hexbit[3];  
  103.     matrix[7][5] = matrix[2][2];  
  104.     matrix[7][6] = matrix[2][3];  
  105.     matrix[7][7] = matrix[2][4];  
  106.   
  107.     return;  
  108. }  
  109.   
  110. unsigned char XTIME(unsigned char x) {  
  111.     return ((x << 1) ^ ((x & 0x80) ? 0x1b : 0x00));  
  112. }  
  113. unsigned char multiply(unsigned char a, unsigned char b) {  
  114.     unsigned char temp[8] = { a };  
  115.     unsigned char tempmultiply = 0x00;  
  116.     int i = 0;  
  117.     for (i = 1; i < 8; i++) {  
  118.         temp[i] = XTIME(temp[i - 1]);  
  119.     }  
  120.     tempmultiply = (b & 0x01) * a;  
  121.     for (i = 1; i <= 7; i++) {  
  122.         tempmultiply ^= (((b >> i) & 0x01) * temp[i]);  
  123.     }  
  124.     return tempmultiply;  
  125. }  
  126.   
  127. unsigned char multiply_bit(unsigned char plaintext, unsigned char key) {  
  128.     int ret_len = 0;  
  129.     bool plaintext_hexbit[8] = { falsefalsefalsefalsefalsefalse,  
  130.             falsefalse };  
  131.     bool key_hexbit[8] = { falsefalsefalsefalsefalsefalsefalse,  
  132.             false };  
  133.     bool cipher_hexbit[8] = { falsefalsefalsefalsefalsefalsefalse,  
  134.             false };  
  135.     //把plaintext转换成二进制  
  136.     convertto_bit(plaintext, plaintext_hexbit, ret_len);  
  137.     bool matrix[8][8] = { };  
  138.     convertto_matrix(plaintext_hexbit, matrix);  
  139.   
  140.     //把key转换成二进制  
  141.     convertto_bit(key, key_hexbit, ret_len);  
  142.   
  143.     //print_matrix(matrix);  
  144.     //printf("\n");  
  145.   
  146.     //print_bit(key_hexbit, sizeof(key_hexbit));  
  147.     //printf("\n");  
  148.     int i = 0;  
  149.     int j = 0;  
  150.   
  151.     for (i = 0; i < 8; i++) {  
  152.         cipher_hexbit[i] = false;  
  153.         for(j = 0;j < 8;j++) {  
  154.             if(key_hexbit[j]){  
  155.                 cipher_hexbit[i] ^=matrix[i][7-j];  
  156.             }  
  157.         }  
  158.     }  
  159.   
  160.     //print_bit(cipher_hexbit, sizeof(cipher_hexbit));  
  161.   
  162.     unsigned char outcome = 0;  
  163.     for (i = 0; i < 8; i++) {  
  164.         if (cipher_hexbit[i]) {  
  165.             outcome ^= 0x01 << (7 - i);  
  166.         }  
  167.     }  
  168.     return outcome;  
  169. }  
  170.   
  171. int main(int argc, char * argv[]) {  
  172.   
  173.     unsigned char plaintext = 0x49;  
  174.     unsigned char key = 0x24;  
  175.   
  176.     printf("%#x", multiply_bit(plaintext, key));  
  177.     printf("\n");  
  178. //  unsigned char plaintext1 = 0x01;  
  179. //  unsigned char key1 = 0x21;  
  180.     printf("%#x", multiply(plaintext, key));  
  181.   
  182.     return 0;  
  183. }  



输出结果是
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 0xdc  
  2. 0xdc  
结果一样,是正确的

经过测试,后一种方法比第一种方法效率慢很多,原因是其中代码计算矩阵和矩阵乘法比第一种方法复杂。但是第二种提供另外一种思路。


转载出处:http://blog.csdn.net/bupt073114/article/details/27382533


  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Python中实现有限域GF(2^8)内乘法,可以使用多项式乘法的方式来实现。具体的原理如下: 在GF(2^8)内,多项式的系数只能取0或1,也就是说,一个8位的二进制数可以表示为一个8次多项式。例如,二进制数11011001可以表示为多项式x^7 + x^6 + x^4 + x^3 + 1。 GF(2^8)内的乘法可以通过多项式乘法实现。例如,如果我们要计算多项式x^7 + x^6 + x^4 + x^3 + 1和多项式x^3 + x^2 + x,则可以将它们相乘得到一个15次多项式,然后将其对一个特定的生成多项式g(x)取模,得到的余数就是它们在GF(2^8)内的乘积。通常,生成多项式g(x)的系数是一个二进制数,例如,g(x) = x^8 + x^4 + x^3 + x + 1,可以表示为二进制数100011101。 下面是一个Python实现有限域GF(2^8)内乘法代码示例: ```python def gf_mul(a, b): p = 0 for i in range(8): if b & 1: p ^= a hi_bit_set = a & 0x80 a <<= 1 if hi_bit_set: a ^= 0x1b b >>= 1 return p % 256 def gf_pow(x, power): res = 1 while power > 0: if power & 1: res = gf_mul(res, x) x = gf_mul(x, x) power >>= 1 return res def gf_div(a, b): if b == 0: raise ZeroDivisionError() p = gf_pow(b, 254) return gf_mul(a, p) a = 0x57 b = 0x83 print(hex(gf_mul(a, b))) # 输出0xc1 ``` 在这个示例中,我们定义了三个函数:gf_mul()、gf_pow()和gf_div()。gf_mul()函数实现GF(2^8)内的乘法gf_pow()函数实现了幂运算,gf_div()函数实现了除法运算。其中,gf_mul()函数使用了在GF(2^8)内进行乘法运算的方法,gf_pow()函数使用了快速幂算法,gf_div()函数使用了GF(2^8)内的除法运算的方法。 在实际应用中,有限域GF(2^8)内的乘法和幂运算是常用的操作,例如在AES加密算法中,就使用了GF(2^8)内的乘法和幂运算来实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值