使用 Python 在 RSA 算法中将文本转换为数字时无法修复错误
Error I can't fix while converting text to number in RSA algorithm using Python
我的老师给我布置了一项任务,要求我编写一个 python 程序,该程序可以使用 RSA 算法加密消息。所以要做到这一点,我必须创建将文本转换为数字的函数,然后能够操纵这些数字并对其进行加密。但是为了测试我是否正确加密了它,我还设计了一个解密函数,我也在底部做了这个函数。加密函数和 Ascii 函数之间的所有函数都可以在其他函数中使用(此时你会意识到我喜欢将我的代码划分为函数)。我的代码的问题是当我 运行 它
时我不断收到这个错误
Traceback (most recent call last):
File "D:/Applications/Python/Ziad/RSA algotrithim V2.py", line 127, in <module>
print(decrypt(Phi_N, e, encrypted))
File "D:/Applications/Python/Ziad/RSA algotrithim V2.py", line 115, in decrypt
return Num2Text(message)
File "D:/Applications/Python/Ziad/RSA algotrithim V2.py", line 58, in Num2Text
return Ascii2Text(Num2Ascii(message))
File "D:/Applications/Python/Ziad/RSA algotrithim V2.py", line 17, in Ascii2Text
text = text + chr(int(char))
ValueError: invalid literal for int() with base 10: '1.0'
>>> ================================ RESTART =================
我单独测试了所有功能,看看它们是否有效。我重新检查了我的加密和解密功能,它们应该可以工作。出于某种原因,我认为我的问题出在我的解密函数上,因为我认为它给了我十进制数,但是我在互联网上搜索了算法,我看到的所有网站都使用相同的算法。请帮助我找到问题所在,我通常不会向其他人寻求帮助(这是我在 Whosebug 上的第一个问题)并且我已经为此伤脑筋 3 周了。
import math
def Text2Ascii(message):
Ascii = ""
for count in range(len(message)):
if len(str(ord(message[count]))) <= 2:
Ascii = Ascii + "0" +str(ord(message[count])) + " "
else:
Ascii = Ascii + str(ord(message[count])) + " "
return Ascii
def Ascii2Text(message):
text = ""
char = ""
for count in range(len(message)):
if message[count] == " ":
text = text + chr(int(char))
char = ""
else:
char = char + message[count]
text = text + chr(int(char))
return text
def Ascii2Num(message):
Num = ""
for count in range(len(message)):
if message[count] != " ":
Num = Num + message[count]
return int(Num)
def Num2Ascii(message):
Ascii = ""
char = ""
message = str(message)
if len(message)%3 == 0:
for count in range(len(message)):
if (count+1)%3 == 0:
char = char + message[count]
Ascii = Ascii + char + " "
char = ""
else:
char = char + message[count]
else:
Ascii = "0"
for count in range(len(message)):
if (count+2)%3 == 0:
char = char + message[count]
Ascii = Ascii + char + " "
char = ""
else:
char = char + message[count]
return Ascii
def Text2Num(message):
return Ascii2Num(Text2Ascii(message))
def Num2Text(message):
return Ascii2Text(Num2Ascii(message))
def exponent(number, power):
answer = 1
for count in range(power):
answer = number*answer
return answer
def primeCheck(number):
if number == 2:
prime = True
elif number <= 1:
prime = False
else:
n = math.sqrt(number)
n = math.ceil(n)
for count in range(2,n+1):
if number%count == 0:
prime = False
break
else:
prime = True
return prime
def factors(number):
answer = []
if primeCheck(number)== True:
answer = [number,1]
else:
for count in range(1,number+1):
if number%count == 0:
answer.append(count)
return answer
def phi(number):
answer = number
if primeCheck(number) == True:
answer = number - 1
else:
factor = factors(number)
for count in factor:
for count2 in factors(count):
if count2 == count:
answer = answer -1
break
return answer
def encrypt(N,e):
message = input("What is the message you need encrypted?\n")
message = Text2Num(message)
encrypted = (message ** e)%N
return encrypted
def decrypt(Phi_N, e,encrypted):
k = 3
d = (Phi_N*k + 1)/e
message = encrypted ** d
return Num2Text(message)
p = int(input("Give me a prime number: "))
while primeCheck(p) == False:
p = int(input("Give me a prime number: "))
q = int(input("Give me a prime number: "))
while primeCheck(q) == False:
q = int(input("Give me a prime number: "))
N = q*p
Phi_N = (q-1)*(p-1)
e = int(input("Enter your encryption key: "))
encrypted = encrypt(N,e)
print(decrypt(Phi_N, e, encrypted))
您遇到的特定错误是由两个因素共同造成的:
第一个也是最容易解决的问题是您在 Ascii2Text 中分解字符串的方式:
def Ascii2Text(message):
text = ""
char = ""
for count in range(len(message)):
**if message[count] == " ":** #<-- This line is not robust
text = text + chr(int(char))
char = ""
else:
char = char + message[count]
text = text + chr(int(char))
return text
问题是,随着 Num2Ascii 的实现方式,您最终会得到一个尾随 space,这会导致您在循环结束时尝试将空字符串转换为 int,并且ascii 化消息中前面的非 space 个字符。我建议要么大声扼杀无效字符,要么至少不要尝试将它们附加到您尝试在下一行转换为 int 的 "char" 字符串。
这给我们带来了下一个问题:您甚至一开始就有非数字字符。导致您看到的失败的小数点来自 d 的错误计算。 d 应该是 modular multiplicative inverse of e, and it will always be an integer when calculated correctly. Yours, however, was coming up as a decimal more often than not when I ran this code. This is one of the bits of RSA that people choke on most often, since it involves manipulating the modulo operator in ways that people without a math background aren't typically taught. One of the more common, efficient ways to calculate this value is to use the Extended Euclidean algorithm.
关于您在解决上述两个问题后可能 运行 的事情的更多注意事项:
e 应与 Phi_N 互质且小于 Phi_N,您目前尚未验证。如果不这样做,可能无法正确计算 d(只有少数几对数字具有模乘逆)。最简单(虽然不是严格正确)的方法是在 e 下面使用一个 while 循环,就像您对素数所做的那样,它会检查 False == primeCheck(e) or e >= Phi_N
。更准确地说,你必须编写一个包含 Phi_N 和 e 的互质检查,并断言它们除了 1 之外没有共同因子。
您消息的填充版本 m 必须小于 N。如果不这样做,当您尝试在解密期间反转取幂时,可能会导致某些消息无法恢复。为了更容易地验证这一点,您可能希望在用户 select P 和 Q (他们是更有可能改变他们的数字而不是他们想要发送的消息),然后在提供两个素数后添加一个额外的门来检查 N > m.
我的老师给我布置了一项任务,要求我编写一个 python 程序,该程序可以使用 RSA 算法加密消息。所以要做到这一点,我必须创建将文本转换为数字的函数,然后能够操纵这些数字并对其进行加密。但是为了测试我是否正确加密了它,我还设计了一个解密函数,我也在底部做了这个函数。加密函数和 Ascii 函数之间的所有函数都可以在其他函数中使用(此时你会意识到我喜欢将我的代码划分为函数)。我的代码的问题是当我 运行 它
时我不断收到这个错误 Traceback (most recent call last):
File "D:/Applications/Python/Ziad/RSA algotrithim V2.py", line 127, in <module>
print(decrypt(Phi_N, e, encrypted))
File "D:/Applications/Python/Ziad/RSA algotrithim V2.py", line 115, in decrypt
return Num2Text(message)
File "D:/Applications/Python/Ziad/RSA algotrithim V2.py", line 58, in Num2Text
return Ascii2Text(Num2Ascii(message))
File "D:/Applications/Python/Ziad/RSA algotrithim V2.py", line 17, in Ascii2Text
text = text + chr(int(char))
ValueError: invalid literal for int() with base 10: '1.0'
>>> ================================ RESTART =================
我单独测试了所有功能,看看它们是否有效。我重新检查了我的加密和解密功能,它们应该可以工作。出于某种原因,我认为我的问题出在我的解密函数上,因为我认为它给了我十进制数,但是我在互联网上搜索了算法,我看到的所有网站都使用相同的算法。请帮助我找到问题所在,我通常不会向其他人寻求帮助(这是我在 Whosebug 上的第一个问题)并且我已经为此伤脑筋 3 周了。
import math
def Text2Ascii(message):
Ascii = ""
for count in range(len(message)):
if len(str(ord(message[count]))) <= 2:
Ascii = Ascii + "0" +str(ord(message[count])) + " "
else:
Ascii = Ascii + str(ord(message[count])) + " "
return Ascii
def Ascii2Text(message):
text = ""
char = ""
for count in range(len(message)):
if message[count] == " ":
text = text + chr(int(char))
char = ""
else:
char = char + message[count]
text = text + chr(int(char))
return text
def Ascii2Num(message):
Num = ""
for count in range(len(message)):
if message[count] != " ":
Num = Num + message[count]
return int(Num)
def Num2Ascii(message):
Ascii = ""
char = ""
message = str(message)
if len(message)%3 == 0:
for count in range(len(message)):
if (count+1)%3 == 0:
char = char + message[count]
Ascii = Ascii + char + " "
char = ""
else:
char = char + message[count]
else:
Ascii = "0"
for count in range(len(message)):
if (count+2)%3 == 0:
char = char + message[count]
Ascii = Ascii + char + " "
char = ""
else:
char = char + message[count]
return Ascii
def Text2Num(message):
return Ascii2Num(Text2Ascii(message))
def Num2Text(message):
return Ascii2Text(Num2Ascii(message))
def exponent(number, power):
answer = 1
for count in range(power):
answer = number*answer
return answer
def primeCheck(number):
if number == 2:
prime = True
elif number <= 1:
prime = False
else:
n = math.sqrt(number)
n = math.ceil(n)
for count in range(2,n+1):
if number%count == 0:
prime = False
break
else:
prime = True
return prime
def factors(number):
answer = []
if primeCheck(number)== True:
answer = [number,1]
else:
for count in range(1,number+1):
if number%count == 0:
answer.append(count)
return answer
def phi(number):
answer = number
if primeCheck(number) == True:
answer = number - 1
else:
factor = factors(number)
for count in factor:
for count2 in factors(count):
if count2 == count:
answer = answer -1
break
return answer
def encrypt(N,e):
message = input("What is the message you need encrypted?\n")
message = Text2Num(message)
encrypted = (message ** e)%N
return encrypted
def decrypt(Phi_N, e,encrypted):
k = 3
d = (Phi_N*k + 1)/e
message = encrypted ** d
return Num2Text(message)
p = int(input("Give me a prime number: "))
while primeCheck(p) == False:
p = int(input("Give me a prime number: "))
q = int(input("Give me a prime number: "))
while primeCheck(q) == False:
q = int(input("Give me a prime number: "))
N = q*p
Phi_N = (q-1)*(p-1)
e = int(input("Enter your encryption key: "))
encrypted = encrypt(N,e)
print(decrypt(Phi_N, e, encrypted))
您遇到的特定错误是由两个因素共同造成的:
第一个也是最容易解决的问题是您在 Ascii2Text 中分解字符串的方式:
def Ascii2Text(message):
text = ""
char = ""
for count in range(len(message)):
**if message[count] == " ":** #<-- This line is not robust
text = text + chr(int(char))
char = ""
else:
char = char + message[count]
text = text + chr(int(char))
return text
问题是,随着 Num2Ascii 的实现方式,您最终会得到一个尾随 space,这会导致您在循环结束时尝试将空字符串转换为 int,并且ascii 化消息中前面的非 space 个字符。我建议要么大声扼杀无效字符,要么至少不要尝试将它们附加到您尝试在下一行转换为 int 的 "char" 字符串。
这给我们带来了下一个问题:您甚至一开始就有非数字字符。导致您看到的失败的小数点来自 d 的错误计算。 d 应该是 modular multiplicative inverse of e, and it will always be an integer when calculated correctly. Yours, however, was coming up as a decimal more often than not when I ran this code. This is one of the bits of RSA that people choke on most often, since it involves manipulating the modulo operator in ways that people without a math background aren't typically taught. One of the more common, efficient ways to calculate this value is to use the Extended Euclidean algorithm.
关于您在解决上述两个问题后可能 运行 的事情的更多注意事项:
e 应与 Phi_N 互质且小于 Phi_N,您目前尚未验证。如果不这样做,可能无法正确计算 d(只有少数几对数字具有模乘逆)。最简单(虽然不是严格正确)的方法是在 e 下面使用一个 while 循环,就像您对素数所做的那样,它会检查
False == primeCheck(e) or e >= Phi_N
。更准确地说,你必须编写一个包含 Phi_N 和 e 的互质检查,并断言它们除了 1 之外没有共同因子。您消息的填充版本 m 必须小于 N。如果不这样做,当您尝试在解密期间反转取幂时,可能会导致某些消息无法恢复。为了更容易地验证这一点,您可能希望在用户 select P 和 Q (他们是更有可能改变他们的数字而不是他们想要发送的消息),然后在提供两个素数后添加一个额外的门来检查 N > m.