簡體   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-2025 STACKOOM.COM