2016-12-01 131 views
0

我想在python中實現Shamir Secret Sharing Sceme,我需要詢問用戶密碼,然後用sha256獲取哈希碼,但是當我嘗試使用它作爲參數時對於AES來說,密鑰的長度必須是16,24或32位,是不是會返回一個32字節的字符串?使用sha256密碼AES加密

這裏是我的代碼:

import getpass 
import hashlib 
import random 
import operator 
from functools import reduce 
import sys 
import os 
from Crypto.Cipher import AES 

p= 208351617316091241234326746312124448251235562226470491514186331217050270460481 
points= [] 

## Class Prime 
# 
# Class that represents integers modulo p, it is built from a non negative integer 
# , comes with its own implementations of basic operations like sum, multiplication 
# and division, the division is calculated ith the extended euclidean algorithm. 
class Prime(object): 
    ## The constructor 
    def __init__(self, n): 
     self.n = n % p 
    def __add__(self, other): return Prime(self.n + other.n) 
    def __sub__(self, other): return Prime(self.n - other.n) 
    def __mul__(self, other): return Prime(self.n * other.n) 
    def __pow__(self, x): return Prime(self.n**x) 
    def __truediv__(self, other): return self * other.inverse() 
    def __div__(self, other): return self * other.inverse() 
    def __neg__(self): return Prime(-self.n) 
    def __eq__(self, other): return isinstance(other, Prime) and self.n == other.n 
    def __abs__(self): return abs(self.n) 
    def __str__(self): return str(self.n) 
    def __divmod__(self, divisor): 
     q,r = divmod(self.n, divisor.n) 
     return (Prime(q), Prime(r)) 
    def EuclideanAlgorithm(a, b): 
     if abs(b) > abs(a): 
      (x,y,d) = EuclideanAlgorithm(b, a) 
      return (y,x,d) 
     if abs(b) == 0: 
      return (1, 0, a) 
     x1, x2, y1, y2 = 0, 1, 1, 0 
     while abs(b) > 0: 
      q, r = divmod(a,b) 
      x = x2 - q*x1 
      y = y2 - q*y1 
      a, b, x2, x1, y2, y1 = b, r, x1, x, y1, y 
     return (x2, y2, a) 
    def inverse(self): 
     (x,y,d)= EuclideanAlgorithm(self.n, p) 
     return Prime(x) 

## Class Polynomial 
# 
# Class that represents a polynomial, it is built from a list of coefficients 
# comes with a call method to evaluate the polynomial in a value "x", and has 
# a reduced lagrange method that gets the constant value of a polynomial from 
# a set of points 
class Polynomial(object): 
    ## The constructor 
    def __init__(self, coefficients): 
     self.coeff= coefficients 
    def __call__(self, x): 
     n = 0 
     tmp = Prime(0) 
     for i in self.coeff: 
      tmp = tmp + (i*(x**n)) 
      n += 1 
     return tmp 
    def lagrange(points): 
     product= functools.reduce(operator.mul, points, 1) 
     sum= 0 
     for x in points: 
      p= 1 
      for y in points: 
       if x!= y: 
        p= p*(x-y) 
      sum+= poly(x)/(-x*p) 
     return sum 

## Ask the user for a password and gets its hash code with sha256 
def password(): 
    p= getpass.getpass() 
    h= hashlib.sha256(p) 
    s= h.hexdigest() 
    constant= int(s, 16) 
    return constant 

## Makes a polynomial with random coefficients and a fixed constant value, and 
# evaluates it with n random values an writes the results to a file. 
# @param constant The constant value of the polynomial. 
# @param evaluations The number of evaluations to be made. 
# @param degree The degree of the polynomial. 
# @param out_fileName The name of the file where the evaluations are going 
# to be written. 
# \pre The constant, evaluations and degree must be positive integers. 
# \post If no error occurs then, the file whose name was passed will contain 
# n evaluations of the polynomial. 
def makeKeys(constant, evaluations, degree, out_fileName): 
    coeffs= [] 
    coeffs.append(Prime(constant)) 
    for x in range(1, degree): 
     randomc= random.randint(1, p - 1) 
     coeffs.append(Prime(randomc)) 
    poly= Polynomial(coeffs) 
    file= open(out_fileName, "w") 
    for x in range(1, evaluations + 1): 
     randomi= random.randint(1, p - 1) 
     points.append(randomi) 
     e= poly(Prime(randomi)) 
     file.write("(%d, %d)\n" % (randomi, e.n)) 
    file.close() 

def encrypt(key, in_fileName, out_fileName): 
    iv = ''.join(chr(random.randint(0, 0xFF)) for i in range(16)) 
    encryptor = AES.new(key, AES.MODE_ECB, iv) 
    filesize = os.path.getsize(in_filename) 
    with open(in_filename, 'rb') as infile: 
     with open(out_filename, 'wb') as outfile: 
      outfile.write(struct.pack('<Q', filesize)) 
      outfile.write(iv) 
      while True: 
       chunk = infile.read(chunksize) 
       if len(chunk) == 0: 
        break 
       elif len(chunk) % 16 != 0: 
        chunk += ' ' * (16 - len(chunk) % 16) 
       outfile.write(encryptor.encrypt(chunk)) 

def decrypt(ciphertext, key): 
    iv = ciphertext[:AES.block_size] 
    cipher = AES.new(key, AES.MODE_ECB, iv) 
    plaintext = cipher.decrypt(ciphertext[AES.block_size:]) 
    return plaintext.rstrip(b"\0") 

def decrypt_file(file_name, key): 
    with open(file_name, 'rb') as fo: 
     ciphertext = fo.read() 
    dec = decrypt(ciphertext, key) 
    with open(file_name[:-4], 'wb') as fo: 
     fo.write(dec) 
+2

你舉的例子是大到能夠理解。請提供一個最小的答案。例如。只需調用get password函數和AES即可。 –

回答

0

我看不到pasword和加密的鏈路/解密功能,但我supose密碼返回鍵。在這種情況下,密鑰是具有32或64位的整數。 AES的最小值是128位。

試試這個:

def password(): 
    p= getpass.getpass() 
    h= hashlib.sha256(p) 
    return h.digest() 
+0

這並不奏效,因爲我需要將該密碼轉換爲整數模數素,對於多項式 – alexis

+0

好的。那麼如果你正在使用python 2修改你的原代碼使用long而不是int –

+0

是不是h.digest()是一個字符串? – alexis