def xy2uv(curve, x, y): """Convert Weierstrass X,Y coordinates to twisted Edwards curve U,V """ s, t = curve.st() xmt = curve.pos(x - t) u = xmt * modinvert(y, curve.p) v = curve.pos(xmt - s) * modinvert(xmt + s, curve.p) return u % curve.p, v % curve.p
def uv2xy(curve, u, v): """Convert twisted Edwards curve U,V coordinates to Weierstrass X,Y """ s, t = curve.st() k1 = (s * (1 + v)) % curve.p k2 = curve.pos(1 - v) x = t + k1 * modinvert(k2, curve.p) y = k1 * modinvert(u * k2, curve.p) return x % curve.p, y % curve.p
def _add(self, p1x, p1y, p2x, p2y): if p1x == p2x and p1y == p2y: # double t = ( (3 * p1x * p1x + self.a) * modinvert(2 * p1y, self.p)) % self.p else: tx = self.pos(p2x - p1x) % self.p ty = self.pos(p2y - p1y) % self.p t = (ty * modinvert(tx, self.p)) % self.p tx = self.pos(t * t - p1x - p2x) % self.p ty = self.pos(t * (p1x - tx) - p1y) % self.p return tx, ty
def st(self): """Compute s/t parameters for twisted Edwards curve points conversion """ if self.e is None or self.d is None: raise ValueError("non twisted Edwards curve") if self._st is not None: return self._st self._st = ( self.pos(self.e - self.d) * modinvert(4, self.p) % self.p, (self.e + self.d) * modinvert(6, self.p) % self.p, ) return self._st
def exp(self, degree, x=None, y=None): p = self.p a = self.a x = x or self.x y = y or self.y X, Y, Z = 1, 1, 0 degree_bin = bin(degree)[2:] i = len(degree_bin) - 1 if i == 0: raise ValueError("Bad degree value") while i >= 0: # Doubling if Z != 0: lm2 = X * X % p * 3 lm1 = Z * Z * a % p lm1 += lm2 lm2 = Y * Z % p lm3 = lm2 * X * Y % p lm5 = lm3 * 8 lm4 = lm1 * lm1 % p - lm5 lm5 = lm2 * 2 % p lm6 = lm5 * 2 * lm5 % p X = lm4 * lm5 % p lm7 = Y * Y % p * lm6 Y = ((lm3 * 4 - lm4) * lm1 - lm7) % p Z = lm2 * lm6 % p if X < 0: X += p if Y < 0: Y += p if Z < 0: Z += p # Adding if degree_bin[-i - 1] == "1": if Z == 0: X, Y, Z = x, y, 1 else: lm1 = y * Z % p - Y lm3 = x * Z % p - X lm2 = lm3 * lm3 % p lm4 = lm2 * lm3 % p lm5 = 2 * X * lm2 % p lm6 = lm1 * lm1 * Z % p - lm4 - lm5 lm5 = Y * lm4 % p Y = ((lm2 * X - lm6) * lm1 - lm5) % p X = lm3 * lm6 % p Z = Z * lm4 % p if X < 0: X += p if Y < 0: Y += p if Z < 0: Z += p i -= 1 if Z == 0: return -1, -1 lm1 = modinvert(Z, p) r1, r2 = X * lm1 % p, Y * lm1 % p return r1, r2
def exp(self, degree, x=None, y=None): p = self.p a = self.a x = x or self.x y = y or self.y X, Y, Z = 1, 1, 0 degree_bin = bin(degree)[2:] i = len(degree_bin) - 1 if i == 0: raise ValueError("Bad degree value") while i >= 0: # Doubling if Z != 0: lm2 = X * X % p * 3 lm1 = Z * Z * a % p lm1 += lm2 lm2 = Y * Z % p lm3 = lm2 * X * Y % p lm5 = lm3 * 8 lm4 = lm1 * lm1 % p - lm5 lm5 = lm2 * 2 % p lm6 = lm5 * 2 * lm5 % p X = lm4 * lm5 % p lm7 = Y * Y % p * lm6 Y = ((lm3 * 4 - lm4) * lm1 - lm7) % p Z = lm2 * lm6 % p if X < 0: X += p if Y < 0: Y += p if Z < 0: Z += p # Adding if degree_bin[-i - 1] == "1": if Z == 0: X, Y, Z = x, y, 1 else: lm1 = y * Z % p - Y lm3 = x * Z % p - X lm2 = lm3 * lm3 % p lm4 = lm2 * lm3 % p lm5 = 2 * X * lm2 % p lm6 = lm1 * lm1 * Z % p - lm4 - lm5 lm5 = Y * lm4 % p Y = ((lm2 * X - lm6) * lm1 - lm5) % p X = lm3 * lm6 % p Z = Z * lm4 % p if X < 0: X += p if Y < 0: Y += p if Z < 0: Z += p i -= 1 if Z == 0: return -1, -1 lm1 = modinvert(Z, p) r1, r2 = X * lm1 % p, Y * lm1 % p return r1, r2
def verify(curve, pubkeyX, pubkeyY, digest, signature, size=SIZE_341001): """ Verify provided digest with the signature :param GOST3410Curve curve: curve to use :param long pubkeyX: public key's X :param long pubkeyY: public key's Y :param digest: digest needed to check :type digest: bytes, 32 bytes :param signature: signature to verify with :type signature: bytes, 64 bytes :param size: signature size :type size: 32 (for 34.10-2001) or 64 (for 34.10-2012) :rtype: bool """ if len(digest) != size: raise ValueError("Invalid digest length") if len(signature) != size * 2: raise ValueError("Invalid signature length") q = curve.q p = curve.p s = bytes2long(signature[:size]) r = bytes2long(signature[size:]) if r <= 0 or r >= q or s <= 0 or s >= q: return False e = bytes2long(digest) % curve.q if e == 0: e = 1 v = modinvert(e, q) z1 = s * v % q z2 = q - r * v % q p1x, p1y = curve.exp(z1) q1x, q1y = curve.exp(degree=z2, x=pubkeyX, y=pubkeyY) lm = q1x - p1x if lm < 0: lm += p lm = modinvert(lm, p) z1 = q1y - p1y lm = lm * z1 % p lm = lm * lm % p lm = lm - p1x - q1x lm = lm % p if lm < 0: lm += p lm %= q # This is not constant time comparison! return lm == r
def verify(curve, pubkeyX, pubkeyY, digest, signature, size=SIZE_341001): """ Verify provided digest with the signature :param GOST3410Curve curve: curve to use :param long pubkeyX: public key's X :param long pubkeyY: public key's Y :param digest: digest needed to check :type digest: bytes, 32 bytes :param signature: signature to verify with :type signature: bytes, 64 bytes :param size: signature size :type size: 32 (for 34.10-2001) or 64 (for 34.10-2012) :rtype: bool """ if len(digest) != size: raise ValueError("Invalid digest length") if len(signature) != size * 2: raise ValueError("Invalid signature length") q = curve.q p = curve.p s = bytes2long(signature[:size]) r = bytes2long(signature[size:]) if r <= 0 or r >= q or s <= 0 or s >= q: return False e = bytes2long(digest) % curve.q if e == 0: e = 1 v = modinvert(e, q) z1 = s * v % q z2 = q - r * v % q p1x, p1y = curve.exp(z1) q1x, q1y = curve.exp(degree=z2, x=pubkeyX, y=pubkeyY) lm = q1x - p1x if lm < 0: lm += p lm = modinvert(lm, p) z1 = q1y - p1y lm = lm * z1 % p lm = lm * lm % p lm = lm - p1x - q1x lm = lm % p if lm < 0: lm += p lm %= q # This is not constant time comparison! return lm == r
def verify(curve, pub, digest, signature, mode=2001): """ Verify provided digest with the signature :param GOST3410Curve curve: curve to use :type pub: (long, long) :param digest: digest needed to check :type digest: bytes, 32 or 64 bytes :param signature: signature to verify with :type signature: bytes, 64 or 128 bytes :rtype: bool """ size = MODE2SIZE[mode] if len(signature) != size * 2: raise ValueError("Invalid signature length") q = curve.q p = curve.p s = bytes2long(signature[:size]) r = bytes2long(signature[size:]) if r <= 0 or r >= q or s <= 0 or s >= q: return False e = bytes2long(digest) % curve.q if e == 0: e = 1 v = modinvert(e, q) z1 = s * v % q z2 = q - r * v % q p1x, p1y = curve.exp(z1) q1x, q1y = curve.exp(z2, pub[0], pub[1]) lm = q1x - p1x if lm < 0: lm += p lm = modinvert(lm, p) z1 = q1y - p1y lm = lm * z1 % p lm = lm * lm % p lm = lm - p1x - q1x lm = lm % p if lm < 0: lm += p lm %= q # This is not constant time comparison! return lm == r