python中的RSA加密

发布于 2024-11-14 17:32:30 字数 2607 浏览 0 评论 0 原文

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

这是错误:

p  937
q  353
n  330761
phi  329472
e  5
d  264609
Traceback (most recent call last):
  File "rsa.py", line 94, in 
    print dec_rsa(b, d, n)
  File "rsa.py", line 88, in dec_rsa
    char_array.append(decrypt_byte(i, d, n))
  File "rsa.py", line 77, in decrypt_byte
    return find_key(alpha, (c**d)%n)
  File "rsa.py", line 67, in find_key
    return [k for k, v in dic.iteritems() if v == val][0]
IndexError: list index out of range

代码:

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)

I decided to write a simple RSA encryption implementation in Python, but every time I run it it prints the error IndexError: list out of range when it's decrypting and in find_key.

Here's the error:

p  937
q  353
n  330761
phi  329472
e  5
d  264609
Traceback (most recent call last):
  File "rsa.py", line 94, in 
    print dec_rsa(b, d, n)
  File "rsa.py", line 88, in dec_rsa
    char_array.append(decrypt_byte(i, d, n))
  File "rsa.py", line 77, in decrypt_byte
    return find_key(alpha, (c**d)%n)
  File "rsa.py", line 67, in find_key
    return [k for k, v in dic.iteritems() if v == val][0]
IndexError: list index out of range

The code:

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笔落惊风雨 2024-11-21 17:32:30

我希望你喜欢学习 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);请参阅此示例

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

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

希望有帮助!

I hope you're enjoying learning Python!

A couple of things:

(1) Your isPrime is broken: it thinks 1 is prime, 2 and 3 aren't, but all of 25, 35, 121, 143, 289, 323, 529, 841, 899 are. Getting a composite will lead to problems.

(2) You also don't check to see that p != q.

(3) Your alpha[str(byte)] should be alpha[byte] (otherwise you'll get "96llo, worl5").

(4) You're taking the wrong multiplicative modular inverse. You want modInverse(e, phi(n)), not modInverse(e, n); see this worked example.

After fixing those, it seems to work for me.

The following aren't bugs, but suggestions: you should probably use pow(c,d,n) rather than (c**d)%n; for large numbers the former will be much faster. As well, if you want to turn a letter into a number, and you don't really care what number, you could use the "ord"/"chr" functions, and not even need a dictionary. In any case, you might want to swap the keys and values in your dictionary: right now your find_key might as well be using a list, as you're simply searching over all the k,v pairs until you find a match.

Hope that helps!

北凤男飞 2024-11-21 17:32:30

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

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

2.计算 n = p*q

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

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

5 .使用乘法逆算法(扩展欧几里德)从d,st d*e ≡ 1 (mod φ(n)) href="https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm" rel="nofollow noreferrer">此处:

模 n Python 代码的乘法逆

# 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 的

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

The implementation of RSA can be further simplified as follows:

1.Choose two different large primes, here for the sake of simplicity let's choose p=937, q=353, as done in the example

2.Compute n = p*q

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

4.Choose the public key e as coprime with φ(n), for simplicity, let's choose e=5, which is a prime

5.Compute the private key d, s.t. d*e ≡ 1 (mod φ(n)), using the multiplicative inverse algorithm (extended Euclidean) from here:

Compute multiplicative inverse of a modulo 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

Python code for steps 1-5:

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.Encrypt the message (plaintext) with the receiver's public key (e) at sender's end

7.Decrypt the ciphertext received at the receiver end with his private key (d)

The following code shows how the encryption / decryption can be done:

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 

Now, let's use the above functions for encryption / decryption:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文