使用标准库在Python中进行私有/公有加密

23 投票
4 回答
42416 浏览
提问于 2025-04-17 08:31

有没有什么模块是我搜索时没找到的,可以让我写出下面这样的代码?我想写这种代码的原因不重要。我只想要一些简单的代码,能够生成公钥和私钥,并且可以方便地用这些密钥来编码和解码数据。

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文件或其他类型的证书的。我希望能避免处理这些文件,能够即时生成公钥和私钥,并且快速在内存中处理数据。

4 个回答

2

这是另一个例子

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}
3

PyCrypto 从版本2.4.1开始可以在Python 3上使用。

38

公钥加密在标准库里是没有的。不过在PyPi上有一些第三方库可以用:

如果你对背后的数学原理感兴趣,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)

撰写回答