标签:需要 end bytes 运算 span 矩阵 com 使用 欧几里得
几点需要注意的,求解逆元的时候使用的是拓展欧几里得,但是那些运算规则需要变一变,模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
标签:需要 end bytes 运算 span 矩阵 com 使用 欧几里得
原文地址:https://www.cnblogs.com/Guhongying/p/9822499.html