python中list问题及GF(2^8)上域元素的乘x
最近学习aes算法的时候,在网上看到一份代码感觉写的挺好的。
https://github.com/bozhu/AES-Python/blob/master/aes.py
但是其中有一个点有点小疑问。仔细研究了一下…拾一下以前看过的知识。
def __round_encrypt(self, state_matrix, key_matrix):
self.__sub_bytes(state_matrix)
self.__shift_rows(state_matrix)
def __sub_bytes(self, s):
for i in range(4):
for j in range(4):
s[i][j] = Sbox[s[i][j]]
def __shift_rows(self, s):
s[0][1], s[1][1], s[2][1], s[3][1] = s[1][1], s[2][1], s[3][1], s[0][1]
s[0][2], s[1][2], s[2][2], s[3][2] = s[2][2], s[3][2], s[0][2], s[1][2]
s[0][3], s[1][3], s[2][3], s[3][3] = s[3][3], s[0][3], s[1][3], s[2][3]
在进行字节替换和行移位的时候,函数并没有返回值,那么state_matrix,它是如何变化的传入到下一个函数中去?
a = 1
print a
def test(t):
t = 3
print t
test(a)
print a
---运行结果---
1
3
1
a = [1,2,3]
print a
def test1(t):
t.append(4)
print t
test1(a)
print a
---运行结果---
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4]
第一个代码块也是平时所理解的,感觉没啥问题,但是第二个代码块,在经过test1函数的处理后,并没有return 返回与赋值,那么为啥a变成了[1,2,3,4]
看下a、t变量的id,他们都是一样的值,也就是带入函数后,t只是a的一个引用,他们最后指向的内存块还是那个值,在整个列表的操作中,都是对这个内存存储的值进行操作,最后a和t的值都是有变化的。
引用http://blog.csdn.net/xidianliutingting/article/details/51682867的图。
所以这可以解释的通一开始的问题,正是因为列表这种赋值其实只是给了一个引用的id,但是还是指向同一个内存值。
所以在使用的时候可以利用 t=a[:]切片操作,这样新的list就是另外一个空间了。
另外就是list的深拷贝和浅拷贝。
在copy库中有一个copy和一个deepcopy
copy.copy是浅拷贝,只拷贝父对象,子对象并不会被拷贝过去,而copy.deepcopy则是深拷贝,相当于完完全全的复制。
子对象不被拷贝是指,比如
a = [1,2,3,[4,5,6]]
其中[4,5,6]就是子对象。
记录aes编写过程中一个重点,在列混淆的时候需要运算,GF(2^8)上域元素的乘x
xtime = lambda a: (((a << 1) ^ 0x1B) & 0xFF) if (a & 0x80) else (a << 1)
def _mult(byte1, byte2): # returns a(x)b(x) (a byte)
"""
Multiplies two polynomials a(x), b(x) in GF(28) modulo the irreducible polynomial m(x) = x8+x4+x3+x+1. (i.e. m(x) = 0x11b).
Parameters:
a - A polynomial a(x) = a7x7+a6x6+a5x5+a4x4+a3x3+a2x2+a1x+a0 in GF(28).
b - A polynomial b(x) = b7x7+b6x6+b5x5+b4x4+b3x3+b2x2+b1x+b0 in GF(28).
Returns:
a(x)b(x) modulo x8+x4+x3+x+1.
"""
sum = 0b00000000
toBeXored = byte2
for i in range(8):
if (byte1 & 0b00000001) == 0b00000001:
sum = sum ^ toBeXored
toBeXored = xtime(toBeXored)
byte1 = byte1 >> 1
return sum
print hex(_mult(0x57,0x13))
其中要注意的是,byte1和byte2都是16进制...当时看成10进制的时候,纠结了超级久。
0x01b=b
0x02b 只要b小于0x80,b<<1。如果b大于或等于0x80,(b<<1)^0x1b
对于大于0x02可以分解成0x02和0x01的算法。
所以
b * 0x0d
= b * (0x08 + 0x04 + 0x01)
= (b * 0x08) + (b * 0x04) + (b * 0x01)
= (b * 0x02 * 0x02 * 0x02) + (b * 0x02 * 0x02) + (b * 0x01)