我正在努力理解生成roundkey的逐位操作。下面是给我的代码:
def generateRoundkeys80(key, rounds):
"""Generate the roundkeys for a 80-bit key
Input:
key: the key as a 80-bit integer
rounds: the number of rounds as an integer
Output: list of 64-bit roundkeys as integers"""
roundkeys = []
for i in xrange(1, rounds + 1): # (K1 ... K32)
# rawkey: used in comments to show what happens at bitlevel
# rawKey[0:64]
roundkeys.append(key >> 16)
# 1. Shift
# rawKey[19:len(rawKey)]+rawKey[0:19]
key = ((key & (2 ** 19 - 1)) << 61) + (key >> 19)
# 2. SBox
# rawKey[76:80] = S(rawKey[76:80])
key = (Sbox[key >> 76] << 76) + (key & (2 ** 76 - 1))
#3. Salt
#rawKey[15:20] ^ i
key ^= i << 15
return roundkeys
我所理解的是,在(1(中,我们进行61位左旋转(我实现了key = (key << 61)|(key >> (len(key) - 61))
(,(2(将sbox应用于最左边的4位,(3(将循环计数器与位15-19异或。然而,当涉及到按位操作时,我不理解**和+的含义。如有任何解释,不胜感激!
让我们考虑一下代码中的以下行,希望所有操作都能变得清晰:
key = ((key & (2 ** 19 - 1)) << 61) + (key >> 19)
让我们从表达式(2 ** 19 - 1)
开始。运算符**
是幂运算。在您提供的代码中,它用于构造二进制数,这些二进制数将在操作中用作掩码。例如,二进制中的数字2 ** 19
将是"0";1〃;然后是19个零。2 ** 19 - 1
是19个1。
当你执行(key & (2 ** 19 - 1))
时,它是一个逐位AND,会给你密钥的最后19位,<< 61
会在右边加61个零,所以你最终得到密钥的最后十九位,后面跟着61个零。
(key >> 19)
将转储密钥中最右侧的19位数字,并向上移动其余数字,在左侧填充19个零。所以当你把两个数字加在一起时,每个数字只有零,而另一个有数据。+
实际上只是将它们组合在一起。
如果您想跟随Python的计算,可以使用print {0.b}.format(key)
来查看数字的二进制字符串表示。