繁体   English   中英

类型错误:<<:'str' 和 'int' 的操作数类型不受支持

[英]TypeError: unsupported operand type(s) for <<: 'str' and 'int'

谁能给我一些关于我 10 岁儿子正在尝试的 Python 项目的广泛指导? 我很少寻找特定的编码解决方案,但我希望这是一个提出问题的好地方。 我想看看我儿子是否正在着手对他的编码项目进行实际操作,以及是否有一种相对简单的方法可以让他学习正确的步骤。 或者,这对于一个喜欢阅读和尝试各种编码项目只是为了好玩的 10 岁孩子来说是不合时宜的? 如您所见,我不是编码员,对此类项目知之甚少,因此将不胜感激!

我儿子喜欢密码学,他告诉我他尝试了下面的 Python 代码。 他希望构建一个类似海绵的功能来加密按摩,使其无法被解密。 这受到他的书“Serious Cryptography”(J. Aumasson 着)中标题为“基于排列的哈希函数:海绵函数”的部分的启发。 当他运行他编写的代码时,他收到错误消息“类型错误:<<:'str'和'int'不受支持的操作数类型”(请参阅​​他在代码下方终端中的交互)。

非常感谢! 亚历山大

这是他的代码:

import math
import textwrap

plaintext = raw_input("The value to be hashed: ") # Get the user to input the data to be hashed
nonce = raw_input("The nonce to be used: ")       # Get the user to input the nonce to be used
key = raw_input("The key to be used: ")           # Get the user to input the key to be used
blocks = textwrap.wrap(plaintext, 16)             # Split the string into 128-bit blocks
if len(blocks[len(blocks)-1]) < 16:               # Check if the last block is less than 128 bits
    while len(blocks[len(blocks)-1]) < 16:        # Keep iterating the following code
        blocks[len(blocks)-1] += "."              # Add padding to the end of the block to make it 128-bit
sponge = nonce                                    # Set the sponge's initial state to that of the nonce
for j in blocks:                                  # Absorb all of the blocks
    sponge = (sponge << 128) + j                  # Concatenate the current sponge value and the block
    sponge = textwrap.wrap(sponge, 128)           # Convert the sponge into 128-bit blocks
    for z in sponge:                              # Keep iterating the following code
        z = z^j                                   # XOR the sponge block with the message block 
sponge = join(sponge)                             # Convert the blocks back into a string
sponge = textwrap.wrap(sponge, len(key)*8)        # Convert the sponge into blocks with the same length of the key
output = sponge                                   # Create a new variable to save space
del nonce, blocks                                 # Delete variables to save space
while len(output) > 1:                            # Keep iterating the following code
    output[1] = output[1]^output[0] >> output[0]  # XOR the second element with the first, then shift forward
    del output[0]                                 # Delete the first element, so it can repeat again
tag = ((output^plaintext) <<< sponge) + output    # Generate an authentication tag. That's not overkill, is it?
print output                                      # Oh yeah, just print it in hexadecimal, I dunno how to

当他在终端运行脚本时,这是交互:

  • 要散列的值:abcioagdsbvasizfuvbosuif
  • 要使用的随机数:iugzaliuglieas
  • 要使用的密钥:asljdgadskj

例外:

Traceback (most recent call last):
  File "DarkKnight-Sponge.py", line 13, in <module>
    sponge = (sponge << 128) + j                  # Concatenate the current sponge value and the block
TypeError: unsupported operand type(s) for <<: 'str' and 'int'

恭喜你儿子! 这个项目对我来说看起来很现实。 我能想到的唯一雄心勃勃的事情是直接钻研像<<^这样的按位运算符,而不是尝试对字符序列实现相应的操作。 位运算符有时看起来像算术黑魔法,因为它们操纵数字的内部二进制表示,我们不像数字的十进制表示或文本那样熟悉。

了解错误信息

TypeError: unsupported operand type(s) for <<: 'str' and 'int'

这个错误非常简单:它表示无法执行sponge << 128操作,因为sponge是一个str ,即(字符)字符串,即文本,而 128 是一个 int,即整数。

想象一下,如果您让计算机计算"three" + 2 它会返回一个错误,因为+需要两个数字,但"three"是一个字符串,而不是一个数字。 同样,如果你让计算机计算"327" + 173 ,它会返回一个错误,因为"327"是文本,而不是数字。

了解发生错误的线路

运算符<<左移运算符。 它将一个数字向左移动一定数量的位。 计算机以二进制表示形式存储数字; 我们人类更习惯于十进制表示,所以让我们用“左移数字”操作来做一个比喻。 “向左移动一个数字”意味着将它乘以 10 的幂。例如,138 向左移动两次就是 13800。我们在右边用零填充。 在二进制表示中,bitshift 的工作原理相同,但改为乘以 2 的幂。 二进制表示的 138 是1110110 将它向左移动两次给出111011000 ,这与将其乘以100 (即 4)相同。

如果spongej都是数字,并且j小于 2^128,则该行:

sponge = (sponge << 128) + j                  # Concatenate the current sponge value and the block

sponge向左移动 128 位,然后将小于 128 位的数字添加到结果中。 实际上,这是将sponge位与j位连接起来。 回到我们的十进制类比:如果x是一个数字,而y是一个小于 100 的数字,那么数字x * 100 + y是通过连接xy的数字获得的数字。 例如, 1374 * 100 + 56 = 137456

解决问题

我没有读过启发这段代码的密码学书籍,所以我只是从这里开始猜测。

我的理解是这本书期望plaintextnoncekey是数字。 但是,在您儿子的代码中,它们都是文本。 这两种类型的对象之间的区别并非不可调和。 无论如何,在计算机的内存中,所有内容都存储为位序列。 数字是位序列; 一个字符串是一个字符序列,每个字符本身就是一个短的位序列。

我看到三种可能性:(1)在执行操作之前将所有文本转换为数字; (2) 调整操作,使它们可以应用于字符串而不是整数; (3) 将所有文本转换为仅包含字符01字符串并调整操作,以便将它们应用于此类序列。 密码算法在现实世界中的高效实现肯定都选择了第二个选项。 第三个选项显然是三个选项中效率较低的一个,但出于学习目的,这是一个可能的选项。

看看你的代码,我注意到所有使用的操作都是关于序列的操作,而不是关于算术运算。 正如我提到的, (sponge << 128) + j是两个位序列的串联。 稍后在代码^使用的按位异或运算期望两个长度相同的位序列,并返回一个长度相同的序列,在两个序列具有不同位的每个位置处为1 ,在两个序列具有不同位的每个位置处返回0序列具有相同的位。 例如, 00010110 ^ 00110111 = 00100001因为第三位和第八位不同,但所有其他位都相等。

将文本转换为 int

要将文本转换为数字(我称之为选项 2),您可以用这些行替换代码的前三行:

plaintext_string = raw_input("The value to be hashed: ") # Get the user to input the data to be hashed
nonce_string = raw_input("The nonce to be used: ")       # Get the user to input the nonce to be used
key_string = raw_input("The key to be used: ")           # Get the user to input the key to be used

def string_to_int(txt):
  number = 0
  for c in txt:
    number = (number << 8) + ord(c)
  return number

plaintext = string_to_int(plaintext_string)
nonce = string_to_int(plaintext_string)
key = string_to_int(key_string)

这是如何工作的:python 函数ord每个 ascii 字符c映射到一个 8 位数字。 8 位块使用公式number = (number << 8) + ord(c) ,您可以从上面的讨论中识别出来。

这不足以使您的代码正常工作,因为之后直接使用的textwrap.wrap()函数需要一个字符串,而不是一个 int。 一种可能性是用自定义函数text_to_intblocks()替换textwrap.wrap()函数:

def string_to_intblocks(txt, blocksize):
  blocks = []
  block_number = 0
  for i,c in enumerate(txt):
    block_number = (block_number << 8) + ord(c)
    if i % blocksize == 0:
        blocks.append(block_number)
        block_number = 0
  return blocks

然后将blocks = textwrap.wrap(plaintext, 16)替换为blocks = string_to_intblocks(plaintext_string, 16)

这仍然不足以修复您儿子的代码。 我确信以下六行中存在逻辑错误,尽管修复它需要比我目前对算法有更好的理解:

sponge = nonce                                    # Set the sponge's initial state to that of the nonce
for j in blocks:                                  # Absorb all of the blocks
    sponge = (sponge << 128) + j                  # Concatenate the current sponge value and the block
    sponge = textwrap.wrap(sponge, 128)           # Convert the sponge into 128-bit blocks
    for z in sponge:                              # Keep iterating the following code
        z = z^j                                   # XOR the sponge block with the message block
sponge = join(sponge)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM