Esempio n. 1
0
class ECDSA:
    """
    Digital Signature Algorithm using Elliptic Curves
    """
    def __init__(self, ec, G, n):
        self.ec = ec
        self.G = G
        self.GFn = FiniteField(n)

    def calcpub(self, privkey):
        """
        calculate the public key for private key x

        return G*x
        """
        return self.G * self.GFn.value(privkey)

    def sign(self, message, privkey, secret):
        """
        sign the message using private key and sign secret

        for signsecret k, message m, privatekey x
        return (G*k,  (m+x*r)/k)
        """
        m = self.GFn.value(message)
        x = self.GFn.value(privkey)
        k = self.GFn.value(secret)

        R = self.G * k

        r = self.GFn.value(R.x)
        s = (m + x * r) // k

        return (r, s)

    def calcr(self, k):
        R = self.G * k
        return self.GFn.value(R.x)

    def verify(self, message, pubkey, rnum, snum):
        """
        Verify the signature

        for message m, pubkey Y, signature (r,s)

        r = xcoord(R)

        verify that :  G*m+Y*r=R*s

        this is true because: { Y=G*x, and R=G*k, s=(m+x*r)/k }
         
        G*m+G*x*r = G*k*(m+x*r)/k  ->
        G*(m+x*r) = G*(m+x*r)

        several ways to do the verification:
            r == xcoord[ G*(m/s) + Y*(r/s) ]  <<< the standard way
            R * s == G*m + Y*r
            r == xcoord[ (G*m + Y*r)/s) ]
 
        """
        m = self.GFn.value(message)
        r = self.GFn.value(rnum)
        s = self.GFn.value(snum)

        R = self.G * (m // s) + pubkey * (r // s)

        # alternative methods of verifying
        #RORG= self.ec.decompress(r, 0)
        #RR = self.G * m + pubkey * r
        #print("#1: %s .. %s"  % (RR, RORG*s))
        #print("#2: %s .. %s"  % (RR*(1//s), r))
        #print("#3: %s .. %s"  % (R, r))

        return R.x == r

    def findpk(self, message, rnum, snum, flag):
        """
        find pubkey Y from message m, signature (r,s)
        Y = (R*s-G*m)/r

        note that there are 2 pubkeys related to a signature
        """
        m = self.GFn.value(message)
        r = self.GFn.value(rnum)
        s = self.GFn.value(snum)

        R = self.ec.decompress(r, flag)

        #return (R*s - self.G * m)*(1//r)
        return R * (s // r) - self.G * (m // r)

    def findpk2(self, r1, s1, r2, s2, flag1, flag2):
        """
        find pubkey Y from 2 different signature on the same message
        sigs: (r1,s1) and (r2,s2)

        returns  (R1*s1-R2*s2)/(r1-r2)
        """
        R1 = self.ec.decompress(r1, flag1)
        R2 = self.ec.decompress(r2, flag2)

        rdiff = self.GFn.value(r1 - r2)

        return (R1 * s1 - R2 * s2) * (1 // rdiff)

    def crack2(self, r, s1, s2, m1, m2):
        """
        find signsecret and privkey from duplicate 'r'

        signature (r,s1) for message m1
        and signature (r,s2) for message m2

        s1= (m1 + x*r)/k
        s2= (m2 + x*r)/k

        subtract -> (s1-s2) = (m1-m2)/k  ->  k = (m1-m2)/(s1-s2)

        -> privkey =  (s1*k-m1)/r  .. or  (s2*k-m2)/r
        """
        sdelta = self.GFn.value(s1 - s2)
        mdelta = self.GFn.value(m1 - m2)

        secret = mdelta // sdelta
        x1 = self.crack1(r, s1, m1, secret)
        x2 = self.crack1(r, s2, m2, secret)

        if x1 != x2:
            print("x1=%s" % x1)
            print("x2=%s" % x2)

        return (secret, x1)

    def crack1(self, rnum, snum, message, signsecret):
        """
        find privkey, given signsecret k, message m, signature (r,s)

        x= (s*k-m)/r
        """
        m = self.GFn.value(message)
        r = self.GFn.value(rnum)
        s = self.GFn.value(snum)
        k = self.GFn.value(signsecret)
        return (s * k - m) // r

    def find_k(self, message, privkey, rnum, snum):
        """
        find signing secret used to create signature, given message, privkey and signature

        k= (m+x*r)/s
        """
        m = self.GFn.value(message)
        r = self.GFn.value(rnum)
        s = self.GFn.value(snum)
        x = self.GFn.value(privkey)
        return (m + x * r) // s

    def find_M(self, rnum, snum, pubkey, flag):
        r = self.GFn.value(rnum)
        s = self.GFn.value(snum)
        R = self.ec.decompress(r, flag)

        M = R * s - pubkey * r

        return M
Esempio n. 2
0
class ECDSA:
    """
    Digital Signature Algorithm using Elliptic Curves
    """
    def __init__(self, ec, G, n):
        self.ec= ec
        self.G= G
        self.GFn= FiniteField(n)

    def calcpub(self, privkey):
        """
        calculate the public key for private key x

        return G*x
        """
        return self.G * self.GFn.value(privkey)

    def sign(self, message, privkey, secret):
        """
        sign the message using private key and sign secret

        for signsecret k, message m, privatekey x
        return (G*k,  (m+x*r)/k)
        """
        m= self.GFn.value(message)
        x= self.GFn.value(privkey)
        k= self.GFn.value(secret)

        R= self.G * k

        r= self.GFn.value(R.x)
        s= (m + x*r) / k

        return (r, s)

     
    def verify(self, message, pubkey, rnum, snum):
        """
        Verify the signature

        for message m, pubkey Y, signature (r,s)

        r = xcoord(R)

        verify that :  G*m+Y*r=R*s

        this is true because: { Y=G*x, and R=G*k, s=(m+x*r)/k }
         
        G*m+G*x*r = G*k*(m+x*r)/k  ->
        G*(m+x*r) = G*(m+x*r)

        several ways to do the verification:
            r == xcoord[ G*(m/s) + Y*(r/s) ]  <<< the standard way
            R * s == G*m + Y*r
            r == xcoord[ (G*m + Y*r)/s) ]
 
        """
        m= self.GFn.value(message)
        r= self.GFn.value(rnum)
        s= self.GFn.value(snum)

        R = self.G * (m/s) + pubkey * (r/s)

        # alternative methods of verifying
        #RORG= self.ec.decompress(r, 0)
        #RR = self.G * m + pubkey * r
        #print "#1: %s .. %s"  % (RR, RORG*s)
        #print "#2: %s .. %s"  % (RR*(1/s), r)
        #print "#3: %s .. %s"  % (R, r)

        return R.x == r

    def findpk(self, message, rnum, snum, flag):
        """
        find pubkey Y from message m, signature (r,s)
        Y = (R*s-G*m)/r

        note that there are 2 pubkeys related to a signature
        """
        m= self.GFn.value(message)
        r= self.GFn.value(rnum)
        s= self.GFn.value(snum)

        R= self.ec.decompress(r, flag)

        #return (R*s - self.G * m)*(1/r)
        return R*(s/r) - self.G * (m/r)

    def findpk2(self, r1, s1, r2, s2, flag1, flag2):
        """
        find pubkey Y from 2 different signature on the same message
        sigs: (r1,s1) and (r2,s2)

        returns  (R1*s1-R2*s2)/(r1-r2)
        """
        R1= self.ec.decompress(r1, flag1)
        R2= self.ec.decompress(r2, flag2)

        rdiff= self.GFn.value(r1-r2)

        return (R1*s1-R2*s2)*(1/rdiff)

    def crack2(self, r, s1, s2, m1, m2):
        """
        find signsecret and privkey from duplicate 'r'

        signature (r,s1) for message m1
        and signature (r,s2) for message m2

        s1= (m1 + x*r)/k
        s2= (m2 + x*r)/k

        subtract -> (s1-s2) = (m1-m2)/k  ->  k = (m1-m2)/(s1-s2)

        -> privkey =  (s1*k-m1)/r  .. or  (s2*k-m2)/r
        """
        sdelta= self.GFn.value(s1-s2)
        mdelta= self.GFn.value(m1-m2)

        secret= mdelta / sdelta
        x1= self.crack1(r, s1, m1, secret)
        x2= self.crack1(r, s2, m2, secret)

        if x1!=x2:
            print "x1=%s" % x1
            print "x2=%s" % x2

        return (secret, x1)

    def crack1(self, rnum, snum, message, signsecret):
        """
        find privkey, given signsecret k, message m, signature (r,s)

        x= (s*k-m)/r
        """
        m= self.GFn.value(message)
        r= self.GFn.value(rnum)
        s= self.GFn.value(snum)
        k= self.GFn.value(signsecret)
        return (s*k-m)/r

    def find_k(self, message, privkey, rnum, snum):
        """
        find signing secret used to create signature, given message, privkey and signature

        k= (m+x*r)/s
        """
        m= self.GFn.value(message)
        r= self.GFn.value(rnum)
        s= self.GFn.value(snum)
        x= self.GFn.value(privkey)
        return (m+x*r)/s