import time
from math import *
from time import *

from pypbc import *



def sigcost(M, m, n):
    def H0(ID, R):
        h0 = Element(pairing, Zr, value=hash(str([ID, R])))
        return h0

    def H1(ID, i):
        h1 = Element(pairing, G1, value=hash(str([ID, i])))
        return h1

    def H2(ID, j, tau):
        h2 = Element(pairing, Zr, value=hash(str([ID, j, tau])))
        return h2

    def H3(vk, ID):
        h3 = Element(pairing, G1, value=hash(str([vk, ID])))
        return h3

    def lH2(v):
        h2 = Element(pairing, G1, value=hash(str(v)))
        return h2

    def lH3(h2, pkB, skA):
        pairs = pairing.apply(h2, pkB)
        h3 = Element(pairing, G1, value=pairs ** skA)
        return h3

 
    p = 80 
    p1 = get_random_prime(2 * p)
    p2 = get_random_prime(4 * p) 
    params = Parameters(n=p1*p2)
    pairing = Pairing(params)
    g = Element.random(pairing, G1) 
    h = Element.random(pairing, G2) 
    s = Element.random(pairing, Zr)  
    mpk = Element(pairing, G2, value=h ** s)  

  
    def resignUser(ID):
        r = Element.random(pairing, Zr) 
        R = Element(pairing, G2, value=h ** r)  
        ID = Element.random(pairing, Zr)
        x = Element(pairing, Zr, value=r + s * H0(ID, R))
        temp1 = pairing.apply(g ** x, h)
        temp2 = pairing.apply(g, R * (mpk ** H0(ID, R)))
        if temp1 == temp2:
            return x, R
        else:
            print('error')

    Signer_ID = Element.random(pairing, Zr)
    Receiver_ID = Element.random(pairing, Zr)
    Combiner_ID = {}
    T = m
    for i in range(0, T): 
        Combiner_ID[i] = Element.random(pairing, Zr)
    Signer_x, Signer_R = resignUser(Signer_ID)
    Receiver_x, Receiver_R = resignUser(Receiver_ID)
    Combiner_x = {}
    Combiner_R = {}
    for i in range(0, T):
        Combiner_x[i], Combiner_R[i] = resignUser(Combiner_ID[i])

    def Combiner(t):
        B = int(Element.random(pairing, Zr))
        b = {}
        q = {}
        Q = 1
        for i in range(0, t):
            q[i] = int(Element.random(pairing, Zr))
            b[i] = Element(pairing, Zr, value=B % q[i])
            Q *= q[i]
        return B, b, q, Q
    T0=time()
    B, b, q, Q = Combiner(T)
    T1=time()
    delta_t=T1-T0
    def comp(m, n):  
        mk = []
        vk = []
        h1 = H1(Signer_ID, Element(pairing, Zr, value=m - 1))
        h2 = []
        h3 = H3(vk, Signer_ID)
        Hm = Element(pairing, Zr, value=1)
        for j in range(0, n):
            mk.append(Element.random(pairing, Zr))
            h2.append(H2(Signer_ID, j, Element.random(pairing, Zr)))
        for i in range(0, m):
            if i == m - 1:
                vk.append(Element(pairing, Zr, value=0))
            else:
                vk.append(Element(pairing, Zr, value=1))
        t0 = time()
        for j in range(0, n):
            Hm += Element(pairing, Zr, value=h2[j] * mk[j])
        sigk = Element(pairing, G1, value=h1 * (g ** (Hm)))
        Sig = Element(pairing, G1, value=(sigk ** Signer_x) * (h3 ** (B % Q)))
        t1 = time()
        print('sig1:%fs' % ((t1 - t0) * m+delta_t))
        sigj = Element(pairing, G1, value=sigk ** Signer_x)
        e0 = time()
        tempBegin = pairing.apply(sigj, h)
        tempEnd = pairing.apply(sigk, Signer_R * (mpk ** H0(Signer_ID, Signer_R)))
        e1 = time()
        print('ver1:%fs' % ((e1 - e0) * n * m / T))
        Gj = Element(pairing, G1, value=1)
        a = Element.random(pairing, Zr)
        b = Element(pairing, G2, value=h ** a)
        t2 = time()
        for j in range(0, n):
            Gj *= Element(pairing, G1, value=g ** mk[j])
        sigL = Element(pairing, G1, value=h1 * Gj)
        sigLin = Element(pairing, G1, value=(sigL ** a) * lH3(lH2(vk), b, a))
        t3 = time()
        print('sig2:%fs' % ((t3 - t2) * m))
        e3 = time()
        tempBe = pairing.apply(sigLin, h)
        tempEn = pairing.apply(sigL, b) * pairing.apply(lH3(lH2(vk), b, a), h)
        e4 = time()
        if tempBe == tempEn:
            print('ver2:%fs' % ((e4 - e3) * n * m))
        else:
            print('error')
        t4 = time()
        for j in range(0, n):
            Gj *= Element(pairing, G1, value=g ** mk[j])
        sigBon = Element(pairing, G1, value=h1 * Gj)
        sigBoneh = Element(pairing, G1, value=sigBon ** a)
        t5 = time()
        print('sig3:%fs' % ((t5 - t4) * m))
        e5 = time()
        tempB = pairing.apply(sigBoneh, h)
        tempE = pairing.apply(sigBon, b)
        e6 = time()
        if tempB == tempE:
            print('ver3:%fs' % ((e6 - e5) * n * m))
        else:
            print('error')

    if m + n <= 73:
        if 20 * m * n * T >= M:
            if 20 * (m - 1) * n * T <= M:
                print('%d%d' % (n, m))
                comp(m, n)
                print('\n')
