From 05da4603fb8155f89fc24dcebf880938a0394e85 Mon Sep 17 00:00:00 2001 From: Determinant Date: Sun, 16 Aug 2020 02:31:31 -0400 Subject: freeze the dependencies --- freezed_deps/ecdsa/test_der.py | 384 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 384 insertions(+) create mode 100644 freezed_deps/ecdsa/test_der.py (limited to 'freezed_deps/ecdsa/test_der.py') diff --git a/freezed_deps/ecdsa/test_der.py b/freezed_deps/ecdsa/test_der.py new file mode 100644 index 0000000..e6cd593 --- /dev/null +++ b/freezed_deps/ecdsa/test_der.py @@ -0,0 +1,384 @@ + +# compatibility with Python 2.6, for that we need unittest2 package, +# which is not available on 3.3 or 3.4 +import warnings +from binascii import hexlify +try: + import unittest2 as unittest +except ImportError: + import unittest +from six import b +import hypothesis.strategies as st +from hypothesis import given, example +import pytest +from ._compat import str_idx_as_int +from .curves import NIST256p, NIST224p +from .der import remove_integer, UnexpectedDER, read_length, encode_bitstring,\ + remove_bitstring, remove_object, encode_oid + + +class TestRemoveInteger(unittest.TestCase): + # DER requires the integers to be 0-padded only if they would be + # interpreted as negative, check if those errors are detected + def test_non_minimal_encoding(self): + with self.assertRaises(UnexpectedDER): + remove_integer(b('\x02\x02\x00\x01')) + + def test_negative_with_high_bit_set(self): + with self.assertRaises(UnexpectedDER): + remove_integer(b('\x02\x01\x80')) + + def test_minimal_with_high_bit_set(self): + val, rem = remove_integer(b('\x02\x02\x00\x80')) + + self.assertEqual(val, 0x80) + self.assertFalse(rem) + + def test_two_zero_bytes_with_high_bit_set(self): + with self.assertRaises(UnexpectedDER): + remove_integer(b('\x02\x03\x00\x00\xff')) + + def test_zero_length_integer(self): + with self.assertRaises(UnexpectedDER): + remove_integer(b('\x02\x00')) + + def test_empty_string(self): + with self.assertRaises(UnexpectedDER): + remove_integer(b('')) + + def test_encoding_of_zero(self): + val, rem = remove_integer(b('\x02\x01\x00')) + + self.assertEqual(val, 0) + self.assertFalse(rem) + + def test_encoding_of_127(self): + val, rem = remove_integer(b('\x02\x01\x7f')) + + self.assertEqual(val, 127) + self.assertFalse(rem) + + def test_encoding_of_128(self): + val, rem = remove_integer(b('\x02\x02\x00\x80')) + + self.assertEqual(val, 128) + self.assertFalse(rem) + + +class TestReadLength(unittest.TestCase): + # DER requires the lengths between 0 and 127 to be encoded using the short + # form and lengths above that encoded with minimal number of bytes + # necessary + def test_zero_length(self): + self.assertEqual((0, 1), read_length(b('\x00'))) + + def test_two_byte_zero_length(self): + with self.assertRaises(UnexpectedDER): + read_length(b('\x81\x00')) + + def test_two_byte_small_length(self): + with self.assertRaises(UnexpectedDER): + read_length(b('\x81\x7f')) + + def test_long_form_with_zero_length(self): + with self.assertRaises(UnexpectedDER): + read_length(b('\x80')) + + def test_smallest_two_byte_length(self): + self.assertEqual((128, 2), read_length(b('\x81\x80'))) + + def test_zero_padded_length(self): + with self.assertRaises(UnexpectedDER): + read_length(b('\x82\x00\x80')) + + def test_two_three_byte_length(self): + self.assertEqual((256, 3), read_length(b'\x82\x01\x00')) + + def test_empty_string(self): + with self.assertRaises(UnexpectedDER): + read_length(b('')) + + def test_length_overflow(self): + with self.assertRaises(UnexpectedDER): + read_length(b('\x83\x01\x00')) + + +class TestEncodeBitstring(unittest.TestCase): + # DER requires BIT STRINGS to include a number of padding bits in the + # encoded byte string, that padding must be between 0 and 7 + + def test_old_call_convention(self): + """This is the old way to use the function.""" + warnings.simplefilter('always') + with pytest.warns(DeprecationWarning) as warns: + der = encode_bitstring(b'\x00\xff') + + self.assertEqual(len(warns), 1) + self.assertIn("unused= needs to be specified", + warns[0].message.args[0]) + + self.assertEqual(der, b'\x03\x02\x00\xff') + + def test_new_call_convention(self): + """This is how it should be called now.""" + warnings.simplefilter('always') + with pytest.warns(None) as warns: + der = encode_bitstring(b'\xff', 0) + + # verify that new call convention doesn't raise Warnings + self.assertEqual(len(warns), 0) + + self.assertEqual(der, b'\x03\x02\x00\xff') + + def test_implicit_unused_bits(self): + """ + Writing bit string with already included the number of unused bits. + """ + warnings.simplefilter('always') + with pytest.warns(None) as warns: + der = encode_bitstring(b'\x00\xff', None) + + # verify that new call convention doesn't raise Warnings + self.assertEqual(len(warns), 0) + + self.assertEqual(der, b'\x03\x02\x00\xff') + + def test_explicit_unused_bits(self): + der = encode_bitstring(b'\xff\xf0', 4) + + self.assertEqual(der, b'\x03\x03\x04\xff\xf0') + + def test_empty_string(self): + self.assertEqual(encode_bitstring(b'', 0), b'\x03\x01\x00') + + def test_invalid_unused_count(self): + with self.assertRaises(ValueError): + encode_bitstring(b'\xff\x00', 8) + + def test_invalid_unused_with_empty_string(self): + with self.assertRaises(ValueError): + encode_bitstring(b'', 1) + + def test_non_zero_padding_bits(self): + with self.assertRaises(ValueError): + encode_bitstring(b'\xff', 2) + + +class TestRemoveBitstring(unittest.TestCase): + def test_old_call_convention(self): + """This is the old way to call the function.""" + warnings.simplefilter('always') + with pytest.warns(DeprecationWarning) as warns: + bits, rest = remove_bitstring(b'\x03\x02\x00\xff') + + self.assertEqual(len(warns), 1) + self.assertIn("expect_unused= needs to be specified", + warns[0].message.args[0]) + + self.assertEqual(bits, b'\x00\xff') + self.assertEqual(rest, b'') + + def test_new_call_convention(self): + warnings.simplefilter('always') + with pytest.warns(None) as warns: + bits, rest = remove_bitstring(b'\x03\x02\x00\xff', 0) + + self.assertEqual(len(warns), 0) + + self.assertEqual(bits, b'\xff') + self.assertEqual(rest, b'') + + def test_implicit_unexpected_unused(self): + warnings.simplefilter('always') + with pytest.warns(None) as warns: + bits, rest = remove_bitstring(b'\x03\x02\x00\xff', None) + + self.assertEqual(len(warns), 0) + + self.assertEqual(bits, (b'\xff', 0)) + self.assertEqual(rest, b'') + + def test_with_padding(self): + ret, rest = remove_bitstring(b'\x03\x02\x04\xf0', None) + + self.assertEqual(ret, (b'\xf0', 4)) + self.assertEqual(rest, b'') + + def test_not_a_bitstring(self): + with self.assertRaises(UnexpectedDER): + remove_bitstring(b'\x02\x02\x00\xff', None) + + def test_empty_encoding(self): + with self.assertRaises(UnexpectedDER): + remove_bitstring(b'\x03\x00', None) + + def test_empty_string(self): + with self.assertRaises(UnexpectedDER): + remove_bitstring(b'', None) + + def test_no_length(self): + with self.assertRaises(UnexpectedDER): + remove_bitstring(b'\x03', None) + + def test_unexpected_number_of_unused_bits(self): + with self.assertRaises(UnexpectedDER): + remove_bitstring(b'\x03\x02\x00\xff', 1) + + def test_invalid_encoding_of_unused_bits(self): + with self.assertRaises(UnexpectedDER): + remove_bitstring(b'\x03\x03\x08\xff\x00', None) + + def test_invalid_encoding_of_empty_string(self): + with self.assertRaises(UnexpectedDER): + remove_bitstring(b'\x03\x01\x01', None) + + def test_invalid_padding_bits(self): + with self.assertRaises(UnexpectedDER): + remove_bitstring(b'\x03\x02\x01\xff', None) + + +class TestStrIdxAsInt(unittest.TestCase): + def test_str(self): + self.assertEqual(115, str_idx_as_int('str', 0)) + + def test_bytes(self): + self.assertEqual(115, str_idx_as_int(b'str', 0)) + + def test_bytearray(self): + self.assertEqual(115, str_idx_as_int(bytearray(b'str'), 0)) + + +class TestEncodeOid(unittest.TestCase): + def test_pub_key_oid(self): + oid_ecPublicKey = encode_oid(1, 2, 840, 10045, 2, 1) + self.assertEqual(hexlify(oid_ecPublicKey), b("06072a8648ce3d0201")) + + def test_nist224p_oid(self): + self.assertEqual(hexlify(NIST224p.encoded_oid), b("06052b81040021")) + + def test_nist256p_oid(self): + self.assertEqual(hexlify(NIST256p.encoded_oid), + b"06082a8648ce3d030107") + + def test_large_second_subid(self): + # from X.690, section 8.19.5 + oid = encode_oid(2, 999, 3) + self.assertEqual(oid, b'\x06\x03\x88\x37\x03') + + def test_with_two_subids(self): + oid = encode_oid(2, 999) + self.assertEqual(oid, b'\x06\x02\x88\x37') + + def test_zero_zero(self): + oid = encode_oid(0, 0) + self.assertEqual(oid, b'\x06\x01\x00') + + def test_with_wrong_types(self): + with self.assertRaises((TypeError, AssertionError)): + encode_oid(0, None) + + def test_with_small_first_large_second(self): + with self.assertRaises(AssertionError): + encode_oid(1, 40) + + def test_small_first_max_second(self): + oid = encode_oid(1, 39) + self.assertEqual(oid, b'\x06\x01\x4f') + + def test_with_invalid_first(self): + with self.assertRaises(AssertionError): + encode_oid(3, 39) + + +class TestRemoveObject(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.oid_ecPublicKey = encode_oid(1, 2, 840, 10045, 2, 1) + + def test_pub_key_oid(self): + oid, rest = remove_object(self.oid_ecPublicKey) + self.assertEqual(rest, b'') + self.assertEqual(oid, (1, 2, 840, 10045, 2, 1)) + + def test_with_extra_bytes(self): + oid, rest = remove_object(self.oid_ecPublicKey + b'more') + self.assertEqual(rest, b'more') + self.assertEqual(oid, (1, 2, 840, 10045, 2, 1)) + + def test_with_large_second_subid(self): + # from X.690, section 8.19.5 + oid, rest = remove_object(b'\x06\x03\x88\x37\x03') + self.assertEqual(rest, b'') + self.assertEqual(oid, (2, 999, 3)) + + def test_with_padded_first_subid(self): + with self.assertRaises(UnexpectedDER): + remove_object(b'\x06\x02\x80\x00') + + def test_with_padded_second_subid(self): + with self.assertRaises(UnexpectedDER): + remove_object(b'\x06\x04\x88\x37\x80\x01') + + def test_with_missing_last_byte_of_multi_byte(self): + with self.assertRaises(UnexpectedDER): + remove_object(b'\x06\x03\x88\x37\x83') + + def test_with_two_subids(self): + oid, rest = remove_object(b'\x06\x02\x88\x37') + self.assertEqual(rest, b'') + self.assertEqual(oid, (2, 999)) + + def test_zero_zero(self): + oid, rest = remove_object(b'\x06\x01\x00') + self.assertEqual(rest, b'') + self.assertEqual(oid, (0, 0)) + + def test_empty_string(self): + with self.assertRaises(UnexpectedDER): + remove_object(b'') + + def test_missing_length(self): + with self.assertRaises(UnexpectedDER): + remove_object(b'\x06') + + def test_empty_oid(self): + with self.assertRaises(UnexpectedDER): + remove_object(b'\x06\x00') + + def test_empty_oid_overflow(self): + with self.assertRaises(UnexpectedDER): + remove_object(b'\x06\x01') + + def test_with_wrong_type(self): + with self.assertRaises(UnexpectedDER): + remove_object(b'\x04\x02\x88\x37') + + def test_with_too_long_length(self): + with self.assertRaises(UnexpectedDER): + remove_object(b'\x06\x03\x88\x37') + + +@st.composite +def st_oid(draw, max_value=2**512, max_size=50): + """ + Hypothesis strategy that returns valid OBJECT IDENTIFIERs as tuples + + :param max_value: maximum value of any single sub-identifier + :param max_size: maximum length of the generated OID + """ + first = draw(st.integers(min_value=0, max_value=2)) + if first < 2: + second = draw(st.integers(min_value=0, max_value=39)) + else: + second = draw(st.integers(min_value=0, max_value=max_value)) + rest = draw(st.lists(st.integers(min_value=0, max_value=max_value), + max_size=max_size)) + return (first, second) + tuple(rest) + + +@given(st_oid()) +def test_oids(ids): + encoded_oid = encode_oid(*ids) + decoded_oid, rest = remove_object(encoded_oid) + assert rest == b'' + assert decoded_oid == ids -- cgit v1.2.3