[英]Different results when return multiple values in python (Cryptopal challenges)
I'm working on problem 3(set 1) of the cryptopals challenges ( https://cryptopals.com/sets/1/challenges/3 ) 我正在研究cryptopals挑战的问题3(set 1)( https://cryptopals.com/sets/1/challenges/3 )
I've already found the key ('x') and decrypted the message ('Cooking mcs like a pound of bacon') Here is my code: 我已经找到了密钥('x')并解密了消息('像一磅培根一样烹饪mcs')这是我的代码:
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"))
The problem is when I use the function breakSingleByteXOR to return one value (decryptedMess), it came out okay "cOOKING mcS LIKE A POUND OF BACON" 问题是,当我使用功能breakSingleByteXOR返回一个值(decryptedMess)时,结果“显示mcS像培根一样”没问题
But when I return 2 values with the function (as the code above - (key,decryptedMess)), I received a weird result ('x', 'cOOKING\\x00mc\\x07S\\x00LIKE\\x00A\\x00POUND\\x00OF\\x00BACON'), can anyboby explain to me why this is the case? 但是当我使用函数返回2个值时(如上面的代码-(key,decryptedMess)),我收到了一个奇怪的结果('x','cOOKING \\ x00mc \\ x07S \\ x00LIKE \\ x00A \\ x00POUND \\ x00OF \\ x00BACON') ,任何人都可以向我解释为什么会这样吗?
Tbh, I'm learning python as I'm doing the challenges so hopefully I dont trigger anyone with these code.... I'd also really appreciate it if anyone could give me some advices on writing good python code Tbh,我在学习python的同时也正面临挑战,因此希望我不会用这些代码触发任何人。...如果有人可以给我一些有关编写良好python代码的建议,我也将非常感谢
Thanks guys :D 谢谢大家:D
It's true that the reason for the difference in the printed string is a quirk of the print
function. 的确,打印字符串不同的原因是print
功能的怪癖。
The deeper problem with that program is that it's not producing the correct answer. 该程序的更深层问题是它无法产生正确的答案。 That's because the big ugly if
that tries to decide whether a decrypted character is in the acceptable range is incorrect. 那是因为if
试图确定解密的字符是否在可接受的范围内,那很丑陋if
这是不正确的。
It's incorrect in two ways. 这有两种错误。 The first is that (asciiValue >= 90)
should be (asciiValue >= 97)
. 第一个是(asciiValue >= 90)
应该是(asciiValue >= 97)
。 A better way to write all of those expressions, which would have avoided this error, is to express them as (asciiValue >= ord('a'))
and (asciiValue == ord(' '))
and so on, avoiding the inscrutable numbers. 编写所有这些表达式的更好方法(可以避免此错误)是将它们表示为(asciiValue >= ord('a'))
和(asciiValue == ord(' '))
,依此类推,避免使用难以理解的数字。
The second way is that the expressions are not properly grouped. 第二种方法是表达式未正确分组。 As they stand they do this: 当他们站立时,他们这样做:
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
so some of the characters that should be good (specifically 'a' through 'z' and space) are counted as bad. 因此,一些本应该不错的字符(特别是从“ a”到“ z”以及空格)被视为坏字符。 To fix, you need to rework the parentheses so that the condition is: 要解决此问题,您需要对括号进行重新处理,以使条件为:
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
or (this is style you were trying for) 或(您正在尝试的样式)
character is not (in the range 'A' to 'Z'
or in the range 'a' to 'z'
or a space)
I'm not going to give you the exact drop-in expression to fix the program, it'll be better for you to work it out for yourself. 我不会为您提供确切的插入式表达式来修复该程序,让您自己解决这个问题会更好。 (A good way to deal with this kind of complexity is to move it into a separate function that returns True
or False
. That makes it easy to test that your implementation is correct, just by calling the function with different characters and seeing that the result is what you wanted.) (处理这种复杂性的一种好方法是将其移动到一个返回True
或False
的单独函数中。通过调用具有不同字符的函数并查看结果,可以轻松地测试实现是否正确是你想要的。)
When you get the correct expression, you'll find that the program discovers a different "best key" and the decrypted string for that key contains no goofy out-of-range characters that behave strangely with print
. 当您获得正确的表达式时,您会发现程序发现了一个不同的“最佳密钥”,并且该密钥的解密字符串不包含愚蠢的超出范围的字符,这些字符在print
上的行为异常。
The print
function is the culprit - it is translating the characters \\x00
and \\x07
to ASCII values when executed. print
功能是罪魁祸首-执行时它将\\x00
和\\x07
字符\\x07
为ASCII值。 Specifically, this only occurs when passing a string to the print
function, not an iterable or other object (like your tuple
). 具体来说,只有在将字符串传递给print
函数时,才会发生这种情况,而不是将迭代对象或其他对象(例如tuple
)传递给它。
This is an example: 这是一个例子:
>>> s = 'This\x00string\x00is\x00an\x00\x07Example.'
>>> s
'This\x00string\x00is\x00an\x00\x07Example.'
>>> print(s)
This string is an Example.
If you were to add the string s
to an iterable ( tuple
, set
, or list
), s
will not be formatted by the print
function: 如果要将字符串s
添加到可迭代( tuple
, set
或list
)中,则将不会通过print
函数set
s
格式:
>>> 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.')
Because the \\x00
and \\x07
bytes are ASCII control characters, ( \\x00
being NUL and \\x07
being BEL), you can't represent them in any other way. 因为\\x00
和\\x07
字节是ASCII控制字符( \\x00
是NUL, \\x07
是BEL),所以您无法用其他任何方式表示它们。 So one of the only ways you could strip these characters from the string without printing would be to use the .replace()
method; 因此,无需打印就可以从字符串中剥离这些字符的唯一方法之一就是使用.replace()
方法。 but given \\x00
bytes are being treated as spaces by the terminal, you would have to use s.replace('\\x00', ' ')
to get the same output, which has now changed the true content of the string. 但是如果终端将\\x00
字节视为空格,则必须使用s.replace('\\x00', ' ')
来获得相同的输出,该输出现在更改了字符串的真实内容。
Otherwise when building the string; 否则在构建字符串时; you could try and implement some logic to check for ASCII control characters and either not add them to tempMess
or add a different character like a space or similar. 您可以尝试实现一些逻辑来检查ASCII控制字符,而不是将它们添加到tempMess
或不添加其他字符(例如空格或类似字符)。
ASCII Wiki: https://en.wikipedia.org/wiki/ASCII ASCII Wiki: https : //en.wikipedia.org/wiki/ASCII
Curses Module: https://docs.python.org/3.7/library/curses.ascii.html?highlight=ascii#module-curses.ascii (Might be useful if you wish to implement any logic). 诅咒模块: https ://docs.python.org/3.7/library/curses.ascii.html?highlight = ascii#module- curses.ascii (如果您希望实现任何逻辑,可能会很有用)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.