PRESENT密码的逐位操作



我正在努力理解生成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)来查看数字的二进制字符串表示。

最新更新