逆向工程凯撒密码
Reverse engineer Ceasar cipher
我进行了逆向工程解密,但没有得到预期的结果。
例如输入
Lipps${svph%
偏移量为 4 的结果应该是
Hello World!
但我明白了
ello´world³
我做错了什么?
code = input("Enter text to decrypt: ")
distance = int(input("Enter number of offset: "))
plainText = ''
for ch in code:
ordValue = ord(ch)
cipherValue = ordValue - distance
if cipherValue < ord('a'):
cipherValue = ord('z') - \
(distance - (ord('a') - ordValue + 1))
plainText += chr(cipherValue)
print(plainText)
好的,我让它在 a-z 上工作,并给了你一个小的测试框架 enter/check 自动而不是每次都输入它。
def dowork(code, distance, lower, upper):
bounddown, boundup = ord(lower), ord(upper)
plaintext = ""
for ch in code:
ordValue = ord(ch)
cipherValue = ordValue - distance
if cipherValue < bounddown:
cipherValue = boundup - bounddown - ordValue +1
plaintext += chr(cipherValue)
return plaintext
dataexp = [
(("jgnnq",2, 'a', 'z'),"hello"),
]
for input_, exp in dataexp:
got = dowork(*input_)
msg = "exp:%s:%s:got for %s" % (exp, got, inp)
if exp == got:
print("good! %s" % msg)
else:
print("bad ! %s" % msg)
这会打印
good! exp:hello:hello:got for ('jgnnq', 2, 'a', 'z')
现在您需要做的就是向 dataexp 列表添加一个额外的项目,例如
(("Lipps${svph%", 4, <lowerbound>, <upperbound char>), "Hello World!")
一旦你确定了上限和下限,它就应该可以工作了。请注意,我不知道 caesar 代码,我只是直接复制了你的代码,但对其进行了一些重组。
*_input
所做的是获取该元组(或多或少是一个列表)中的这 4 个值,并将它们分配给 dowork
函数中的 code, distance, lower, upper
。
lower
对应于代码中的 a
,upper
对应于 z
.
exp 是您所期望的,exp == got
只是检查函数返回的内容是否正确。一旦你得到正确的功能,它应该适用于 both 我的简单 a-z
,2 距离,hello
测试和你更复杂的 4 距离,但包括标点符号
上下限
你的 2 个字符串,输入和输出,是 Lipps${svph%
和 Hello World!
。这意味着所有这些字符都需要落在您的上限和下限值之内,对吗?所以所有这些的最小顺序位置是你的 lower
,最大顺序是你的 upper
。现在,我不是 Cryptonomicon 的那个人,我记不起 ord(a) < ord(A) 与否,更不用说标点符号了。所以你必须好好修改一下,这就是为什么我的测试只基于小写字母。不过我会加 0-9。
最终版本
这不需要您确定将哪个字符放在下界和哪个字符上界。我们采用 lower = 32(可打印字符的开始),upper = 255。这样标点符号、大小写、数字、它们的 ord 值就不再重要了。
#full ASCII range, you can go to town on entering whatever you want
bounddown, boundup = 32, 255
plaintext = ""
for ch in code:
ordValue = ord(ch)
cipherValue = ordValue - distance
if cipherValue < bounddown:
cipherValue = boundup - bounddown - ordValue +1
plaintext += chr(cipherValue)
下面是输入一定范围内的字符(本例a-z
)进行加解密的实现。您可以根据需要将其调整为其他范围。
def caesar(text, offset, decrypt=False):
lower_bound, upper_bound = ord('a'), ord('z')
if decrypt:
offset = (upper_bound - lower_bound + 1) - offset
result = ''
for t in text:
o = ord(t)
if lower_bound <= o <= upper_bound:
new_t = o + offset
if new_t > upper_bound:
new_t = (new_t % upper_bound) + lower_bound - 1
result += chr(new_t)
else:
result += t
return result
那么您可以拨打:
caesar(caesar('hello world!', 2,), 2, True)
# => 'hello world!'
我进行了逆向工程解密,但没有得到预期的结果。
例如输入
Lipps${svph%
偏移量为 4 的结果应该是
Hello World!
但我明白了
ello´world³
我做错了什么?
code = input("Enter text to decrypt: ")
distance = int(input("Enter number of offset: "))
plainText = ''
for ch in code:
ordValue = ord(ch)
cipherValue = ordValue - distance
if cipherValue < ord('a'):
cipherValue = ord('z') - \
(distance - (ord('a') - ordValue + 1))
plainText += chr(cipherValue)
print(plainText)
好的,我让它在 a-z 上工作,并给了你一个小的测试框架 enter/check 自动而不是每次都输入它。
def dowork(code, distance, lower, upper):
bounddown, boundup = ord(lower), ord(upper)
plaintext = ""
for ch in code:
ordValue = ord(ch)
cipherValue = ordValue - distance
if cipherValue < bounddown:
cipherValue = boundup - bounddown - ordValue +1
plaintext += chr(cipherValue)
return plaintext
dataexp = [
(("jgnnq",2, 'a', 'z'),"hello"),
]
for input_, exp in dataexp:
got = dowork(*input_)
msg = "exp:%s:%s:got for %s" % (exp, got, inp)
if exp == got:
print("good! %s" % msg)
else:
print("bad ! %s" % msg)
这会打印
good! exp:hello:hello:got for ('jgnnq', 2, 'a', 'z')
现在您需要做的就是向 dataexp 列表添加一个额外的项目,例如
(("Lipps${svph%", 4, <lowerbound>, <upperbound char>), "Hello World!")
一旦你确定了上限和下限,它就应该可以工作了。请注意,我不知道 caesar 代码,我只是直接复制了你的代码,但对其进行了一些重组。
*_input
所做的是获取该元组(或多或少是一个列表)中的这 4 个值,并将它们分配给 dowork
函数中的 code, distance, lower, upper
。
lower
对应于代码中的 a
,upper
对应于 z
.
exp 是您所期望的,exp == got
只是检查函数返回的内容是否正确。一旦你得到正确的功能,它应该适用于 both 我的简单 a-z
,2 距离,hello
测试和你更复杂的 4 距离,但包括标点符号
上下限
你的 2 个字符串,输入和输出,是 Lipps${svph%
和 Hello World!
。这意味着所有这些字符都需要落在您的上限和下限值之内,对吗?所以所有这些的最小顺序位置是你的 lower
,最大顺序是你的 upper
。现在,我不是 Cryptonomicon 的那个人,我记不起 ord(a) < ord(A) 与否,更不用说标点符号了。所以你必须好好修改一下,这就是为什么我的测试只基于小写字母。不过我会加 0-9。
最终版本
这不需要您确定将哪个字符放在下界和哪个字符上界。我们采用 lower = 32(可打印字符的开始),upper = 255。这样标点符号、大小写、数字、它们的 ord 值就不再重要了。
#full ASCII range, you can go to town on entering whatever you want
bounddown, boundup = 32, 255
plaintext = ""
for ch in code:
ordValue = ord(ch)
cipherValue = ordValue - distance
if cipherValue < bounddown:
cipherValue = boundup - bounddown - ordValue +1
plaintext += chr(cipherValue)
下面是输入一定范围内的字符(本例a-z
)进行加解密的实现。您可以根据需要将其调整为其他范围。
def caesar(text, offset, decrypt=False):
lower_bound, upper_bound = ord('a'), ord('z')
if decrypt:
offset = (upper_bound - lower_bound + 1) - offset
result = ''
for t in text:
o = ord(t)
if lower_bound <= o <= upper_bound:
new_t = o + offset
if new_t > upper_bound:
new_t = (new_t % upper_bound) + lower_bound - 1
result += chr(new_t)
else:
result += t
return result
那么您可以拨打:
caesar(caesar('hello world!', 2,), 2, True)
# => 'hello world!'