【问题标题】:Why is my RSA Implementation in Python not working?为什么我在 Python 中的 RSA 实现不起作用?
【发布时间】:2017-10-18 01:18:57
【问题描述】:

出于学习目的,我正在尝试在 Python 中实现 RSA 公钥加密。我已经看了一些示例代码并搜索了整个 stackoverflow 试图找到答案。

我的实现工作不正常,我不知道为什么。

我可以轻松生成公钥和私钥。当我使用公钥进行加密时,我会得到类似

16102208556492

我认为这看起来是正确的。当我现在尝试解密密文时,它会给我随机的 ASCII 符号。所以我认为解密一定是错误的,但它看起来也很好。

自从几天以来我一直在努力寻找误判!

我从 Darrel Hankerson、Alfred Menezes 和 Scott Vanstone 所著的“椭圆曲线密码学指南”一书中的数学算法开始。

算法 1.1:RSA 密钥对生成

INPUT: Security parameter l
OUTPUT: RSA public key e, private key d and n
1. Randomly select two primes p and q with same bitlength l/2
2. Compute n = pq and phi = (p-1)(q-1)
3. Select an arbitrary integer e with 1 < e < phi and gcd(e, phi)==1
4. Compute the integer d satisfying 1 < d < phi and ed == 1 mod phi
5. Return(n, e, d)

算法 1.2:基本 RSA 加密

INPUT: RSA public key e, n, plaintext m
OUTPUT: Ciphertext c
1. Compute c = m**e mod n
2. Return(c)

算法 1.3:基本 RSA 解密

INPUT: RSA private d, n, ciphertext c
OUTPUT: Plaintext m
1. Compute m = c**d mod n
2. Return(m)

我了解它在数学上是如何工作的,所以我这样实现它:

Python中的算法1.1

# INPUT: Secure parameter l
def Generation(l):
    # Randomly select 2 primes with same Bitlength l/2
    p = Randomly_Select_Prime_w_Bitlength(l/2)
    q = Randomly_Select_Prime_w_Bitlength(l/2)
    # Compute
    n = p * q
    phi = (p - 1) * (q - 1)
    # Select an arbitrary integer e with 1 < e < phi and gcd(e,phi) == 1
    e = int(Arbitrary_Int_e(phi))
    # Compute the integer d satisfying 1 < d < phi and e*d == 1 % phi
    d = inverse(e, n)
    # Return n e d
    print("Public Key: " + str(e))
    print("Private Key: " + str(d))
    print("n = " + str(n))

Python中的算法1.2

# INPUT: RSA public key e, n, message m
def Encryption(e, n, m):
    c = [pow(ord(char),e,n) for char in m]
    print(''.join(map(lambda x: str(x), c)))
    return c

Python中的算法1.3

# INPUT: RSA private key d, n, ciphertext c
def Decryption(d, n, c):
    m =  [chr(pow(char, d, n)) for char in c]
    print(''.join(m))
    return ''.join(m)

我在这里的编码似乎不是很错误,但无论如何,这里或其他功能一定有问题。

这是我的完整 python 代码

# RSA

# Imports
import random

# INPUT: Secure parameter l
def Generation(l):
    # Randomly select 2 primes with same Bitlength l/2
    p = Randomly_Select_Prime_w_Bitlength(l/2)
    q = Randomly_Select_Prime_w_Bitlength(l/2)
    # Compute
    n = p * q
    phi = (p - 1) * (q - 1)
    # Select an arbitrary integer e with 1 < e < phi and gcd(e,phi) == 1
    e = int(Arbitrary_Int_e(phi))
    # Compute the integer d satisfying 1 < d < phi and e*d == 1 % phi
    d = inverse(e, n)
    # Return n e d
    print("Public Key: " + str(e))
    print("Private Key: " + str(d))
    print("n = " + str(n))

# INPUT: RSA public key e, n, message m
def Encryption(e, n, m):
    c = [pow(ord(char),e,n) for char in m]
    print(''.join(map(lambda x: str(x), c)))
    return c

# INPUT: RSA private key d, n, ciphertext c
def Decryption(d, n, c):
    m =  [chr(pow(char, d, n)) for char in c]
    print(''.join(m))
    return ''.join(m)

def mrt(odd_int):
    odd_int = int(odd_int)
    rng = odd_int - 2
    n1 = odd_int - 1
    _a = [i for i in range(2,rng)]
    a = random.choice(_a)
    d = n1 >> 1
    j = 1
    while((d&1)==0):
        d = d >> 1
        j += 1
    t = a
    p = a
    while(d>0):
        d = d>>1
        p = p*p % odd_int
        if(d&1):
            t = t*p % odd_int
    if(t == 1 or t == n1):
        return True
    for i in range(1,j):
        t = t*t % odd_int
        if(t==n1):
            return True
        if(t<=1):
            break
    return False

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

def Randomly_Select_Prime_w_Bitlength(l):
    prime = random.getrandbits(int(l))
    if (prime % 2 == 1):
        if (mrt(prime)):
            return prime
    return Randomly_Select_Prime_w_Bitlength(l)

def Arbitrary_Int_e(phi):
    _e = [i for i in range(1, phi)]
    e = random.choice(_e)
    if(gcd(e, phi) == 1 % phi):
        return e
    return Arbitrary_Int_e(phi)

def inverse(e, phi):
    a, b, u = 0, phi, 1
    while(e > 0):
        q = b // e
        e, a, b, u = b % e, u, e, a-q*u
    if (b == 1):
        return a % phi
    else:
        print("Must be coprime!")    

【问题讨论】:

  • 在我看来,您是在要求 random.getrandbits() 函数生成半位??不完全确定,但它会在我的系统上引发错误。你的意思是半字节吗? EDIT 它不是 1,不是很好的变量名选择
  • 不应该是d = inverse(e, phi)而不是d = inverse(e, n)
  • @MarekKlein 你完全正确!看看stackoverflow.com/a/23280454/7581751 我想它应该是正确的假设: d = inverse(e, phi) 就像我在我的函数中定义的那样。我更改了代码,但仍然无法正常工作。
  • @MarekKlein 我觉得完全愚蠢,因为它现在运行良好。感谢您的快速评论。你应该给出答案^^我真的很惭愧我自己没有找到这个。该死的。
  • @s0T7x 同样在你的伪代码中你写了4. Compute the integer d satisfying 1 &lt; d &lt; phi and ed == 1 mod phi。因此,您需要 e mod phi 的模逆。但同样从逻辑的角度来看,n 是公开的,e 是公开的,因此如果可行,任何人都可以计算出应该是私有的 d。

标签: python algorithm encryption cryptography rsa


【解决方案1】:

正如Marek Klein 在他的评论中所说,我用错误的参数调用了 "inverse()" 函数。 是d = inverse(e, n) 而不是d = inverse(e, phi)

但从逻辑的角度来看,n 是公开的,e 是公开的,因此如果可行,任何人都可以计算出应该是私有的 d。

还有squeamish ossifrage指出

函数 Randomly_Select_Prime_w_Bitlength() 经常产生比所需位数少的数字,并且有时会产生运行时错误(因为odd_int 在 mrt() 中太小)。如果 p 和 q 太小,您将无法像预期的那样加密尽可能多的数据。

Randomly_Select_Prime_w_Bitlength() 现在涵盖检查随机素数是否大于 3,因此它不能通过尽可能小来返回运行时错误。

这里是更正后的代码:

# RSA 

# Imports
import random

# INPUT: Secure parameter l
def Generation(l):
    # Randomly select 2 primes with same Bitlength l/2
    p = Randomly_Select_Prime_w_Bitlength(l/2)
    q = Randomly_Select_Prime_w_Bitlength(l/2)
    # Compute
    n = p * q
    phi = (p - 1) * (q - 1)
    # Select an arbitrary integer e with 1 < e < phi and gcd(e,phi) == 1
    e = int(Arbitrary_Int_e(phi))
    # Compute the integer d statisfying 1 < d < phi and e*d == 1 % phi
    d = inverse(e, phi)
    # Return n e d
    print("Public Key: " + str(e))
    print("Private Key: " + str(d))
    print("n = " + str(n))

# INPUT: RSA public key e, n, message m
def Encryption(e, n, m):
    c = [pow(ord(char),e,n) for char in m]
    print(''.join(map(lambda x: str(x), c)))
    return c

# INPUT: RSA private key d, n, ciphertext c
def Decryption(d, n, c):
    m =  [chr(pow(char, d, n)) for char in c]
    print(''.join(m))
    return ''.join(m)

def mrt(odd_int):
    odd_int = int(odd_int)
    rng = odd_int - 2
    n1 = odd_int - 1
    _a = [i for i in range(2,rng)]
    a = random.choice(_a)
    d = n1 >> 1
    j = 1
    while((d&1)==0):
        d = d >> 1
        j += 1
    t = a
    p = a
    while(d>0):
        d = d>>1
        p = p*p % odd_int
        if(d&1):
            t = t*p % odd_int
    if(t == 1 or t == n1):
        return True
    for i in range(1,j):
        t = t*t % odd_int
        if(t==n1):
            return True
        if(t<=1):
            break
    return False

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

def Randomly_Select_Prime_w_Bitlength(l):
    prime = random.getrandbits(int(l))
    if (prime % 2 == 1 and prime > 3):
        if (mrt(prime)):
            return prime
    return Randomly_Select_Prime_w_Bitlength(l)

def Arbitrary_Int_e(phi):
    _e = [i for i in range(1, phi)]
    e = random.choice(_e)
    if(gcd(e, phi) == 1 % phi):
        return e
    return Arbitrary_Int_e(phi)

def inverse(e, phi):
    a, b, u = 0, phi, 1
    while(e > 0):
        q = b // e
        e, a, b, u = b % e, u, e, a-q*u
    if (b == 1):
        return a % phi
    else:
        print("Must be coprime!")    

【讨论】:

    【解决方案2】:

    在python中有一个更简单的实现RSA的方法:

    bits = 2048 # the bit length of the rsa key, must be multiple of 256 and >= 1024
    E = 65537 # (default) the encryption exponent to be used [int]
    from Crypto.PublicKey import RSA
    key = RSA.generate(bits,E)
    with open('my_key.pem','w') as file:
        file.write(key.exportKey())
        file.write(key.publickey().exportKey())
    

    Crypto.PublicKey 的使用需要(在 windows CMD 或 mac TERMINAL 中):

    pip install pycrypto
    

    对于一些运行 python 3 的系统(比如我的):

    pip3 install pycrypto
    

    公钥(模数+加密指数)和私钥(解密指数)都是base64格式,可以转换成16进制作他用:

    from base64 import b64decode
    base64_string = 'AAAAbbbb123456=='
    hex_string = b64decode(base64string).hex()
    

    彼此之间在短时间内生成的两个密钥的最高有效数字可能相等:

    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpLVejQvo2xJwx04Oo2qotAge9 wWQDsk62hb0ua8r9+VM837+cArMStt9BoSTOCmNz7cYUXzGjQUsUi7tnHXM+Ddec EG7J3q/w12ox2QN3wTndsW+GO9BD2EHY674t8A3JLSJP/bcD/FGBtjzytyd5hmQJ Fife8rr4sAMkTXwoIwIDAQAB 和(彼此之间约 10 秒) MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCz9un7Xq248zlmkwVuXze2tUMy a30BaodLJXYuAktGuiMAFwpprql0N9T06HdiphZmr+hT45gG57ZOlJn/yzN4U30Q DXevDVapq6aYJ/Q21CO2bkLkMjEMy5D4IdwMeBgK+5pJFYETB6TzLfDkEcTQMr++ f7EHosWd0iBGm01cKQIDAQAB

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-16
      • 1970-01-01
      • 1970-01-01
      • 2017-05-10
      相关资源
      最近更新 更多