Ejemplo n.º 1
0
    def __init__(self, hasher, option="ISO", fmt="DER"):
        if not option in ("ISO","ISOx","BSI","LIBSECP","Z"):
            raise ECPyException('ECSchnorr option not supported: %s'%option)
        if not fmt in list_formats():
            raise ECPyException('ECSchnorr format not supported: %s'%fmt)

        self._hasher = hasher
        self.fmt = fmt
        self.maxtries = 100
        self.option = option
Ejemplo n.º 2
0
    def _do_sign(self, msg, pv_key, k):
        if (pv_key.curve == None):
            raise ECPyException('private key haz no curve')
        curve = pv_key.curve
        n = curve.order
        G = curve.generator
        size = curve.size >> 3

        Q = G * k
        hasher = self._hasher()
        if self.option == "ISO":
            xQ = (Q.x).to_bytes(size, 'big')
            yQ = (Q.y).to_bytes(size, 'big')
            hasher.update(xQ + yQ + msg)
            r = hasher.digest()
            r = int.from_bytes(r, 'big')
            s = (k + r * pv_key.d) % n
            if r == 0 or s == 0:
                return None

        elif self.option == "ISOx":
            xQ = (Q.x).to_bytes(size, 'big')
            hasher.update(xQ + msg)
            r = hasher.digest()
            r = int.from_bytes(r, 'big')
            s = (k + r * pv_key.d) % n
            if r == 0 or s == 0:
                return None

        elif self.option == "BSI":
            xQ = Q.x.to_bytes(size, 'big')
            hasher.update(msg + xQ)
            r = hasher.digest()
            r = int.from_bytes(r, 'big')
            s = (k - r * pv_key.d) % n
            if r == 0 or s == 0:
                return None

        elif self.option == "LIBSECP":
            if Q.y & 1:
                k = n - k
                Q = G * k
            r = (Q.x % n).to_bytes(size, 'big')
            hasher.update(r + msg)
            h = hasher.digest()
            h = int.from_bytes(h, 'big')
            r = Q.x % n
            s = (k - h * pv_key.d) % n
        return encode_sig(r, s, self.fmt)
Ejemplo n.º 3
0
    def sign_secp256k1(self, msg, pv_key, algo16=b""):
        """
        Specific signature for SECP256K1 curve:
        https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr.mediawiki

        Args:
            msg (bytes)                    : the message hash to sign
            pv_key (ecpy.keys.ECPrivateKey): key to use for signing
        """
        if pv_key.curve.name != 'secp256k1':
            raise ECPyException("specific 'secp256k1' curve signature")

        n = pv_key.curve.order
        size = pv_key.curve.size >> 3

        # Let P = dG
        P = pv_key.curve.generator * pv_key.d
        # Let k = int(hash(bytes(d) || m)) mod
        data = pv_key.d.to_bytes(size, "big") + msg + algo16[:16]
        k = int.from_bytes(self._hasher(data).digest(), "big") % n
        # Fail if k = 0
        if k == 0:
            raise ECPyException("signature failed")
        return self._do_sign(msg, pv_key, k)
Ejemplo n.º 4
0
    def _do_sign(self, msg, pv_key, k):
        if (pv_key.curve == None):
            raise ECPyException('private key haz no curve')
        curve = pv_key.curve
        n     = curve.order
        G     = curve.generator
        size  = (curve.size+7)//8

        Q = G*k
        hasher = self._hasher()
        if self.option == "ISO":
            xQ = (Q.x).to_bytes(size,'big')
            yQ = (Q.y).to_bytes(size,'big')
            hasher.update(xQ+yQ+msg)
            r = hasher.digest()
            r = int.from_bytes(r,'big')
            if r % n == 0:
                return None
            s = (k+r*pv_key.d)%n
            if s==0:
                return None

        elif self.option == "ISOx":
            xQ = (Q.x).to_bytes(size,'big')
            hasher.update(xQ+msg)
            r = hasher.digest()
            r = int.from_bytes(r,'big')
            if r % n == 0:
                return None
            s = (k+r*pv_key.d)%n
            if s==0:
                return None

        elif self.option == "BSI":
            xQ = Q.x.to_bytes(size,'big')
            hasher.update(msg+xQ)
            r = hasher.digest()
            r = int.from_bytes(r,'big')
            if r%n == 0:
                return None
            s = (k-r*pv_key.d)%n
            if s==0:
                return None

        elif self.option == "LIBSECP":
            if Q.y & 1:
                k = n-k
                Q = G*k
            r = (Q.x%n).to_bytes(size,'big')
            hasher.update(r+msg)
            h = hasher.digest()
            h = int.from_bytes(h,'big')
            if h > n:
                return None
            r = Q.x % n
            s = (k - h*pv_key.d)%n

        elif self.option == "Z":
            if Q.y & 1:
                xQ = b'\x03'+Q.x.to_bytes(size,'big')
            else :
                xQ = b'\x02'+Q.x.to_bytes(size,'big')
            pu_key = pv_key.get_public_key()
            if pu_key.W.y & 1:
                xPub = b'\x03'+pu_key.W.x.to_bytes(size,'big')
            else :
                xPub = b'\x02'+pu_key.W.x.to_bytes(size,'big')
            hasher.update(xQ+xPub+msg)
            r = hasher.digest()
            r = int.from_bytes(r,'big') % n
            if r % n == 0:
                return None
            s = (k - r*pv_key.d) %n
            if s==0:
                return None

        return encode_sig(r, s, self.fmt)
Ejemplo n.º 5
0
    def _do_sign(self, msg, pv_key, k):
        if (pv_key.curve == None):
            raise ECPyException('private key has no curve')
        curve = pv_key.curve
        n = curve.order
        G = curve.generator
        size = curve.size >> 3

        Q = G * k
        hasher = self._hasher()
        if self.option == "ISO":
            xQ = (Q.x).to_bytes(size, 'big')
            yQ = (Q.y).to_bytes(size, 'big')
            hasher.update(xQ + yQ + msg)
            r = hasher.digest()
            r = int.from_bytes(r, 'big')
            s = (k + r * pv_key.d) % n
            if r == 0 or s == 0:
                return None

        elif self.option == "ISOx":
            xQ = (Q.x).to_bytes(size, 'big')
            hasher.update(xQ + msg)
            r = hasher.digest()
            r = int.from_bytes(r, 'big')
            s = (k + r * pv_key.d) % n
            if r == 0 or s == 0:
                return None

        elif self.option == "BSI":
            xQ = Q.x.to_bytes(size, 'big')
            hasher.update(msg + xQ)
            r = hasher.digest()
            r = int.from_bytes(r, 'big')
            s = (k - r * pv_key.d) % n
            if r == 0 or s == 0:
                return None

        elif self.option == "LIBSECP":
            if Q.y & 1:
                k = n - k
                Q = G * k
            r = (Q.x % n).to_bytes(size, 'big')
            hasher.update(r + msg)
            h = hasher.digest()
            h = int.from_bytes(h, 'big')
            r = Q.x % n
            s = (k - h * pv_key.d) % n

        elif self.option == "Z":
            if Q.y & 1:
                xQ = b'\x03' + Q.x.to_bytes(size, 'big')
            else:
                xQ = b'\x02' + Q.x.to_bytes(size, 'big')
            pu_key = pv_key.get_public_key()
            if pu_key.W.y & 1:
                xPub = b'\x03' + pu_key.W.x.to_bytes(size, 'big')
            else:
                xPub = b'\x02' + pu_key.W.x.to_bytes(size, 'big')
            hasher.update(xQ + xPub + msg)
            r = hasher.digest()
            r = int.from_bytes(r, 'big') % n
            s = (k - r * pv_key.d) % n
            if r == 0 or s == 0:
                return None

        # https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr.mediawiki
        elif self.option == "SECP256K1":
            # R = Q...
            # Let k = k' if jacobi(y(R)) = 1, otherwise let k = n - k'
            k = k if _jacobi(Q.y, pv_key.curve.field) == 1 else n - k
            # Let P = d'G
            P = G * pv_key.d
            # Let e = int(hash(bytes(R) || bytes(P) || m)) mod n
            e = int.from_bytes(
                self._hasher(Q.x.to_bytes(size, "big") + P.serialize() +
                             msg).digest(), "big") % n
            # The signature is bytes(R) || bytes((k + ed) mod n)
            r = Q.x % n
            s = (k + e * pv_key.d) % n

        return encode_sig(r, s, self.fmt,
                          0 if self.fmt not in ["RAW", "EDDSA"] else size)