使用标准库的 Python 中的私有/公共加密
Posted
技术标签:
【中文标题】使用标准库的 Python 中的私有/公共加密【英文标题】:Private/Public Encryption in Python with Standard Library 【发布时间】:2012-01-22 06:59:17 【问题描述】:是否有一个模块在我的搜索中无法发现允许编写如下代码?想要编写这样的代码的原因并不重要。我所追求的只是一些具有简单 API 的代码,用于生成公共和私有字节密钥,并使用这些密钥轻松编码和解码数据。
import module, os
method, bits, data = 'RSA', 1024, os.urandom(1024)
public, private = module.generate_keys(method, bits)
assert isinstance(public, bytes) and isinstance(private, bytes)
assert module.decode(module.encode(data, private), public) == data
assert module.decode(module.encode(data, public), private) == data
大多数似乎可用的功能都需要下载一个包,并且只能在 Python 2.x 上运行。找到使用 PEM 文件或其他类型证书的库也很常见。我希望避免处理此类文件,即时生成公钥和私钥,并快速处理内存中的数据。
【问题讨论】:
我不知道一个理想的解决方案,但你总是可以依靠使用 python 子进程模块通过命令行调用 gpg 【参考方案1】:公钥加密不在标准库中。不过,PyPi 上有一些第三方库:
PyCrypto RSA Python如果您对它背后的数学感兴趣,Python 可以让您轻松进行实验:
code = pow(msg, 65537, 5551201688147) # encode using a public key
plaintext = pow(code, 109182490673, 5551201688147) # decode using a private key
密钥生成涉及更多。这是一个简化的示例,说明如何使用 urandom 作为熵源在内存中生成密钥。代码在Py2.6和Py3.x下都运行:
import random
def gen_prime(N=10**8, bases=range(2,20000)):
# XXX replace with a more sophisticated algorithm
p = 1
while any(pow(base, p-1, p) != 1 for base in bases):
p = random.SystemRandom().randrange(N)
return p
def multinv(modulus, value):
'''Multiplicative inverse in a given modulus
>>> multinv(191, 138)
18
>>> 18 * 138 % 191
1
'''
# http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
x, lastx = 0, 1
a, b = modulus, value
while b:
a, q, b = b, a // b, a % b
x, lastx = lastx - q * x, x
result = (1 - lastx * modulus) // value
return result + modulus if result < 0 else result
def keygen(N):
'''Generate public and private keys from primes up to N.
>>> pubkey, privkey = keygen(2**64)
>>> msg = 123456789012345
>>> coded = pow(msg, 65537, pubkey)
>>> plain = pow(coded, privkey, pubkey)
>>> assert msg == plain
'''
# http://en.wikipedia.org/wiki/RSA
prime1 = gen_prime(N)
prime2 = gen_prime(N)
totient = (prime1 - 1) * (prime2 - 1)
return prime1 * prime2, multinv(totient, 65537)
【讨论】:
您知道这些库中是否有任何一个既支持如上所示的简单 API 又在 Python 3.x 上运行的库? RSA Python 链接包含纯 Python 代码,包括您正在寻找的大部分内容。您可能需要对其进行一些调整以完全匹配您正在寻找的 API。 APSN 配方、pow 示例和 PyCrypto 在 Python 3 上运行良好。 嗨@RaymondHettinger。正如您在此处描述的那样,我想在 java 中实现此算法。但我看到 python 用pow(code,pub,pri)
轻松做的事情几乎不可能用 java 计算。我想我错过了某事。你会建议我吗? (即使没有,谢谢你的回答:))
嗨@RaymondHettinger,我缺少的一点是模幂运算。 Python 本机实现它。因此,即使在 RPi 中,计算也非常快。再次感谢。
@MertGülsoy 快速模指数计算很容易实现。见math.stackexchange.com/a/453108【参考方案2】:
PyCrypto 自 2.4.1 起适用于 Python 3。
【讨论】:
【参考方案3】:这是另一个例子
import random
# RSA Algorithm
ops = raw_input('Would you like a list of prime numbers to choose from (y/n)? ')
op = ops.upper()
if op == 'Y':
print """\n 2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113
127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199 211 223 227 229
233 239 241 251 257 263 269 271 277 281
283 293 307 311 313 317 331 337 347 349
353 359 367 373 379 383 389 397 401 409
419 421 431 433 439 443 449 457 461 463
467 479 487 491 499 503 509 521 523 541
547 557 563 569 571 577 587 593 599 \n"""
rsa()
else:
print "\n"
rsa()
def rsa():
# Choose two prime numbers p and q
p = raw_input('Choose a p: ')
p = int(p)
while isPrime(p) == False:
print "Please ensure p is prime"
p = raw_input('Choose a p: ')
p = int(p)
q = raw_input('Choose a q: ')
q = int(q)
while isPrime(q) == False or p==q:
print "Please ensure q is prime and NOT the same value as p"
q = raw_input('Choose a q: ')
q = int(q)
# Compute n = pq
n = p * q
# Compute the phi of n
phi = (p-1) * (q-1)
# Choose an integer e such that e and phi(n) are coprime
e = random.randrange(1,phi)
# Use Euclid's Algorithm to verify that e and phi(n) are comprime
g = euclid(e,phi)
while(g!=1):
e = random.randrange(1,phi)
g = euclid(e,phi)
# Use Extended Euclid's Algorithm
d = extended_euclid(e,phi)
# Public and Private Key have been generated
public_key=(e,n)
private_key=(d,n)
print "Public Key [E,N]: ", public_key
print "Private Key [D,N]: ", private_key
# Enter plain text to be encrypted using the Public Key
sentence = raw_input('Enter plain text: ')
letters = list(sentence)
cipher = []
num = ""
# Encrypt the plain text
for i in range(0,len(letters)):
print "Value of ", letters[i], " is ", character[letters[i]]
c = (character[letters[i]]**e)%n
cipher += [c]
num += str(c)
print "Cipher Text is: ", num
plain = []
sentence = ""
# Decrypt the cipher text
for j in range(0,len(cipher)):
p = (cipher[j]**d)%n
for key in character.keys():
if character[key]==p:
plain += [key]
sentence += key
break
print "Plain Text is: ", sentence
# Euclid's Algorithm
def euclid(a, b):
if b==0:
return a
else:
return euclid(b, a % b)
# Euclid's Extended Algorithm
def extended_euclid(e,phi):
d=0
x1=0
x2=1
y1=1
orig_phi = phi
tempPhi = phi
while (e>0):
temp1 = int(tempPhi/e)
temp2 = tempPhi - temp1 * e
tempPhi = e
e = temp2
x = x2- temp1* x1
y = d - temp1 * y1
x2 = x1
x1 = x
d = y1
y1 = y
if tempPhi == 1:
d += phi
break
return d
# Checks if n is a prime number
def isPrime(n):
for i in range(2,n):
if n%i == 0:
return False
return True
character = "A":1,"B":2,"C":3,"D":4,"E":5,"F":6,"G":7,"H":8,"I":9,"J":10,
"K":11,"L":12,"M":13,"N":14,"O":15,"P":16,"Q":17,"R":18,"S":19,
"T":20,"U":21,"V":22,"W":23,"X":24,"Y":25,"Z":26,"a":27,"b":28,
"c":29,"d":30,"e":31,"f":32,"g":33,"h":34,"i":35,"j":36,"k":37,
"l":38,"m":39,"n":40,"o":41,"p":42,"q":43,"r":44,"s":45,"t":46,
"u":47,"v":48,"w":49,"x":50,"y":51,"z":52, " ":53, ".":54, ",":55,
"?":56,"/":57,"!":58,"(":59,")":60,"$":61,":":62,";":63,"'":64,"@":65,
"#":66,"%":67,"^":68,"&":69,"*":70,"+":71,"-":72,"_":73,"=":74
【讨论】:
这段代码没有任何工作机会。缩进被破坏。此外很难阅读(变量名)【参考方案4】:这里在各个方面都提到了 PyCrypto。有了这个答案,而不是评论,我想指出 PyCrypto 的最后一个版本是从 2013 年开始的。对于密码库,这是不可接受的,因为潜在的危险问题没有得到解决。
但是,PyCrypto 有一个分支,PyCryptodome,将继续开发。 Link to Github: https://github.com/Legrandin/pycryptodome
【讨论】:
以上是关于使用标准库的 Python 中的私有/公共加密的主要内容,如果未能解决你的问题,请参考以下文章