import random
from my_modules import modules
import itertools
import copy
qu_chong=[]#防止在破解密码时相同的明文输出情况重复出现
# 初始化
def init(length, interval):
    listV = []  # 超递增向量
    listV_b = []  # 每个元素对应的乘数
    bagCapacity = 1000  # 背包容积
    # 初始化超递增向量与listV_b
    for i in range(length):
        listV.append(sum(listV) + random.randrange(1, interval))
        listV_b.append(0)
    # 求超递增背包的解
    bagCapacityTmp = bagCapacity
    for i in range(len(listV)-1, -1, -1):
        if bagCapacityTmp >= listV[i]:
            bagCapacityTmp -= listV[i]
            listV_b[i] = 1
    return listV

# 产生私钥:k、t、t的逆元
def creatPKey(listV):
    # listV = init()
    while True:
        k = int(input("输入私钥k(大于%d):" % (sum(listV))))
        if k <= sum(listV):
            continue
        while True:
            t = int(input("输入私钥t(与k互素):"))
            if not modules.judgeCoPrime(k, t):
                continue
            break
        break
    inverse_t = modules.getInverse(t, k)
    return k, t, inverse_t

# 产生公钥:
def creatSKey(listV, t, k):
    sKeyList = [] # 公钥序列
    for i in listV:
        sKeyList.append((int(i) * t) % k)
    return sKeyList

# 加密
def encrypt(massage, sKeyList):
    massageList = []    # 明文分组后的列表
    ciphertextList = [] # 存储密文的列表
    # 扩充明文消息串
    while len(massage) % len(sKeyList) != 0:
        massage = "0" + massage
    # 对明文进行分组
    for i in range(int(len(massage) / len(sKeyList))):
        start = (i * len(sKeyList))
        end = ((i + 1) * len(sKeyList))
        massageList.append(massage[start : end])
    # 采用内积和的方法加密
    for i in massageList:
        # 此处使用lambda时,要注意类型转换
        multiplyList = list(map(lambda x, y: int(x) * int(y), list(i), sKeyList))
        ciphertextList.append(sum(multiplyList))
    return ciphertextList

# 解密
def decrypt(massage, sKeyList, k, inverse_t):
    pliantextList = [] # 存储明文的列表
    reductListV = []  # 还原后的初始超递增向量
    # 还原超递增向量
    for i in sKeyList:
        reductListV.append(int(i) * inverse_t % k)
    # 计算出用于解密的临时背包容积
    bagCapacityList = []
    for i in massage:
        bagCapacityList.append(int(i) * inverse_t % k)
    # 利用求出的临时背包容积求解背包问题,结果即明文
    for bagCap in bagCapacityList:
        pliantextTmp = []   # 存储密文列表中每个密文解密后的序列
        for i in range(len(reductListV)):
            pliantextTmp.append(0)
        for i in range(len(reductListV) - 1, -1, -1):
            if bagCap >= reductListV[i]:
                bagCap -= reductListV[i]
                pliantextTmp[i] = 1
        pliantextList += pliantextTmp
    # 去除扩充的0并转换为字符串
    start, end = 0, 0
    for i in range(len(pliantextList)):
        if pliantextList[i] !=0:
            break
        end = i + 1
    del pliantextList[start : end]
    pliantextList = map(str, pliantextList)
    pliantext = "".join(pliantextList)
    return pliantext
#破解背包公钥密码
def crack (sKeyList,ciphertextList):
    list_len=len(sKeyList)
    flag=1
    pkh=sKeyList[0]+sKeyList[1]
    pkl=sKeyList[0]
    for i in range(1,list_len):
        if(i>=1 and sKeyList[i]<sKeyList[i-1]):
            if(pkh<sKeyList[i-1]+sKeyList[i]):
                pkh=sKeyList[i-1]+sKeyList[i]
            if(pkl>sKeyList[i-1]):
                pkl=sKeyList[i-1]
            if(flag):
                flag=0
    if(flag):
        pkh=sKeyList[list_len-1]+1
        pkl=sKeyList[0]-1
    AA=[]
    t=0
    NS=1 #破解状态
    FA=1 #寻找超递增向量,找不到为0
    k=pkh
    while (NS and FA):
        sum=0
        t=t+1
        AA.clear()
        AA.append(sKeyList[0]*t%k)
        for i in range(1,list_len):
            AA.append(sKeyList[i]*t%k)
            sum=sum+AA[i-1]
            if (sum>=AA[i]):  #判断是否为超递增序列
                break
            elif( i==list_len-1):
                #print("k=",k,"t=",t,"AA",AA)
                decryption(ciphertextList,AA,k,t)
                #NS=0
        if (k>pkl and t >=k):  #判断能否找到超递增序列
            k=k-1
            t=0
        elif (k<=pkl):
            FA=0
            if(not qu_chong):
                print("输入的公钥不存在或无法求得(k&&t)以求得递增背包序列")
            else:
                print("输出完毕!")
   # decryption(ciphertextList,AA,k,t)
# 利用破解所得的k,t和递增背包序列以及待破解密文,解密明文,思路同上述“解密”
def decryption(cipher,input_list,k,inv_t):
    sumx = []
    result_list=[]
    global qu_chong
    for i in cipher:
        sumx .append((inv_t * int(i)) % k)
    for sumxx in sumx:
        between_list=[]
        for i in range(len(input_list)):
            between_list.append(0)
        for i in range(len(input_list)-1,-1,-1):
            if(sumxx>=input_list[i]):
                sumxx-=input_list[i]
                between_list[i]=1
        result_list+=between_list
    if(qu_chong !=result_list):
        qu_chong=copy.deepcopy(result_list)#使用深拷贝
        print("去除前导0之前的result_list:",result_list)
        start=0
        end=0
        for i in range(len(result_list)):
            if result_list[i] !=0:
                break
            end = i + 1
        del result_list[start : end]
        result_list = map(str, result_list)
        result_list = "".join(result_list)

        print("解密以及去除前导0后的明文为:",result_list)
if __name__ == "__main__":
    listV = [1, 3, 7, 13, 26, 65, 119, 267]
    length = int(input("输入超递增向量元素个数:"))
    interval = int(input("输入随机增量:"))
    #length, interval = 8, 4
    listV = init(length, interval)
    print("初始向量:", listV)
    k, t, inverse_t = creatPKey(listV)
    print("\n私钥验证成功,分别为  <k:%d>, <t:%d>,<t逆元:%d>" %(k, t, inverse_t))
    sKeyList = creatSKey(listV, t, k)
    print("公钥向量为:", sKeyList, "\n")
    while True:
        choice = input("1、加密    2、解密    3、破解\n请选择:")
        if choice == "1":
            massage = input("输入明文(01序列):")
            ciphertextList = encrypt(massage, sKeyList)
            print("加密结果:", ciphertextList)
        elif choice == "2":
            ciphertextList = list(map(int, list(input("输入密文:").split(","))))
            sKeyList = list(map(int, list(input("输入公钥向量:").split(","))))
            k = int(input("输入密钥k:"))
            inverse_t = int(input("输入密钥t逆:"))
            pliantext = decrypt(ciphertextList, sKeyList, k, inverse_t)
            print("解密结果:", pliantext)
        elif choice=="3":
            ciphertext =list(map(int, list(input("输入密文:").split(","))))
            public =list(map(int, list(input("输入公钥向量:").split(","))))
            crack(public,ciphertext)

同时将两个常用函数分离了出来,组成模块modules,在源码中插入:

# 判断互质
def judgeCoPrime(a, b):
    # 求最大公因数
    def maxCommonFactor(m, n):
        result = 0
        while  m % n > 0:
            result = m % n
            m = n
            n = result
        return result
    if maxCommonFactor(a, b) == 1:
        return True
    return False

# 求逆元
def getInverse(a, b):
    # 扩展的欧几里得
    def extGcd(a_, b_, arr):
        if b_ == 0:
            arr[0] = 1
            arr[1] = 0
            return a_
        g = extGcd(b_, a_ % b_, arr)
        t = arr[0]
        arr[0] = arr[1]
        arr[1] = t - int(a_ / b_) * arr[1]
        return g
    # 求a模b的乘法逆x
    arr = [0,1,]
    gcd = extGcd(a, b, arr)
    if gcd == 1:
        return (arr[0] % b + b) % b
    else:
        return -1