首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TypeError:不支持<<的操作数类型:'str‘和'int’

TypeError:不支持<<的操作数类型:'str‘和'int’
EN

Stack Overflow用户
提问于 2020-09-02 10:34:55
回答 1查看 1.2K关注 0票数 1

有谁能为我10岁的儿子正在尝试的Python项目提供一些广泛的指导呢?我不太想寻找具体的编码解决方案,但我希望这是一个问这个问题的好地方。我想知道的是,我的儿子是否对他的编码项目有所了解,以及是否有一个相对简单的方法让他学习正确的步骤。或者,对于一个10岁喜欢阅读和尝试各种编码项目只是为了好玩的人来说,这是不可能的吗?正如你所看到的,我不是一个程序员,对这类项目知之甚少,所以我会感激你的耐心和善意!

我儿子对密码学很感兴趣,他告诉我他尝试了下面的Python代码。他希望建立一个类似海绵的功能来加密按摩,使其无法解密。这是受他的著作“严肃密码学”(J.Aumasson)中的一个章节的启发,标题为“基于排列的散列函数:海绵函数”。当他运行他编写的代码时,他会得到错误消息"TypeError:<<:'str‘和’int‘的不受支持的操作数类型(参见代码下面终端中的交互)。

非常感谢!亚历山大

这是他的密码:

代码语言:javascript
复制
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

  • The当前要使用的值:要使用的iugzaliuglieas

  • The键: asljdgadskj

例外情况:

代码语言:javascript
复制
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'
EN

回答 1

Stack Overflow用户

发布于 2020-09-02 11:25:13

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

理解错误信息

代码语言:javascript
复制
TypeError: unsupported operand type(s) for <<: 'str' and 'int'

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

想象一下,如果您要求计算机计算"three" + 2。它将返回一个错误,因为+需要两个数字,但是"three"是一个字符串,而不是数字。类似地,如果您要求计算机计算"327" + 173,它将返回一个错误,因为"327"是文本,而不是数字。

了解发生错误的行

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

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

代码语言:javascript
复制
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)调整操作,使它们可以应用于字符串而不是ints;(3)将所有文本转换为仅包含字符01的字符串,并对操作进行调整,以便将它们应用于这些序列。在现实世界中,密码算法的高效实现无疑都选择了第二种方案。第三种选择显然是这三种方法中效率较低的,但就学习目的而言,这是一种可能的选择。

查看您的代码,我注意到所有使用的操作都是关于对序列的操作,而不是关于算术操作。正如我所提到的,(sponge << 128) + j是两个位序列的级联。代码中稍后使用的按位xor操作需要两个相同长度的位序列,并在两个序列具有不同比特的每个位置返回与1相同长度的序列,在两个序列具有相同比特的每个位置返回0。例如,00010110 ^ 00110111 = 00100001,因为第三位和第八位是不同的,但是所有其他位都是相等的。

将文本转换为int

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

代码语言:javascript
复制
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)

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

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

代码语言:javascript
复制
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)

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

代码语言:javascript
复制
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)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63703737

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档