PRESENT 密码的按位运算

Bitwise operation for PRESENT cipher

我正在尝试了解生成轮密钥的按位运算。下面是给我的代码:

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 将是一个“1”,后跟 19 个零。数字2 ** 19 - 1是19个。

当你做 (key & (2 ** 19 - 1)) 时,它是按位与,它会给你密钥的最后 19 位,<< 61 会在右边添加 61 个零,所以你最终得到密钥的最后 19 位数字后跟 61 个零。

(key >> 19) 将转储密钥中最右边的 19 位数字并将其余数字向上移动,并在左侧填充 19 个零。因此,当您将两个数字相加时,每个数字只有零,而另一个数字有数据。 + 实际上只是将它们放在一起。

如果您想跟随 Python 的计算,您可以使用 print {0.b}.format(key) 查看数字的二进制字符串表示形式。