def test_init(self): with self.assertRaises(ValueError): EllipticCurve( MontgomeryModel(), self.secp128r1.curve.coordinate_model, 1, InfinityPoint(self.secp128r1.curve.coordinate_model), parameters={}, ) with self.assertRaises(ValueError): EllipticCurve( self.secp128r1.curve.model, self.secp128r1.curve.coordinate_model, 15, InfinityPoint(self.secp128r1.curve.coordinate_model), parameters={"c": 0}, ) with self.assertRaises(ValueError): EllipticCurve( self.secp128r1.curve.model, self.secp128r1.curve.coordinate_model, 15, InfinityPoint(self.secp128r1.curve.coordinate_model), parameters={"a": Mod(1, 5), "b": Mod(2, 5)}, )
def test_to_from_affine(self): pt = Point(self.coords, X=Mod(0x161ff7528b899b2d0c28607ca52c5b86, self.secp128r1.curve.prime), Y=Mod(0xcf5ac8395bafeb13c02da292dded7a83, self.secp128r1.curve.prime), Z=Mod(1, self.secp128r1.curve.prime)) other = pt.to_affine().to_model(self.coords, self.secp128r1.curve) self.assertEqual(pt, other)
def test_bytes(self): pt = Point(self.coords, X=Mod(0x4, self.secp128r1.curve.prime), Y=Mod(0x6, self.secp128r1.curve.prime), Z=Mod(2, self.secp128r1.curve.prime)) self.assertEqual( bytes(pt), b"\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02" ) self.assertEqual(bytes(InfinityPoint(self.coords)), b"\x00")
def generate(self) -> Tuple[int, Point]: resp = self.send_cmd(SMessage.from_raw(cmd_generate()), self.timeout) priv = resp["s"].data pub = resp["w"].data self.privkey = int(priv, 16) pub_len = len(pub) x = int(pub[:pub_len // 2], 16) y = int(pub[pub_len // 2:], 16) self.pubkey = Point(AffineCoordinateModel(self.model), x=Mod(x, self.params.curve.prime), y=Mod(y, self.params.curve.prime)) return self.privkey, self.pubkey
def test_to_from_affine(self): pt = Point( self.coords, X=Mod(0x161FF7528B899B2D0C28607CA52C5B86, self.secp128r1.curve.prime), Y=Mod(0xCF5AC8395BAFEB13C02DA292DDED7A83, self.secp128r1.curve.prime), Z=Mod(1, self.secp128r1.curve.prime), ) other = pt.to_affine().to_model(self.coords, self.secp128r1.curve) self.assertEqual(pt, other)
def setUp(self): self.secp128r1 = get_params("secg", "secp128r1", "projective") self.add = self.secp128r1.curve.coordinate_model.formulas[ "add-2007-bl"] self.dbl = self.secp128r1.curve.coordinate_model.formulas[ "dbl-2007-bl"] self.mult = LTRMultiplier(self.add, self.dbl) self.priv_a = Mod(0xDEADBEEF, self.secp128r1.order) self.mult.init(self.secp128r1, self.secp128r1.generator) self.pub_a = self.mult.multiply(int(self.priv_a)) self.priv_b = Mod(0xCAFEBABE, self.secp128r1.order) self.pub_b = self.mult.multiply(int(self.priv_b))
def test_inverse(self): p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF self.assertEqual( Mod( 0x702BDAFD3C1C837B23A1CB196ED7F9FADB333C5CFE4A462BE32ADCD67BFB6AC1, p).inverse(), Mod( 0x1CB2E5274BBA085C4CA88EEDE75AE77949E7A410C80368376E97AB22EB590F9D, p), ) with self.assertRaises(NonInvertibleError): Mod(0, p).inverse() with self.assertRaises(NonInvertibleError): Mod(5, 10).inverse() getconfig().ec.no_inverse_action = "warning" with warnings.catch_warnings(record=True) as w: Mod(0, p).inverse() self.assertTrue(issubclass(w[0].category, NonInvertibleWarning)) with warnings.catch_warnings(record=True) as w: Mod(5, 10).inverse() self.assertTrue(issubclass(w[0].category, NonInvertibleWarning)) getconfig().ec.no_inverse_action = "ignore" Mod(0, p).inverse() Mod(5, 10).inverse() getconfig().ec.no_inverse_action = "error"
def test_equals(self): pt = Point(self.coords, X=Mod(0x4, self.secp128r1.curve.prime), Y=Mod(0x6, self.secp128r1.curve.prime), Z=Mod(2, self.secp128r1.curve.prime)) other = Point(self.coords, X=Mod(0x2, self.secp128r1.curve.prime), Y=Mod(0x3, self.secp128r1.curve.prime), Z=Mod(1, self.secp128r1.curve.prime)) self.assertTrue(pt.equals(other)) self.assertNotEqual(pt, other) self.assertFalse(pt.equals(2)) self.assertNotEqual(pt, 2) infty_one = InfinityPoint(self.coords) infty_other = InfinityPoint(self.coords) self.assertTrue(infty_one.equals(infty_other)) self.assertEqual(infty_one, infty_other) mont = MontgomeryModel() different = Point(mont.coordinates["xz"], X=Mod(0x64daccd2656420216545e5f65221eb, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa), Z=Mod(1, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)) self.assertFalse(pt.equals(different)) self.assertNotEqual(pt, different)
def test_sqrt(self): p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff self.assertIn( Mod( 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc, p).sqrt(), (0x9add512515b70d9ec471151c1dec46625cd18b37bde7ca7fb2c8b31d7033599d, 0x6522aed9ea48f2623b8eeae3e213b99da32e74c9421835804d374ce28fcca662 )) q = 0x75d44fee9a71841ae8403c0c251fbad self.assertIn( Mod(0x591e0db18cf1bd81a11b2985a821eb3, q).sqrt(), (0x113b41a1a2b73f636e73be3f9a3716e, 0x64990e4cf7ba44b779cc7dcc8ae8a3f))
def test_ecdh_raw(self): self.target.allocate_ka(KeyAgreementEnum.ALG_EC_SVDP_DH) self.target.allocate(KeypairEnum.KEYPAIR_LOCAL, KeyBuildEnum.BUILD_KEYPAIR, 256, KeyClassEnum.ALG_EC_FP) self.target.set(KeypairEnum.KEYPAIR_LOCAL, CurveEnum.secp256r1, ParameterEnum.DOMAIN_FP) self.target.generate(KeypairEnum.KEYPAIR_LOCAL) mult = LTRMultiplier( self.secp256r1_projective.curve.coordinate_model.formulas["add-2016-rcb"], self.secp256r1_projective.curve.coordinate_model.formulas["dbl-2016-rcb"]) keygen = KeyGeneration(copy(mult), self.secp256r1_projective) priv, pubkey_projective = keygen.generate() ecdh_resp = self.target.ecdh_direct(KeypairEnum.KEYPAIR_LOCAL, True, TransformationEnum.NONE, KeyAgreementEnum.ALG_EC_SVDP_DH, bytes(pubkey_projective.to_affine())) self.assertTrue(ecdh_resp.success) export_privkey_resp = self.target.export(KeypairEnum.KEYPAIR_LOCAL, KeyEnum.PRIVATE, ParameterEnum.S) privkey = Mod(int.from_bytes( export_privkey_resp.get_param(KeypairEnum.KEYPAIR_LOCAL, ParameterEnum.S), "big"), self.secp256r1.curve.prime) ecdh = ECDH_SHA1(copy(mult), self.secp256r1_projective, pubkey_projective, privkey) expected = ecdh.perform() self.assertEqual(ecdh_resp.secret, expected)
def test_ecdh(self): self.target.allocate_ka(KeyAgreementEnum.ALG_EC_SVDP_DH) self.target.allocate(KeypairEnum.KEYPAIR_BOTH, KeyBuildEnum.BUILD_KEYPAIR, 256, KeyClassEnum.ALG_EC_FP) self.target.set(KeypairEnum.KEYPAIR_BOTH, CurveEnum.secp256r1, ParameterEnum.DOMAIN_FP) self.target.generate(KeypairEnum.KEYPAIR_BOTH) ecdh_resp = self.target.ecdh(KeypairEnum.KEYPAIR_LOCAL, KeypairEnum.KEYPAIR_REMOTE, True, TransformationEnum.NONE, KeyAgreementEnum.ALG_EC_SVDP_DH) self.assertTrue(ecdh_resp.success) export_public_resp = self.target.export(KeypairEnum.KEYPAIR_LOCAL, KeyEnum.PUBLIC, ParameterEnum.W) pubkey_bytes = export_public_resp.get_param(KeypairEnum.KEYPAIR_LOCAL, ParameterEnum.W) pubkey = self.secp256r1.curve.decode_point(pubkey_bytes) export_privkey_resp = self.target.export(KeypairEnum.KEYPAIR_REMOTE, KeyEnum.PRIVATE, ParameterEnum.S) privkey = Mod(int.from_bytes( export_privkey_resp.get_param(KeypairEnum.KEYPAIR_REMOTE, ParameterEnum.S), "big"), self.secp256r1.curve.prime) pubkey_projective = pubkey.to_model(self.secp256r1_projective.curve.coordinate_model, self.secp256r1.curve) mult = LTRMultiplier( self.secp256r1_projective.curve.coordinate_model.formulas["add-2016-rcb"], self.secp256r1_projective.curve.coordinate_model.formulas["dbl-2016-rcb"]) ecdh = ECDH_SHA1(mult, self.secp256r1_projective, pubkey_projective, privkey) expected = ecdh.perform() self.assertEqual(ecdh_resp.secret, expected)
def test_implementation(self): if not has_gmp: self.skipTest( "Only makes sense if more Mod implementations are available.") with TemporaryConfig() as cfg: cfg.ec.mod_implementation = "python" self.assertIsInstance(Mod(5, 7), RawMod)
def scalar_mult(self, scalar: int, point: Point) -> Point: resp = self.send_cmd(SMessage.from_raw(cmd_scalar_mult(scalar, point)), self.timeout) result = resp["w"] plen = ((self.params.curve.prime.bit_length() + 7) // 8) * 2 params = {var: Mod(int(result.data[i * plen:(i + 1) * plen], 16), self.params.curve.prime) for i, var in enumerate(self.coords.variables)} return Point(self.coords, **params)
def test_affine_add(self): pt = Point( AffineCoordinateModel(self.secp128r1.curve.model), x=Mod(0xEB916224EDA4FB356421773573297C15, self.secp128r1.curve.prime), y=Mod(0xBCDAF32A2C08FD4271228FEF35070848, self.secp128r1.curve.prime), ) self.assertIsNotNone(self.secp128r1.curve.affine_add(self.affine_base, pt)) added = self.secp128r1.curve.affine_add(self.affine_base, self.affine_base) doubled = self.secp128r1.curve.affine_double(self.affine_base) self.assertEqual(added, doubled) self.assertEqual( self.secp128r1.curve.affine_add(self.secp128r1.curve.neutral, pt), pt ) self.assertEqual( self.secp128r1.curve.affine_add(pt, self.secp128r1.curve.neutral), pt )
def test_to_affine(self): pt = Point(self.coords, X=Mod(0x161ff7528b899b2d0c28607ca52c5b86, self.secp128r1.curve.prime), Y=Mod(0xcf5ac8395bafeb13c02da292dded7a83, self.secp128r1.curve.prime), Z=Mod(1, self.secp128r1.curve.prime)) affine = pt.to_affine() self.assertIsInstance(affine.coordinate_model, AffineCoordinateModel) self.assertSetEqual(set(affine.coords.keys()), set(self.affine.variables)) self.assertEqual(affine.coords["x"], pt.coords["X"]) self.assertEqual(affine.coords["y"], pt.coords["Y"]) self.assertEqual(affine.to_affine(), affine) affine = InfinityPoint(self.coords).to_affine() self.assertIsInstance(affine, InfinityPoint)
def get_pubkey(ctx: click.Context, param, value: Optional[str]) -> Point: if value is None: return None ctx.ensure_object(dict) curve: DomainParameters = ctx.obj["params"] if re.match("^04([0-9a-fA-F]{2})+$", value): value = value[2:] plen = len(value) // 2 x = int(value[:plen], 16) y = int(value[plen:], 16) elif re.match("^[0-9]+,[0-9]+$", value): xs, ys = value.split(",") x = int(xs) y = int(ys) else: raise click.BadParameter("Couldn't parse pubkey: {}.".format(value)) x = Mod(x, curve.curve.prime) y = Mod(y, curve.curve.prime) return Point(AffineCoordinateModel(curve.curve.model), x=x, y=y)
def test_to_affine(self): pt = Point( self.coords, X=Mod(0x161FF7528B899B2D0C28607CA52C5B86, self.secp128r1.curve.prime), Y=Mod(0xCF5AC8395BAFEB13C02DA292DDED7A83, self.secp128r1.curve.prime), Z=Mod(1, self.secp128r1.curve.prime), ) affine = pt.to_affine() self.assertIsInstance(affine.coordinate_model, AffineCoordinateModel) self.assertSetEqual(set(affine.coords.keys()), set(self.affine.variables)) self.assertEqual(affine.coords["x"], pt.coords["X"]) self.assertEqual(affine.coords["y"], pt.coords["Y"]) self.assertEqual(affine.to_affine(), affine) affine = InfinityPoint(self.coords).to_affine() self.assertIsInstance(affine, InfinityPoint)
def test_encode_decode(self): data = { "a": encode_scalar(0xcafebabe), "b": { "c": encode_scalar(Mod(1, 3)), "d": bytes([0x2]) } } encoded = encode_data(None, data) result = decode_data(encoded) self.assertEqual(data, result)
def setUp(self): self.secp128r1 = get_params("secg", "secp128r1", "projective") self.add = self.secp128r1.curve.coordinate_model.formulas[ "add-2007-bl"] self.dbl = self.secp128r1.curve.coordinate_model.formulas[ "dbl-2007-bl"] self.mult = LTRMultiplier(self.add, self.dbl) self.msg = 0xCAFEBABE.to_bytes(4, byteorder="big") self.priv = Mod(0xDEADBEEF, self.secp128r1.order) self.mult.init(self.secp128r1, self.secp128r1.generator) self.pub = self.mult.multiply(self.priv.x)
def test_to_model(self): affine = Point(self.affine, x=Mod(0xabcd, self.secp128r1.curve.prime), y=Mod(0xef, self.secp128r1.curve.prime)) projective_model = self.coords other = affine.to_model(projective_model, self.secp128r1.curve) self.assertEqual(other.coordinate_model, projective_model) self.assertSetEqual(set(other.coords.keys()), set(projective_model.variables)) self.assertEqual(other.coords["X"], affine.coords["x"]) self.assertEqual(other.coords["Y"], affine.coords["y"]) self.assertEqual(other.coords["Z"], Mod(1, self.secp128r1.curve.prime)) infty = InfinityPoint(AffineCoordinateModel( self.secp128r1.curve.model)) other_infty = infty.to_model(self.coords, self.secp128r1.curve) self.assertIsInstance(other_infty, InfinityPoint) with self.assertRaises(ValueError): self.base.to_model(self.coords, self.secp128r1.curve)
class OpTests(TestCase): @parameterized.expand([ ("add", "x = a+b", "x = a+b", OpType.Add), ("sub", "x = a-b", "x = a-b", OpType.Sub), ("mul", "y = a*b", "y = a*b", OpType.Mult), ("div", "z = a/b", "z = a/b", OpType.Div), ("inv", "z = 1/b", "z = 1/b", OpType.Inv), ("pow", "b = a**d", "b = a^d", OpType.Pow), ("sqr", "b = a**2", "b = a^2", OpType.Sqr), ("id1", "b = 7", "b = 7", OpType.Id), ("id2", "b = a", "b = a", OpType.Id), ]) def test_str(self, name, module, result, op_type): code = parse(module, mode="exec") op = CodeOp(code) self.assertEqual(str(op), result) self.assertEqual(op.operator, op_type) @parameterized.expand([ ("add", "x = a+b", {"a": Mod(5, 21), "b": Mod(7, 21)}, Mod(12, 21)), ("sub", "x = a-b", {"a": Mod(7, 21), "b": Mod(5, 21)}, Mod(2, 21)) ]) def test_call(self, name, module, locals, result): code = parse(module, mode="exec") op = CodeOp(code) res = op(**locals) self.assertEqual(res, result)
def test_symbolic(self): p = self.secp128r1.curve.prime k = FF(p) coords = self.secp128r1.curve.coordinate_model sympy_params = { key: SymbolicMod(k(int(value)), p) for key, value in self.secp128r1.curve.parameters.items() } symbolic_point = Point( coords, **{key: SymbolicMod(symbols(key), p) for key in coords.variables}) symbolic_double = self.dbl(p, symbolic_point, **sympy_params)[0] generator_double = self.dbl(p, self.secp128r1.generator, **self.secp128r1.curve.parameters)[0] for outer_var in coords.variables: symbolic_val = getattr(symbolic_double, outer_var).x generator_val = getattr(generator_double, outer_var).x for inner_var in coords.variables: symbolic_val = symbolic_val.subs( inner_var, k(getattr(self.secp128r1.generator, inner_var).x)) self.assertEqual(Mod(int(symbolic_val), p), Mod(generator_val, p))
def test_sqrt(self): p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF self.assertIn( Mod( 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC, p).sqrt(), ( 0x9ADD512515B70D9EC471151C1DEC46625CD18B37BDE7CA7FB2C8B31D7033599D, 0x6522AED9EA48F2623B8EEAE3E213B99DA32E74C9421835804D374CE28FCCA662, ), ) with self.assertRaises(NonResidueError): Mod( 0x702BDAFD3C1C837B23A1CB196ED7F9FADB333C5CFE4A462BE32ADCD67BFB6AC1, p).sqrt() getconfig().ec.non_residue_action = "warning" with warnings.catch_warnings(record=True) as w: Mod( 0x702BDAFD3C1C837B23A1CB196ED7F9FADB333C5CFE4A462BE32ADCD67BFB6AC1, p).sqrt() self.assertTrue(issubclass(w[0].category, NonResidueWarning)) getconfig().ec.non_residue_action = "ignore" Mod(0x702BDAFD3C1C837B23A1CB196ED7F9FADB333C5CFE4A462BE32ADCD67BFB6AC1, p).sqrt() with TemporaryConfig() as cfg: cfg.ec.non_residue_action = "warning" with warnings.catch_warnings(record=True) as w: Mod( 0x702BDAFD3C1C837B23A1CB196ED7F9FADB333C5CFE4A462BE32ADCD67BFB6AC1, p, ).sqrt() self.assertTrue(issubclass(w[0].category, NonResidueWarning)) self.assertEqual(Mod(0, p).sqrt(), Mod(0, p)) q = 0x75D44FEE9A71841AE8403C0C251FBAD self.assertIn( Mod(0x591E0DB18CF1BD81A11B2985A821EB3, q).sqrt(), (0x113B41A1A2B73F636E73BE3F9A3716E, 0x64990E4CF7BA44B779CC7DCC8AE8A3F), ) getconfig().ec.non_residue_action = "error"
def test_is_on_curve(self): self.assertTrue(self.secp128r1.curve.is_on_curve(self.secp128r1.curve.neutral)) pt = Point( self.secp128r1.curve.coordinate_model, X=Mod(0x161FF7528B899B2D0C28607CA52C5B86, self.secp128r1.curve.prime), Y=Mod(0xCF5AC8395BAFEB13C02DA292DDED7A83, self.secp128r1.curve.prime), Z=Mod(1, self.secp128r1.curve.prime), ) self.assertTrue(self.secp128r1.curve.is_on_curve(pt)) self.assertTrue(self.secp128r1.curve.is_on_curve(pt.to_affine())) other = Point( self.secp128r1.curve.coordinate_model, X=Mod(0x161FF7528B899B2D0C28607CA52C5B86, self.secp128r1.curve.prime), Y=Mod(0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, self.secp128r1.curve.prime), Z=Mod(1, self.secp128r1.curve.prime), ) self.assertFalse(self.secp128r1.curve.is_on_curve(other)) self.assertFalse(self.secp128r1.curve.is_on_curve(self.curve25519.generator))
def test_is_on_curve(self): self.assertTrue( self.secp128r1.curve.is_on_curve(self.secp128r1.curve.neutral)) pt = Point(self.secp128r1.curve.coordinate_model, X=Mod(0x161ff7528b899b2d0c28607ca52c5b86, self.secp128r1.curve.prime), Y=Mod(0xcf5ac8395bafeb13c02da292dded7a83, self.secp128r1.curve.prime), Z=Mod(1, self.secp128r1.curve.prime)) self.assertTrue(self.secp128r1.curve.is_on_curve(pt)) self.assertTrue(self.secp128r1.curve.is_on_curve(pt.to_affine())) other = Point(self.secp128r1.curve.coordinate_model, X=Mod(0x161ff7528b899b2d0c28607ca52c5b86, self.secp128r1.curve.prime), Y=Mod(0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, self.secp128r1.curve.prime), Z=Mod(1, self.secp128r1.curve.prime)) self.assertFalse(self.secp128r1.curve.is_on_curve(other)) self.assertFalse( self.secp128r1.curve.is_on_curve(self.curve25519.generator))
def test_other(self): a = Mod(5, 7) b = Mod(3, 7) self.assertEqual(int(-a), 2) self.assertEqual(str(a), "5") self.assertEqual(6 - a, Mod(1, 7)) self.assertNotEqual(a, b) self.assertEqual(a / b, Mod(4, 7)) self.assertEqual(a // b, Mod(4, 7)) self.assertEqual(5 / b, Mod(4, 7)) self.assertEqual(5 // b, Mod(4, 7)) self.assertEqual(a / 3, Mod(4, 7)) self.assertEqual(a // 3, Mod(4, 7)) self.assertEqual(divmod(a, b), (Mod(1, 7), Mod(2, 7))) self.assertEqual(a + b, Mod(1, 7)) self.assertEqual(5 + b, Mod(1, 7)) self.assertEqual(a + 3, Mod(1, 7)) self.assertNotEqual(a, 6)
def test_wrong_pow(self): a = Mod(5, 7) c = Mod(4, 11) with self.assertRaises(TypeError): a**c
def test_wrong_mod(self): a = Mod(5, 7) b = Mod(4, 11) with self.assertRaises(ValueError): a + b
def test_pow(self): a = Mod(5, 7) self.assertEqual(a**(-1), a.inverse()) self.assertEqual(a**0, Mod(1, 7)) self.assertEqual(a**(-2), a.inverse()**2)
def test_eq(self): self.assertEqual(Mod(1, 7), 1) self.assertNotEqual(Mod(1, 7), "1") self.assertEqual(Mod(1, 7), Mod(1, 7)) self.assertNotEqual(Mod(1, 7), Mod(5, 7)) self.assertNotEqual(Mod(1, 7), Mod(1, 5))