python中的RSA加密
我决定用 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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我希望你喜欢学习 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!
RSA的实现可以进一步简化如下:
1.选择两个不同的大素数,这里为了简单起见我们选择
p=937
、q=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 代码的乘法逆
计算步骤 1-5 的
: 6.加密消息(明文)在发送方用接收方的公钥(
e
)7.用接收方的私钥对接收方收到的密文进行解密(
d
)下面的代码展示了如何进行加密/解密:
现在,让我们使用上面的函数进行加密/解密:
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 example2.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 choosee=5
, which is a prime5.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
Python code for steps 1-5:
6.Encrypt the message (plaintext) with the receiver's public key (
e
) at sender's end7.Decrypt the ciphertext received at the receiver end with his private key (
d
)The following code shows how the encryption / decryption can be done:
Now, let's use the above functions for encryption / decryption: