AES SBox的构造(python)
几点需要注意的,求解逆元的时候使用的是拓展欧几里得,但是那些运算规则需要变一变,模2的加减乘除(或者可以理解为多项式的运算)
在进行字节的仿射变换不用进行矩阵的运算。
一个矩阵和一个列向量进行运算的时候可以视为矩阵的列向量的线性组合
代码如下:
1 #使用拓展欧几里得求解乘法矩阵的逆元 2 #求一个数的二进制位的长度 3 def length(a): 4 len=0 5 while(a): 6 a=a>>1 7 len+=1 8 return len 9 10 #模2的加减都是一样的,异或即可 11 def addSub(a,b): 12 return (a^b) 13 14 def gcd(m,n): 15 while(n!=0): 16 m,n=n,m%n 17 return m 18 19 #乘法 20 def multi(a,c): 21 b=0x01 22 flag=[] #flag得到的是c中为1的位(置) 23 for j in range(8): 24 if(c&b): 25 flag.append(j) 26 b=(b<<1)&0x00ff #b从最低位开始,不断左移并与c相与,目的是找出c中为1的位 27 kk=[] 28 kk.append(a) #将a本身存放进去 29 for i in range(7): #8位,除了1之外(1就是原数的本身),其余的都先算出结果 30 if (a&0x80): 31 a=a<<1 32 a=a&0x00ff #将高8位清零,保留低8位(如果上述的左移运算的位数超过8位的话),如果没有这个操作的话,不会默认保留低8位 33 a=a^0x1b 34 else: 35 a=a<<1 36 kk.append(a) 37 result=0 #任何数与0异或都是其本身 38 for k in flag: 39 result=result^kk[k] 40 return result 41 42 #参考:https://www.cnblogs.com/YKang/p/7663737.html 43 #多项式的模2除法运算,函数的返回值是得到的商和余数 44 def division(a,b): 45 len1=length(a) 46 len2=length(b) 47 len3=len1-len2 48 49 if a<b: #被除数小于除数 50 if len3==0: #两个数的长度相同,则直接商1,余数是二者异或的结果 51 return (1,a^b) 52 else: 53 return (0,a) #如果被除数的位数小于除数,则商0,余数为a 54 55 topBit=1 56 topBit<<=(len1-1) 57 b<<=len3 #将b的位数扩充到和a的位数一样的长度 58 59 quotient=0 60 remainder=0 61 62 for i in range(len3): 63 quotient<<=1 #quotient每次左移一位,就是在后面添加0,然后下面再用一个for循环来确定新增的位是0还是1 64 if (topBit&a): #a的最高位为0,即意味着a此时的位数按照正常的一位落位可以满足和除数b的运算 65 quotient^=1 #如果上面的if语句成立,则说明此时的商应该是1,所以0和1异或得1 66 a^=b 67 else: 68 a^=0 69 topBit>>=1 #每运算一次,这个就应该右移一位,继续判断a的位数是否满足 70 b>>=1 #b右移的效果也是一样的 71 quotient<<=1 #quotient继续右移一位,此时新加的为0 72 if a<b: 73 remainder=a 74 else: 75 quotient^=1 76 remainder=a^b 77 78 return quotient,remainder 79 80 def egcd(a,b): 81 r0,r1,s0,s1=1,0,0,1 82 while(b): 83 qt,rt=division(a,b) 84 q,a,b=qt,b,rt 85 r0,r1=r1,addSub(r0,multi(q,r1)) 86 s0,s1=s1,addSub(s0,multi(q,s1)) 87 return s0 #s0是求得的逆元 88 89 #矩阵乘以列向量 90 #矩阵乘以列向量,其实可以以矩阵的列向量进行线性组合 91 #https://www.zhihu.com/question/21351965/answer/103520656 92 #也就是矩阵中的第i列和列向量的第i个元素相乘(这里就是简单的相乘,所以那些在列向量中为0的元素就可以忽略不计), 93 #因为所以的列向量的元素非0几1,所以可以直接使用x进行操作,无须再将x转换成二进制的比特位 94 #异或运算是二进制位的异或,所以在求解res^M[i]的时候就可以直接把res和整个列进行异或 95 #参考:https://www.jianshu.com/p/9626fcd97a69 96 def byteSub(inelem): #传入逆元给函数 97 M=[0x1F, 0x3E, 0x7C, 0xF8, 0xF1, 0xE3, 0xC7, 0x8F] 98 res=0x00 99 i=0 100 x=inelem 101 while x>0: 102 if x%2: 103 res^=M[i] 104 i+=1 105 x>>=1 #位移或者 '//' 106 return hex(res^0x63) 107 108 def sBox(): 109 box=[] 110 for i in range(256): 111 sbox=byteSub(egcd(283,i)) 112 box.append(sbox) 113 for j in range(256): 114 print(box[j],end=' ') 115 if (j+1)%16==0: 116 print('\n') 117 118 sBox()
参考:https://www.jianshu.com/p/9626fcd97a69
https://www.cnblogs.com/YKang/p/7663737.html
https://www.zhihu.com/question/21351965/answer/103520656