简体   繁体   English

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

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

Could anyone please give me some broad guidance for a Python project that my 10 year-old son is trying?谁能给我一些关于我 10 岁儿子正在尝试的 Python 项目的广泛指导? I'm looking less for specific coding solutions, but I hope this is a good place to ask the question.我很少寻找特定的编码解决方案,但我希望这是一个提出问题的好地方。 What I'd like is to see if my son is on to something that's realistic with his coding project and if there's a relatively straightforward way for him to learn the right steps.我想看看我儿子是否正在着手对他的编码项目进行实际操作,以及是否有一种相对简单的方法可以让他学习正确的步骤。 Or is this something that's just out of the league for a 10 year-old who loves to read about and try various coding projects just for fun?或者,这对于一个喜欢阅读和尝试各种编码项目只是为了好玩的 10 岁孩子来说是不合时宜的? As you can see I'm not a coder and know very little about this sort of project, so some patience and good will would be appreciated!如您所见,我不是编码员,对此类项目知之甚少,因此将不胜感激!

My son is into cryptography and he's telling me he tried the Python code below.我儿子喜欢密码学,他告诉我他尝试了下面的 Python 代码。 He hopes to build a sponge-like function to encrypt a massage so that it can't be decrypted.他希望构建一个类似海绵的功能来加密按摩,使其无法被解密。 This is inspired by a section in his book "Serious Cryptography" (by J. Aumasson) with the title "Permutation-based Hash Functions: Sponge Functions".这受到他的书“Serious Cryptography”(J. Aumasson 着)中标题为“基于排列的哈希函数:海绵函数”的部分的启发。 When he runs the code that he wrote, he gets the error message "TypeError: unsupported operand type(s) for <<: 'str' and 'int'" (see his interaction in the terminal below the code).当他运行他编写的代码时,他收到错误消息“类型错误:<<:'str'和'int'不受支持的操作数类型”(请参阅​​他在代码下方终端中的交互)。

Thanks a lot!非常感谢! Alexander亚历山大

Here's his code:这是他的代码:

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

When he runs the script in the terminal, this is the interaction:当他在终端运行脚本时,这是交互:

  • The value to be hashed: abcioagdsbvasizfuvbosuif要散列的值:abcioagdsbvasizfuvbosuif
  • The nonce to be used: iugzaliuglieas要使用的随机数:iugzaliuglieas
  • The key to be used: asljdgadskj要使用的密钥:asljdgadskj

The exception:例外:

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'

Congratulations to your son!恭喜你儿子! The project looks realistic to me.这个项目对我来说看起来很现实。 The only ambitious thing I can think of was delving directly into bitwise operators like << and ^ instead of trying to implement the corresponding operations on sequences of characters.我能想到的唯一雄心勃勃的事情是直接钻研像<<^这样的按位运算符,而不是尝试对字符序列实现相应的操作。 Bitwise operators sometimes look like arithmetic dark magic because they manipulate the internal binary representation of numbers, which we are not as familiar with as a number's decimal representation or a text.位运算符有时看起来像算术黑魔法,因为它们操纵数字的内部二进制表示,我们不像数字的十进制表示或文本那样熟悉。

Understanding the error message了解错误信息

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

This error is pretty straightforward: it says the operation sponge << 128 cannot be performed, because sponge is an str , ie, a (character) string, ie, it's text, whereas 128 is an int, ie, an integer number.这个错误非常简单:它表示无法执行sponge << 128操作,因为sponge是一个str ,即(字符)字符串,即文本,而 128 是一个 int,即整数。

Imagine if you asked the computer to calculate "three" + 2 .想象一下,如果您让计算机计算"three" + 2 It would return an error, because + expects two numbers, but "three" is a string, not a number.它会返回一个错误,因为+需要两个数字,但"three"是一个字符串,而不是一个数字。 Similarly, if you asked the computer to calculate "327" + 173 , it would return an error, because "327" is text, not a number.同样,如果你让计算机计算"327" + 173 ,它会返回一个错误,因为"327"是文本,而不是数字。

Understanding the line on which the error happened了解发生错误的线路

The operator << is the leftwise bitshift operator.运算符<<左移运算符。 It shifts a number to the left by a certain amount of bits.它将一个数字向左移动一定数量的位。 Computers store numbers in binary representation;计算机以二进制表示形式存储数字; we humans are more used to decimal representation, so let's make an anology with a "leftwise digit-shift" operation.我们人类更习惯于十进制表示,所以让我们用“左移数字”操作来做一个比喻。 "Shifting a number to the left" would mean multiplying it by a power of 10. For instance, 138 shifted to the left twice would be 13800. We padded with zeroes on the right. “向左移动一个数字”意味着将它乘以 10 的幂。例如,138 向左移动两次就是 13800。我们在右边用零填充。 In binary representation, bitshift works the same, but multiplies by a power of 2 instead.在二进制表示中,bitshift 的工作原理相同,但改为乘以 2 的幂。 138 in binary representation is 1110110 ;二进制表示的 138 是1110110 shifting it to the left twice gives 111011000 , which is the same as multiplying it by 100 (which is 4).将它向左移动两次给出111011000 ,这与将其乘以100 (即 4)相同。

If sponge and j are both numbers, and j is less than 2^128, then the line:如果spongej都是数字,并且j小于 2^128,则该行:

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

shifts sponge to the left by 128 bits, then adds a number less than 128 bits to the result.sponge向左移动 128 位,然后将小于 128 位的数字添加到结果中。 Effectively, this is concatenating the bits of sponge with the bits of j .实际上,这是将sponge位与j位连接起来。 To come back to our decimal analogy: if x is a number, and y is a number less than 100, then the number x * 100 + y is the number obtained by concatenating the digits of x and y .回到我们的十进制类比:如果x是一个数字,而y是一个小于 100 的数字,那么数字x * 100 + y是通过连接xy的数字获得的数字。 For instance, 1374 * 100 + 56 = 137456 .例如, 1374 * 100 + 56 = 137456

Fixing the issue解决问题

I haven't read the cryptography book that inspired this code, so I am only guessing from here on.我没有读过启发这段代码的密码学书籍,所以我只是从这里开始猜测。

My understanding is that the book expects plaintext , nonce and key to be numbers.我的理解是这本书期望plaintextnoncekey是数字。 However, in your son's code, they are all text.但是,在您儿子的代码中,它们都是文本。 The distinction between those two types of objects is not irreconcilable.这两种类型的对象之间的区别并非不可调和。 Inside a computer's memory, everything is stored as sequences of bits anyway.无论如何,在计算机的内存中,所有内容都存储为位序列。 A number is a sequence of bits;数字是位序列; a string is a sequence of characters, and each character is itself a short sequence of bits.一个字符串是一个字符序列,每个字符本身就是一个短的位序列。

I see three possibilities: (1) convert all the text to numbers before performing the operations;我看到三种可能性:(1)在执行操作之前将所有文本转换为数字; (2) adapt the operations so they can be applied to strings instead of ints; (2) 调整操作,使它们可以应用于字符串而不是整数; (3) convert all the text to strings containing only the characters 0 and 1 and adapt the operations so they can be applied to such sequences. (3) 将所有文本转换为仅包含字符01字符串并调整操作,以便将它们应用于此类序列。 Real-world efficient implementations of cryptography algorithms most certainly all choose the second option.密码算法在现实世界中的高效实现肯定都选择了第二个选项。 The third option is obviously the less efficient of the three, but for learning purposes it's a possible option.第三个选项显然是三个选项中效率较低的一个,但出于学习目的,这是一个可能的选项。

Looking at your code, I notice all operations used are about manipulation of sequences, rather than about arithmetic operations.看看你的代码,我注意到所有使用的操作都是关于序列的操作,而不是关于算术运算。 As I mentioned, (sponge << 128) + j is the concatenation of two sequences of bits.正如我提到的, (sponge << 128) + j是两个位序列的串联。 The bitwise xor operation which is used later in the code ^ expects two sequences of bits of the same length, and returns a sequence of the same length with 1 at every position where the two sequences had distinct bits and 0 at every position where the two sequences had equal bits.稍后在代码^使用的按位异或运算期望两个长度相同的位序列,并返回一个长度相同的序列,在两个序列具有不同位的每个位置处为1 ,在两个序列具有不同位的每个位置处返回0序列具有相同的位。 For instance, 00010110 ^ 00110111 = 00100001 because the third and eighth bits are distinct, but all the other bits are equal.例如, 00010110 ^ 00110111 = 00100001因为第三位和第八位不同,但所有其他位都相等。

Converting text to int将文本转换为 int

To convert text into numbers (which I called option 2), you could replace the first three lines of the code with those lines:要将文本转换为数字(我称之为选项 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)

How this works: every ascii character c is mapped to an 8-bit number by the python function ord .这是如何工作的:python 函数ord每个 ascii 字符c映射到一个 8 位数字。 The 8-bit blocks are concatenated using the formula number = (number << 8) + ord(c) , which you can recognize from the above discussion. 8 位块使用公式number = (number << 8) + ord(c) ,您可以从上面的讨论中识别出来。

This is not sufficient to make your code work properly, as the textwrap.wrap() function used directly afterwards expects a string, not an int.这不足以使您的代码正常工作,因为之后直接使用的textwrap.wrap()函数需要一个字符串,而不是一个 int。 A possibility is to replace the textwrap.wrap() function by a custom function text_to_intblocks() :一种可能性是用自定义函数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

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

This is still not sufficient to fix your son's code.这仍然不足以修复您儿子的代码。 I am convinced there is a logic error in the following six lines, although fixing it would require a better understanding of the algorithm than I currently have:我确信以下六行中存在逻辑错误,尽管修复它需要比我目前对算法有更好的理解:

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