【问题标题】:RSA encryption in pythonpython中的RSA加密
【发布时间】:2011-09-12 22:11:57
【问题描述】:

我决定用 Python 编写一个简单的 RSA 加密实现,但每次运行它都会在解密时和 find_key 中打印错误 IndexError: list out of range

这是错误:

第 937 页 q 353 330761 φ329472 5 d 264609 回溯(最近一次通话最后): 文件“rsa.py”,第 94 行,在 打印 dec_rsa(b, d, n) 文件“rsa.py”,第 88 行,在 dec_rsa char_array.append(decrypt_byte(i, d, n)) 文件“rsa.py”,第 77 行,在解密字节中 返回 find_key(alpha, (c**d)%n) 文件“rsa.py”,第 67 行,在 find_key 返回 [k for k, v in dic.iteritems() if v == val][0] IndexError:列表索引超出范围

代码:

import fractions, sys, random, math

def isPrime( no ):
    if no < 2: return False
    if no == 2: return True
    if not no&1: return False
    for x in range(3, int(no**0.5)+1, 2):
        if no%x == 0:
            return False
    return True

def primes_range(low, high):
    primes = []
    for i in range(high-low):
        if isPrime(i+low):
            primes.append(i+low)
    return primes

let = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789~!@#$%^&*()_+'";:[]/<>,."
a, alpha = 2, {}
for i in let:
    alpha[i] = a
    a+=1

Low = 29
High = 1000
p = random.choice(primes_range(Low, High))
q = random.choice(primes_range(Low, High))
while p == q:
    q = random.choice(primes_range(Low, High))
print "p ",p
print "q ",q
#p = 104729
#q = 3

p, q = int(p), int(q)
n = p*q
phi = (p-1)*(q-1)
print "n ",n
print "phi ",phi

for i in range(2, q if q>p else p):
    if fractions.gcd(i, phi) == 1:
        e = i
        break
print "e ",e

def egcd(a,b):
    u, u1 = 1, 0
    v, v1 = 0, 1
    while b:
        q = a // b
        u, u1 = u1, u - q * u1
        v, v1 = v1, v - q * v1
        a, b = b, a - q * b
    return u, v, a

def modInverse(e, phi):
    return egcd(e, phi)[0]%n

d = modInverse(e, n)
print "d ",d

def find_key(dic, val):
    #print "val ",val
    #print "dic ",list(dic.iteritems())
    return [k for k, v in dic.iteritems() if v == val][0]

def encrypt_byte(byte, e, n):
    try:
        m = alpha[byte]
    except:
        m = int(byte)
    return (m**e)%n

def decrypt_byte(c, d, n):
    return find_key(alpha, (c**d)%n)

def enc_rsa(string, e, n):
    char_array = []
    for i in range(len(string)):
        char_array.append(encrypt_byte(alpha[string[i]], e, n))
    return char_array

def dec_rsa(enc_arr, d, n):
    char_array = []
    for i in enc_arr:
        char_array.append(decrypt_byte(i, d, n))
    return ''.join(char_array)

a = "hello, world"
b = enc_rsa(a, e, n)
#print b
print dec_rsa(b, d, n)

【问题讨论】:

  • 作为一个警告——你在这里实现的不是任何有意义的名称意义上的 RSA。出于安全目的,请勿使用此代码或此代码的任何派生代码。事实上,根本不要使用它。

标签: python algorithm encryption cryptography rsa


【解决方案1】:

希望你喜欢学习 Python!

有几点:

(1) 你的 isPrime 坏了:它认为 1 是素数,2 和 3 不是,但 25、35、121、143、289、323、529、841、899 都是素数。获得复合材料会导致问题。

(2) 你也没有检查 p != q。

(3) 你的 alpha[str(byte)] 应该是 alpha[byte] (否则你会得到 "96llo, worl5")。

(4) 你使用了错误的乘法模逆。你想要 modInverse(e, phi(n)),而不是 modInverse(e, n);见this worked example

修复这些后,它似乎对我有用。

以下不是错误,而是建议:您可能应该使用 pow(c,d,n) 而不是 (c**d)%n;对于大量数字,前者会快得多。同样,如果你想把一个字母变成一个数字,而你并不关心什么数字,你可以使用“ord”/“chr”函数,甚至不需要字典。在任何情况下,您都可能希望交换字典中的键和值:现在您的 find_key 还不如使用列表,因为您只是搜索所有 k,v 对直到找到匹配项。

希望有帮助!

【讨论】:

  • 1.修复了主要功能,谢谢您的提示。 2. 我现在检查 p != q 3. 已修复 4. 我将其更改为 modInverse(e, phi) 5. 它仍然给出 IndexError。 6.我现在将重新发布代码
  • (4) 您没有在代码中更改它,您只是将函数 modInverse 中的第二个变量的名称从 n 更改为 phi。你仍然用 'd = modInverse(e, n)' 来调用它。这意味着 modInverse 函数中的“phi”仍然是 n。
  • 哦,我太笨了...非常感谢!我太累了:)
【解决方案2】:

RSA的实现可以进一步简化如下:

1.选择两个不同的大素数,这里为了简单起见我们选择p=937q=353,如示例中所做的那样

2.计算n = p*q

3.计算Euler Totientφ(n) ≡ (p-1)*(q-1)

4.选择公钥eφ(n)互质,为简单起见,我们选择e=5,它是质数

5.计算私钥d, s.t. d*e ≡ 1 (mod φ(n)),使用来自here的乘法逆算法(扩展欧几里得):

计算模n的乘法逆

# solution t to a*t ≡ 1 (mod n) 

def multiplicative_inverse(a, n):

    t, newt = 0, 1
    r, newr = n, a

    while newr != 0:
        q = r // newr
        t, newt = newt, t - q * newt
        r, newr = newr, r - q * newr

    if t < 0:
        t = t + n

    return t

步骤 1-5 的 Python 代码:

p, q = 937, 353 # use large primes here
n = p*q
φ = (p-1)*(q-1)
e = 5 # choose public key e as a prime, s.t., gcd(φ, e) = 1
d = multiplicative_inverse(e, φ) # private key d
print(d)
# 131789

6.在发送者端用接收者的公钥(e)加密消息(明文)

7.用他的私钥(d)解密接收方收到的密文

以下代码显示了如何进行加密/解密:

def rsa_encrypt(plain_text, e, n):
    # ideally we should convert the plain text to byte array and 
    # then to a big integer which should be encrypted, but here for the sake of 
    # simplicity character-by-character encryption is done, which will be slow in practice
    cipher_text = [ord(x)**e % n for x in plain_text]        
    return cipher_text

def rsa_decrypt(cipher_text, d, n):
    decoded_text = ''.join([chr(x**d % n) for x in cipher_text])
    return decoded_text 

现在,让我们使用上面的函数进行加密/解密:

plain_text = 'Hello world'
cipher_text = rsa_encrypt(plain_text, e, n)
print(cipher_text)
# [296543, 169726, 215626, 215626, 293167, 147571, 122732, 293167, 217253, 215626, 102687]
decoded_text = rsa_decrypt(cipher_text, d, n)
decoded_text 
# Hello world

【讨论】:

    猜你喜欢
    • 2013-07-04
    • 2015-07-15
    • 2011-07-04
    • 2017-06-20
    • 2012-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    相关资源
    最近更新 更多