【问题标题】:Python pow() function returns wrong answerPython pow() 函数返回错误答案
【发布时间】:2018-11-06 20:53:28
【问题描述】:

我正在创建一个基本的 RSA 加密程序,而不使用 RSA 库,该库接收秘密消息,将字符串中的每个字符转换为其 ASCII 值,使用公钥加密并连接值,然后使用私有密钥对其进行解密键并将其返回为字符串。

均以cipher = pow(plain,e,n)plain = pow(cipher,d,n)为原则。我的问题是,当数字变得非常大时,因为我需要 dn 至少为 16 位,pow() 函数似乎会导致计算错误,产生超出范围的 ASCII 值转换为字符。几天来,我一直在努力弄清楚我哪里出错了。任何帮助表示赞赏。代码如下:

from random import randrange, getrandbits

def is_prime(n, k=128):
    # Test if n is not even.
    # But care, 2 is prime !
    if n == 2 or n == 3:
        return True
    if n <= 1 or n % 2 == 0:
        return False
    # find r and s
    s = 0
    r = n - 1
    while r & 1 == 0:
        s += 1
        r //= 2
    # do k tests
    for q in range(k):
        a = randrange(2, n - 1)
        x = pow(a, r, n)
        if x != 1 and x != n - 1:
            j = 1
            while j < s and x != n - 1:
                x = pow(x, 2, n)
                if x == 1:
                    return False
                j += 1
            if x != n - 1:
                return False

    return True

def generate_prime_candidate(length):
    # generate random bits
    p = getrandbits(length)
    #p = randrange(10**7,9*(10**7))
    # apply a mask to set MSB and LSB to 1
    p |= (1 << length - 1) | 1

    return p

def generate_prime_number(length=64):
    p = 4
    # keep generating while the primality test fail
    while not is_prime(p, 128):
        p = generate_prime_candidate(length)
    return p

def gcd(a, b):
    while b != 0:
        a, b = b, a % b
    return a

def generate_keypair(p, q):
    n = p * q

    #Phi is the totient of n
    phi = (p-1) * (q-1)

    #Choose an integer e such that e and phi(n) are coprime
    e = randrange(1,65537)

    g = gcd(e, phi)
    while g != 1:
        e = randrange(1,65537)
        g = gcd(e, phi)

    d = multiplicative_inverse(e, phi)
    return ((e, n), (d, n))

def multiplicative_inverse(e, phi):
    d = 0
    k = 1
    while True:
        d = (1+(k*phi))/e
        if((round(d,5)%1) == 0):
            return int(d)
        else:
            k+=1

def encrypt(m,public):
    key, n = public
    encrypted = ''
    print("Your original message is: ", m)
    result = [(ord(m[i])) for i in range(0,len(m))]
    encryption = [pow(result[i],key,n) for i in range(0,len(result))]
    for i in range(0,len(encryption)):
        encrypted = encrypted + str(encryption[i])
    #encrypted = pow(int(encrypted),key,n)
    print("Your encrypted message is: ", encrypted)
    #return result,encrypted
    return encrypted, encryption

def decrypt(e,c,private):
    key, n = private
    print("Your encrypted message is: ", c)
    print(e)
    decryption = [pow(e[i],key,n) for i in range(0,len(e))]
    print(decryption)
    result = [chr(decryption[i])for i in range(0,len(decryption)) ]
    decrypted = ''.join(result)
    print("Your decrypted message is: ",decrypted)
    return result,decrypted

def fastpow(x,y,p):
    res = 1
    x = x%p

    while(y>0):
        if((y&1) == 1):
            res = (res*x)%p
        y = y>>1
        x = (x*x)%p
    return res



message = input("Enter your secret message: ")
p1 = generate_prime_number()
p2 = generate_prime_number()
public, private = generate_keypair(p1,p2)
print("Your public key is ", public)
print("Your private key is ", private)
encrypted,cipher = encrypt(message,public)
decrypt(cipher,encrypted,private)

追溯:

 File "<ipython-input-281-bce7c44b930c>", line 1, in <module>
   runfile('C:/Users/Mervin/Downloads/group2.py', wdir='C:/Users/Mervin/Downloads')

 File "C:\Users\Mervin\Anaconda3\lib\site-packages\spyder\util\site\sitecustomize.py", line 705, in runfile
   execfile(filename, namespace)

 File "C:\Users\Mervin\Anaconda3\lib\site-packages\spyder\util\site\sitecustomize.py", line 102, in execfile
   exec(compile(f.read(), filename, 'exec'), namespace)

 File "C:/Users/Mervin/Downloads/group2.py", line 125, in <module>
   decrypt(cipher,encrypted,private)

 File "C:/Users/Mervin/Downloads/group2.py", line 100, in decrypt
   result = [chr(decryption[i])for i in range(0,len(decryption)) ]

 File "C:/Users/Mervin/Downloads/group2.py", line 100, in <listcomp>
   result = [chr(decryption[i])for i in range(0,len(decryption)) ]

OverflowError: Python int too large to convert to C long

【问题讨论】:

  • 可能相关:stackoverflow.com/q/23759098/1531971(您应该说明您使用的 Python 版本,也许 2.5+ 解决了您的许多问题。您还应该显示一些示例输出。)
  • 欢迎来到 StackOverflow。请按照您创建此帐户时的建议阅读并遵循帮助文档中的发布指南。 Minimal, complete, verifiable example 适用于此。在您发布 MCVE 代码并准确描述问题之前,我们无法有效地帮助您。我们应该能够将您发布的代码粘贴到文本文件中并重现您描述的问题。这里的关键词是“最小”。
  • 您的multiplicative_inverse() 方法有误。看看Modular multiplicative inverse
  • @DanielPryden:不正确
  • 当事情看起来不对的时候,有两个选择:1.“已经被成千上万人使用多年的实现是错误的”或“我不明白”选择第二个,真正深入了解。

标签: python python-3.x rsa python-3.6


【解决方案1】:

您的方法multiplicative_inverse 不正确。我不确定你在该方法中使用圆形方法和浮点除法做什么,但即使你得到了正确的部分,它也太慢了,需要 O(φ) 步骤。计算modular multiplicative inverses 的常用方法是对extended Euclidean algorithm 的改编,它以 O(log(φ)2) 步运行。这是从 Wikipedia 文章中的伪代码到 python 3 代码的直接映射:

def multiplicative_inverse(a, n):
    t, newt = 0, 1
    r, newr = n, a
    while newr:
        quotient = r // newr
        t, newt = newt, t - quotient * newt
        r, newr = newr, r - quotient * newr
    if r > 1:
        raise ZeroDivisionError("{} is not invertible".format(a))
    if t < 0:
        t = t + n
    return t

【讨论】:

    猜你喜欢
    • 2022-08-17
    • 2018-05-04
    • 1970-01-01
    • 2019-01-19
    • 1970-01-01
    • 1970-01-01
    • 2015-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多