def point_addition(self, P, Q): x = (P.x * Q.y + Q.x * P.y) % self.p x = (x * NumberTheory.modinv(1 + self.d * P.x * Q.x * P.y * Q.y, self.p)) % self.p y = (P.y * Q.y - self.a * P.x * Q.x) % self.p y = (y * NumberTheory.modinv(1 - self.d * P.x * Q.x * P.y * Q.y, self.p)) % self.p return self.point(x, y)
def decode_point(self, serialized_point): assert (isinstance(serialized_point, bytes)) if len(serialized_point) != self.element_octet_cnt: raise InvalidInputException( "Do not know how to decode %s point. Expected %d octets, but got %d." % (str(self), self.element_octet_cnt, len(serialized_point))) serialized_point = bytearray(serialized_point) x_lsb = (serialized_point[-1] >> 7) & 1 serialized_point[-1] &= 0x7f y = int.from_bytes(serialized_point, byteorder="little") if y >= self.p: raise InvalidInputException( "y coordinate of point must be smaller than p.") # x^2 = (1 - y^2) / (a - dy^2) x2 = (1 - y * y) % self.p x2 *= NumberTheory.modinv(self.a - self.d * y * y, self.p) (x_pos, x_neg) = NumberTheory.sqrt_mod_p(x2, self.p) if x_lsb == 0: x = x_pos else: x = x_neg point = self.point(x, y) return point
def point_addition(self, P, Q): if P is None: # O + Q = Q return Q elif Q is None: # P + O = P return P elif ((P.x == Q.x) and (((P.y + Q.y) % self.p) == 0)): # P + (-P) = O return None elif P == Q: # Point doubling s = ((3 * P.x**2) + self.a) * NumberTheory.modinv(2 * P.y, self.p) x = (s * s - (2 * P.x)) % self.p y = (s * (P.x - x) - P.y) % self.p return EllipticCurvePoint(self, x, y) else: # Point addition s = (P.y - Q.y) * NumberTheory.modinv(P.x - Q.x, self.p) x = ((s**2) - P.x - Q.x) % self.p y = (s * (P.x - x) - P.y) % self.p return EllipticCurvePoint(self, x, y)
def create(cls, p, q, e=0x10001, swap_e_d=False, valid_only=True, carmichael_totient=False): n = p * q if not carmichael_totient: totient = (p - 1) * (q - 1) else: totient = NumberTheory.lcm(p - 1, q - 1) gcd = NumberTheory.gcd(e, totient) if (gcd != 1) and valid_only: raise KeyCorruptException( "e = 0x%x isnt't relative prime to totient, gcd = 0x%x. Either accept broken keys or fix e." % (e, gcd)) d = NumberTheory.modinv(e, totient) if swap_e_d: (e, d) = (d, e) dmp1 = d % (p - 1) dmq1 = d % (q - 1) iqmp = NumberTheory.modinv(q, p) asn1 = cls._ASN1_MODEL() asn1["version"] = 0 asn1["modulus"] = n asn1["publicExponent"] = e asn1["privateExponent"] = d asn1["prime1"] = p asn1["prime2"] = q asn1["exponent1"] = dmp1 asn1["exponent2"] = dmq1 asn1["coefficient"] = iqmp der = pyasn1.codec.der.encoder.encode(asn1) return cls(der)
def test_modinv(self): p = 2003 for _ in range(10): r = random.randint(2, p - 1) inv = NumberTheory.modinv(r, p) self.assertEqual(r * inv % p, 1)
def test_modinv_exception(self): with self.assertRaises(InvalidInputException): NumberTheory.modinv(0, 101)