aboutsummaryrefslogtreecommitdiff
path: root/frozen_deps/ecdsa/test_jacobi.py
diff options
context:
space:
mode:
authorDeterminant <[email protected]>2022-11-17 18:08:59 -0800
committerDeterminant <[email protected]>2022-11-17 18:08:59 -0800
commit8154806fe2fccacdc3dafaa68181a07bcf8d6c4c (patch)
treef477e6a005599bb88c18db142c267b9297c6060b /frozen_deps/ecdsa/test_jacobi.py
parentbe4dc086591c9bced04a507d127c83811c5700c4 (diff)
v0.1.7
Diffstat (limited to 'frozen_deps/ecdsa/test_jacobi.py')
-rw-r--r--frozen_deps/ecdsa/test_jacobi.py227
1 files changed, 223 insertions, 4 deletions
diff --git a/frozen_deps/ecdsa/test_jacobi.py b/frozen_deps/ecdsa/test_jacobi.py
index 43ed6c1..1f52804 100644
--- a/frozen_deps/ecdsa/test_jacobi.py
+++ b/frozen_deps/ecdsa/test_jacobi.py
@@ -5,18 +5,31 @@ try:
except ImportError:
import unittest
+import os
+import sys
+import signal
+import pytest
+import threading
+import platform
import hypothesis.strategies as st
from hypothesis import given, assume, settings, example
-from .ellipticcurve import CurveFp, Point, PointJacobi, INFINITY
+from .ellipticcurve import CurveFp, PointJacobi, INFINITY
from .ecdsa import (
generator_256,
curve_256,
generator_224,
generator_brainpoolp160r1,
curve_brainpoolp160r1,
+ generator_112r2,
)
from .numbertheory import inverse_mod
+from .util import randrange
+
+
+NO_OLD_SETTINGS = {}
+if sys.version_info > (2, 7): # pragma: no branch
+ NO_OLD_SETTINGS["deadline"] = 5000
class TestJacobi(unittest.TestCase):
@@ -210,7 +223,8 @@ class TestJacobi(unittest.TestCase):
@example(0)
@example(int(generator_brainpoolp160r1.order()))
def test_precompute(self, mul):
- precomp = PointJacobi.from_affine(generator_brainpoolp160r1, True)
+ precomp = generator_brainpoolp160r1
+ self.assertTrue(precomp._PointJacobi__precompute)
pj = PointJacobi.from_affine(generator_brainpoolp160r1)
a = precomp * mul
@@ -311,6 +325,29 @@ class TestJacobi(unittest.TestCase):
self.assertEqual(c, j_g * (a_mul + b_mul))
+ def test_add_same_scale_points_static(self):
+ j_g = generator_brainpoolp160r1
+ p = curve_brainpoolp160r1.p()
+ a = j_g * 11
+ a.scale()
+ z1 = 13
+ x = PointJacobi(
+ curve_brainpoolp160r1,
+ a.x() * z1**2 % p,
+ a.y() * z1**3 % p,
+ z1,
+ )
+ y = PointJacobi(
+ curve_brainpoolp160r1,
+ a.x() * z1**2 % p,
+ a.y() * z1**3 % p,
+ z1,
+ )
+
+ c = a + a
+
+ self.assertEqual(c, x + y)
+
@settings(max_examples=14)
@given(
st.integers(
@@ -362,11 +399,40 @@ class TestJacobi(unittest.TestCase):
self.assertEqual(c, j_g * (a_mul + b_mul))
+ def test_add_different_scale_points_static(self):
+ j_g = generator_brainpoolp160r1
+ p = curve_brainpoolp160r1.p()
+ a = j_g * 11
+ a.scale()
+ z1 = 13
+ x = PointJacobi(
+ curve_brainpoolp160r1,
+ a.x() * z1**2 % p,
+ a.y() * z1**3 % p,
+ z1,
+ )
+ z2 = 29
+ y = PointJacobi(
+ curve_brainpoolp160r1,
+ a.x() * z2**2 % p,
+ a.y() * z2**3 % p,
+ z2,
+ )
+
+ c = a + a
+
+ self.assertEqual(c, x + y)
+
def test_add_point_3_times(self):
j_g = PointJacobi.from_affine(generator_256)
self.assertEqual(j_g * 3, j_g + j_g + j_g)
+ def test_mul_without_order(self):
+ j_g = PointJacobi(curve_256, generator_256.x(), generator_256.y(), 1)
+
+ self.assertEqual(j_g * generator_256.order(), INFINITY)
+
def test_mul_add_inf(self):
j_g = PointJacobi.from_affine(generator_256)
@@ -378,7 +444,7 @@ class TestJacobi(unittest.TestCase):
self.assertEqual(j_g * 2, j_g.mul_add(1, j_g, 1))
def test_mul_add_precompute(self):
- j_g = PointJacobi.from_affine(generator_256, True)
+ j_g = PointJacobi.from_affine(generator_brainpoolp160r1, True)
b = PointJacobi.from_affine(j_g * 255, True)
self.assertEqual(j_g * 256, j_g + b)
@@ -386,7 +452,7 @@ class TestJacobi(unittest.TestCase):
self.assertEqual(j_g * (5 + 255 * 7), j_g.mul_add(5, b, 7))
def test_mul_add_precompute_large(self):
- j_g = PointJacobi.from_affine(generator_256, True)
+ j_g = PointJacobi.from_affine(generator_brainpoolp160r1, True)
b = PointJacobi.from_affine(j_g * 255, True)
self.assertEqual(j_g * 256, j_g + b)
@@ -405,6 +471,21 @@ class TestJacobi(unittest.TestCase):
self.assertEqual(a, b)
+ def test_mul_add_differnt(self):
+ j_g = PointJacobi.from_affine(generator_256)
+
+ w_a = j_g * 2
+
+ self.assertEqual(j_g.mul_add(1, w_a, 1), j_g * 3)
+
+ def test_mul_add_slightly_different(self):
+ j_g = PointJacobi.from_affine(generator_256)
+
+ w_a = j_g * 2
+ w_b = j_g * 3
+
+ self.assertEqual(w_a.mul_add(1, w_b, 3), w_a * 1 + w_b * 3)
+
def test_mul_add(self):
j_g = PointJacobi.from_affine(generator_256)
@@ -428,11 +509,149 @@ class TestJacobi(unittest.TestCase):
j_g * (0xFF00 + 255 * 0xF0F0), j_g.mul_add(0xFF00, b, 0xF0F0)
)
+ def test_mul_add_with_infinity_as_result(self):
+ j_g = PointJacobi.from_affine(generator_256)
+
+ order = generator_256.order()
+
+ b = PointJacobi.from_affine(generator_256 * 256)
+
+ self.assertEqual(j_g.mul_add(order % 256, b, order // 256), INFINITY)
+
+ def test_mul_add_without_order(self):
+ j_g = PointJacobi(curve_256, generator_256.x(), generator_256.y(), 1)
+
+ order = generator_256.order()
+
+ w_b = generator_256 * 34
+ w_b.scale()
+
+ b = PointJacobi(curve_256, w_b.x(), w_b.y(), 1)
+
+ self.assertEqual(j_g.mul_add(order % 34, b, order // 34), INFINITY)
+
+ def test_mul_add_with_doubled_negation_of_itself(self):
+ j_g = PointJacobi.from_affine(generator_256 * 17)
+
+ dbl_neg = 2 * (-j_g)
+
+ self.assertEqual(j_g.mul_add(4, dbl_neg, 2), INFINITY)
+
def test_equality(self):
pj1 = PointJacobi(curve=CurveFp(23, 1, 1, 1), x=2, y=3, z=1, order=1)
pj2 = PointJacobi(curve=CurveFp(23, 1, 1, 1), x=2, y=3, z=1, order=1)
self.assertEqual(pj1, pj2)
+ def test_equality_with_invalid_object(self):
+ j_g = PointJacobi.from_affine(generator_256)
+
+ self.assertNotEqual(j_g, 12)
+
+ def test_equality_with_wrong_curves(self):
+ p_a = PointJacobi.from_affine(generator_256)
+ p_b = PointJacobi.from_affine(generator_224)
+
+ self.assertNotEqual(p_a, p_b)
+
def test_pickle(self):
pj = PointJacobi(curve=CurveFp(23, 1, 1, 1), x=2, y=3, z=1, order=1)
self.assertEqual(pickle.loads(pickle.dumps(pj)), pj)
+
+ @settings(**NO_OLD_SETTINGS)
+ @given(st.integers(min_value=1, max_value=10))
+ def test_multithreading(self, thread_num):
+ # ensure that generator's precomputation table is filled
+ generator_112r2 * 2
+
+ # create a fresh point that doesn't have a filled precomputation table
+ gen = generator_112r2
+ gen = PointJacobi(gen.curve(), gen.x(), gen.y(), 1, gen.order(), True)
+
+ self.assertEqual(gen._PointJacobi__precompute, [])
+
+ def runner(generator):
+ order = generator.order()
+ for _ in range(10):
+ generator * randrange(order)
+
+ threads = []
+ for _ in range(thread_num):
+ threads.append(threading.Thread(target=runner, args=(gen,)))
+
+ for t in threads:
+ t.start()
+
+ runner(gen)
+
+ for t in threads:
+ t.join()
+
+ self.assertEqual(
+ gen._PointJacobi__precompute,
+ generator_112r2._PointJacobi__precompute,
+ )
+
+ @pytest.mark.skipif(
+ platform.system() == "Windows",
+ reason="there are no signals on Windows",
+ )
+ def test_multithreading_with_interrupts(self):
+ thread_num = 10
+ # ensure that generator's precomputation table is filled
+ generator_112r2 * 2
+
+ # create a fresh point that doesn't have a filled precomputation table
+ gen = generator_112r2
+ gen = PointJacobi(gen.curve(), gen.x(), gen.y(), 1, gen.order(), True)
+
+ self.assertEqual(gen._PointJacobi__precompute, [])
+
+ def runner(generator):
+ order = generator.order()
+ for _ in range(50):
+ generator * randrange(order)
+
+ def interrupter(barrier_start, barrier_end, lock_exit):
+ # wait until MainThread can handle KeyboardInterrupt
+ barrier_start.release()
+ barrier_end.acquire()
+ os.kill(os.getpid(), signal.SIGINT)
+ lock_exit.release()
+
+ threads = []
+ for _ in range(thread_num):
+ threads.append(threading.Thread(target=runner, args=(gen,)))
+
+ barrier_start = threading.Lock()
+ barrier_start.acquire()
+ barrier_end = threading.Lock()
+ barrier_end.acquire()
+ lock_exit = threading.Lock()
+ lock_exit.acquire()
+
+ threads.append(
+ threading.Thread(
+ target=interrupter,
+ args=(barrier_start, barrier_end, lock_exit),
+ )
+ )
+
+ for t in threads:
+ t.start()
+
+ with self.assertRaises(KeyboardInterrupt):
+ # signal to interrupter that we can now handle the signal
+ barrier_start.acquire()
+ barrier_end.release()
+ runner(gen)
+ # use the lock to ensure we never go past the scope of
+ # assertRaises before the os.kill is called
+ lock_exit.acquire()
+
+ for t in threads:
+ t.join()
+
+ self.assertEqual(
+ gen._PointJacobi__precompute,
+ generator_112r2._PointJacobi__precompute,
+ )