在python中返回多个值时的不同结果(Cryptopal挑战)

2024-09-30 12:30:11 发布

您现在位置:Python中文网/ 问答频道 /正文


我正在研究cryptopals挑战(https://cryptopals.com/sets/1/challenges/3)的问题3(第1组)
我已经找到了密钥('x')并解密了消息('x'like a pound of bacon') 这是我的密码:

from hexToBase64 import hexToBinary
from fixedXOR import xorBuffers

def binaryToChar(binaryString):
    asciiValue = 0
    for i in range(int(len(binaryString))-1,-1,-1):
        if(binaryString[i] == '1'):
          asciiValue = asciiValue + 2**(7-i)
    return chr(asciiValue)

def decimalToBinary(number):
    binaryString = ""
    while (number != 0):
        bit = number % 2 
        binaryString = str(bit) + binaryString
        number = int(number/2)
    while(len(binaryString) < 8): 
        binaryString = "0" + binaryString
    return binaryString

def breakSingleByteXOR(cipherString):
    decryptedMess = ""
    lowestError = 10000
    realKey = ""
    for i in range(0,128):
        errorChar = 0 
        tempKey = decimalToBinary(i)
        tempMess = ""
        for j in range(0,len(cipherString),2):
            #Take each byte of the cipherString 
            cipherChar = hexToBinary(cipherString[j:j+2])
            decryptedChar = binaryToChar(xorBuffers(cipherChar,tempKey))
            asciiValue = ord(decryptedChar)
            if (not ((asciiValue >= 65) and (asciiValue <= 90)) \
               or ((asciiValue >= 90) and (asciiValue <= 122)) \
               or ( asciiValue == 32 )):
               # if the character is not one of the characters ("A-Z" or "a-z"
               # or " ") consider it as an "error" 
               errorChar += 1 
            tempMess = tempMess + decryptedChar
        if(errorChar < lowestError):
            lowestError = errorChar
            decryptedMess = tempMess
            realKey = chr(i)
    return (realKey,decryptedMess)



if __name__ == "__main__":
    print(breakSingleByteXOR("1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736")) 

问题是,当我使用函数breakSingleByteXOR返回一个值(decryptedMess)时,结果是“像一磅培根一样煮mcS”
但是当我用函数返回2个值时(如上面的代码-(key,decryptedMess)),我收到了一个奇怪的结果('x','cOOKING\x00mc\x07S\x00LIKE\x00A\x00POUND\x00OF\x00BACON'),有人能解释一下为什么会这样吗?

Tbh,我正在学习python,因为我正在做挑战,所以希望我不会用这些代码触发任何人。。。。如果有人能给我一些关于编写好python代码的建议,我也会非常感激
谢谢各位:D


Tags: orofinnumberforlenifdef
2条回答

打印字符串中出现差异的原因确实是print函数的一个怪癖。你知道吗

这个程序更深层次的问题是它没有产生正确的答案。这是因为试图确定解密字符是否在可接受范围内的大丑陋if是不正确的。你知道吗

这在两个方面是不正确的。第一个是(asciiValue >= 90)应该是(asciiValue >= 97)。编写所有这些表达式的更好方法是将它们表示为(asciiValue >= ord('a'))(asciiValue == ord(' '))等等,这样就避免了难以理解的数字,从而避免了这种错误。你知道吗

第二种方法是表达式没有正确分组。从他们的立场来看,他们是这样做的:

character is not in the range 'A' to 'Z',
    or character is in the range 'a' to 'z',
    or character is 'space',
        then count this as an error

所以一些应该是好的字符(特别是从'a'到'z'和空格)被认为是坏的。要修复此问题,需要重新处理圆括号,以便条件为:

character is not in the range 'A' to 'Z',
    and character is not in the range 'a' to 'z',
    and character is not space,
        then count this as an error

或者(这是你尝试的风格)

character is not (in the range 'A' to 'Z'
    or in the range 'a' to 'z'
    or a space)

我不会给你精确的表达式来修复这个程序,你自己来解决会更好。(处理这种复杂性的一个好方法是将其移到一个单独的函数中,该函数返回TrueFalse。这使得测试您的实现是否正确变得很容易,只需使用不同的字符调用函数并查看结果是否符合您的要求。)

当您得到正确的表达式时,您会发现程序发现了一个不同的“最佳密钥”,并且该密钥的解密字符串不包含任何行为与print异常的愚蠢越界字符。你知道吗

print函数是罪魁祸首—它在执行时将字符\x00\x07转换为ASCII值。具体来说,这只在将字符串传递给print函数时发生,而不是传递给iterable或其他对象(如tuple)。你知道吗

这是一个例子:

>>> s = 'This\x00string\x00is\x00an\x00\x07Example.'

>>> s
'This\x00string\x00is\x00an\x00\x07Example.'

>>> print(s)
This string is an Example.

如果要将字符串s添加到iterable(tuplesetlist)中,s将不会由print函数格式化:

>>> s_list = [s]
>>> print(s_list)  # List
['This\x00string\x00is\x00an\x00\x07Example.']

>>> print(set(s_list))  # Set
{'This\x00string\x00is\x00an\x00\x07Example.'}

>>> print(tuple(s_list))  # Tuple
('This\x00string\x00is\x00an\x00\x07Example.')

编辑

因为\x00\x07字节是ASCII控制字符,(\x00是NUL,\x07是BEL),所以不能用任何其他方式表示它们。因此,在不打印的情况下从字符串中删除这些字符的唯一方法之一是使用.replace()方法;但是如果终端将\x00字节视为空格,则必须使用s.replace('\x00', ' ')来获得相同的输出,这现在改变了字符串的真实内容。你知道吗

否则,在构建字符串时,您可以尝试实现一些逻辑来检查ASCII控制字符,或者不将它们添加到tempMess,或者添加不同的字符,如空格或类似字符。你知道吗

参考文献

ASCII维基:https://en.wikipedia.org/wiki/ASCII

Curses模块:https://docs.python.org/3.7/library/curses.ascii.html?highlight=ascii#module-curses.ascii(如果您希望实现任何逻辑,可能会很有用)。你知道吗

相关问题 更多 >

    热门问题