使用Python在RSA算法中将文本转换为数字时无法修复错误

时间:2015-12-04 10:15:39

标签: python algorithm encryption cryptography rsa

我的任务是由我的老师编写一个可以使用RSA算法加密消息的python程序。所以要做到这一点,我必须创建将文本转换为数字然后能够操纵这些数字并对其进行加密的函数。然而,为了测试我是否正确加密它我还设计了一个解密功能,我也在底部。加密函数和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 =================

我单独测试了所有功能,看看它们是否有效。我重新检查了我的加密和解密功能,他们应该工作。出于某种原因,我认为我的问题是我的解密功能,因为我认为它给了我十进制数,但我在网上搜索算法,我看的所有网站使用相同的算法。请帮助我找到问题,我通常不会向其他人寻求帮助(这是我在StackOverFlow上的第一个问题)而且我已经在这个问题上伤了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))

1 个答案:

答案 0 :(得分:1)

您获得的具体错误是由于两个因素的结合:

第一个,也许最容易解决的是你在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的方式,你最终会得到一个尾随空格,它会导致你尝试在循环结束时将空字符串转换为int,而前面的非空格字符也是如此。你的ascii-fied消息。我建议大声窒息无效字符,或者至少不要试图将它们附加到你试图在下一行转换为int的“char”字符串。

这给我们带来了下一个问题:你首先要有非数字字符。导致您看到失败的小数点来自 d 的错误计算。 d 应该是 e modular multiplicative inverse,并且在正确计算时它将始终为整数。但是,当我运行此代码时,你的常常会以十进制形式出现。这是人们最常窒息的RSA之一,因为它涉及操纵模运算符,使得没有数学背景的人通常不会被教授。计算此值的一种更常见,更有效的方法是使用Extended Euclidean algorithm

在解决上述两个问题之后,您可能会遇到的一些注意事项:

  • e 应该与Phi_N共同使用,而不是Phi_N,您目前尚未验证。如果不这样做,就无法正确计算 d (只有几对数字具有模乘法逆)。最简单(虽然不是严格正确)的方法是在 e 下面使用while循环,就像你对素数一样,检查False == primeCheck(e) or e >= Phi_N。更确切地说,你必须编写一份同时检查Phi_N和 e 的互质检查,并断言他们除了1之外不会共享一个共同因素。

  • 邮件的填充版本 m 必须小于 N 。如果在解密期间尝试撤消取幂,则无法执行此操作可能会导致某些消息无法恢复。为了更轻松地验证这一点,您可能希望在用户选择 P Q 之前捕获来自用户的消息(他们更有可能更改他们的数字而不是消息他们想要发送),然后在提供两个素数之后添加一个额外的门,它检查 N &gt;