aboutsummaryrefslogtreecommitdiff
path: root/frozen_deps/ecdsa/test_curves.py
diff options
context:
space:
mode:
Diffstat (limited to 'frozen_deps/ecdsa/test_curves.py')
-rw-r--r--frozen_deps/ecdsa/test_curves.py361
1 files changed, 361 insertions, 0 deletions
diff --git a/frozen_deps/ecdsa/test_curves.py b/frozen_deps/ecdsa/test_curves.py
new file mode 100644
index 0000000..93b6c9b
--- /dev/null
+++ b/frozen_deps/ecdsa/test_curves.py
@@ -0,0 +1,361 @@
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+import base64
+import pytest
+from .curves import (
+ Curve,
+ NIST256p,
+ curves,
+ UnknownCurveError,
+ PRIME_FIELD_OID,
+ curve_by_name,
+)
+from .ellipticcurve import CurveFp, PointJacobi, CurveEdTw
+from . import der
+from .util import number_to_string
+
+
+class TestParameterEncoding(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ # minimal, but with cofactor (excludes seed when compared to
+ # OpenSSL output)
+ cls.base64_params = (
+ "MIHgAgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP/////////"
+ "//////zBEBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12K"
+ "o6k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsEQQRrF9Hy4SxCR/i85uVjpEDyd"
+ "wN9gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1"
+ "AiEA/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQE="
+ )
+
+ def test_from_pem(self):
+ pem_params = (
+ "-----BEGIN EC PARAMETERS-----\n"
+ "MIHgAgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP/////////\n"
+ "//////zBEBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12K\n"
+ "o6k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsEQQRrF9Hy4SxCR/i85uVjpEDyd\n"
+ "wN9gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1\n"
+ "AiEA/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQE=\n"
+ "-----END EC PARAMETERS-----\n"
+ )
+ curve = Curve.from_pem(pem_params)
+
+ self.assertIs(curve, NIST256p)
+
+ def test_from_pem_with_explicit_when_explicit_disabled(self):
+ pem_params = (
+ "-----BEGIN EC PARAMETERS-----\n"
+ "MIHgAgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP/////////\n"
+ "//////zBEBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12K\n"
+ "o6k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsEQQRrF9Hy4SxCR/i85uVjpEDyd\n"
+ "wN9gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1\n"
+ "AiEA/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQE=\n"
+ "-----END EC PARAMETERS-----\n"
+ )
+ with self.assertRaises(der.UnexpectedDER) as e:
+ Curve.from_pem(pem_params, ["named_curve"])
+
+ self.assertIn("explicit curve parameters not", str(e.exception))
+
+ def test_from_pem_with_named_curve_with_named_curve_disabled(self):
+ pem_params = (
+ "-----BEGIN EC PARAMETERS-----\n"
+ "BggqhkjOPQMBBw==\n"
+ "-----END EC PARAMETERS-----\n"
+ )
+ with self.assertRaises(der.UnexpectedDER) as e:
+ Curve.from_pem(pem_params, ["explicit"])
+
+ self.assertIn("named_curve curve parameters not", str(e.exception))
+
+ def test_from_pem_with_wrong_header(self):
+ pem_params = (
+ "-----BEGIN PARAMETERS-----\n"
+ "MIHgAgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP/////////\n"
+ "//////zBEBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12K\n"
+ "o6k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsEQQRrF9Hy4SxCR/i85uVjpEDyd\n"
+ "wN9gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1\n"
+ "AiEA/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQE=\n"
+ "-----END PARAMETERS-----\n"
+ )
+ with self.assertRaises(der.UnexpectedDER) as e:
+ Curve.from_pem(pem_params)
+
+ self.assertIn("PARAMETERS PEM header", str(e.exception))
+
+ def test_to_pem(self):
+ pem_params = (
+ b"-----BEGIN EC PARAMETERS-----\n"
+ b"BggqhkjOPQMBBw==\n"
+ b"-----END EC PARAMETERS-----\n"
+ )
+ encoding = NIST256p.to_pem()
+
+ self.assertEqual(pem_params, encoding)
+
+ def test_compare_with_different_object(self):
+ self.assertNotEqual(NIST256p, 256)
+
+ def test_named_curve_params_der(self):
+ encoded = NIST256p.to_der()
+
+ # just the encoding of the NIST256p OID (prime256v1)
+ self.assertEqual(b"\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07", encoded)
+
+ def test_verify_that_default_is_named_curve_der(self):
+ encoded_default = NIST256p.to_der()
+ encoded_named = NIST256p.to_der("named_curve")
+
+ self.assertEqual(encoded_default, encoded_named)
+
+ def test_encoding_to_explicit_params(self):
+ encoded = NIST256p.to_der("explicit")
+
+ self.assertEqual(encoded, bytes(base64.b64decode(self.base64_params)))
+
+ def test_encoding_to_unsupported_type(self):
+ with self.assertRaises(ValueError) as e:
+ NIST256p.to_der("unsupported")
+
+ self.assertIn("Only 'named_curve'", str(e.exception))
+
+ def test_encoding_to_explicit_compressed_params(self):
+ encoded = NIST256p.to_der("explicit", "compressed")
+
+ compressed_base_point = (
+ "MIHAAgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP//////////"
+ "/////zBEBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12Ko6"
+ "k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsEIQNrF9Hy4SxCR/i85uVjpEDydwN9"
+ "gS3rM6D0oTlF2JjClgIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8YyVR"
+ "AgEB"
+ )
+
+ self.assertEqual(
+ encoded, bytes(base64.b64decode(compressed_base_point))
+ )
+
+ def test_decoding_explicit_from_openssl(self):
+ # generated with openssl 1.1.1k using
+ # openssl ecparam -name P-256 -param_enc explicit -out /tmp/file.pem
+ p256_explicit = (
+ "MIH3AgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP//////////"
+ "/////zBbBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12Ko6"
+ "k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsDFQDEnTYIhucEk2pmeOETnSa3gZ9+"
+ "kARBBGsX0fLhLEJH+Lzm5WOkQPJ3A32BLeszoPShOUXYmMKWT+NC4v4af5uO5+tK"
+ "fA+eFivOM1drMV7Oy7ZAaDe/UfUCIQD/////AAAAAP//////////vOb6racXnoTz"
+ "ucrC/GMlUQIBAQ=="
+ )
+
+ decoded = Curve.from_der(bytes(base64.b64decode(p256_explicit)))
+
+ self.assertEqual(NIST256p, decoded)
+
+ def test_decoding_well_known_from_explicit_params(self):
+ curve = Curve.from_der(bytes(base64.b64decode(self.base64_params)))
+
+ self.assertIs(curve, NIST256p)
+
+ def test_decoding_with_incorrect_valid_encodings(self):
+ with self.assertRaises(ValueError) as e:
+ Curve.from_der(b"", ["explicitCA"])
+
+ self.assertIn("Only named_curve", str(e.exception))
+
+ def test_compare_curves_with_different_generators(self):
+ curve_fp = CurveFp(23, 1, 7)
+ base_a = PointJacobi(curve_fp, 13, 3, 1, 9, generator=True)
+ base_b = PointJacobi(curve_fp, 1, 20, 1, 9, generator=True)
+
+ curve_a = Curve("unknown", curve_fp, base_a, None)
+ curve_b = Curve("unknown", curve_fp, base_b, None)
+
+ self.assertNotEqual(curve_a, curve_b)
+
+ def test_default_encode_for_custom_curve(self):
+ curve_fp = CurveFp(23, 1, 7)
+ base_point = PointJacobi(curve_fp, 13, 3, 1, 9, generator=True)
+
+ curve = Curve("unknown", curve_fp, base_point, None)
+
+ encoded = curve.to_der()
+
+ decoded = Curve.from_der(encoded)
+
+ self.assertEqual(curve, decoded)
+
+ expected = "MCECAQEwDAYHKoZIzj0BAQIBFzAGBAEBBAEHBAMEDQMCAQk="
+
+ self.assertEqual(encoded, bytes(base64.b64decode(expected)))
+
+ def test_named_curve_encode_for_custom_curve(self):
+ curve_fp = CurveFp(23, 1, 7)
+ base_point = PointJacobi(curve_fp, 13, 3, 1, 9, generator=True)
+
+ curve = Curve("unknown", curve_fp, base_point, None)
+
+ with self.assertRaises(UnknownCurveError) as e:
+ curve.to_der("named_curve")
+
+ self.assertIn("Can't encode curve", str(e.exception))
+
+ def test_try_decoding_binary_explicit(self):
+ sect113r1_explicit = (
+ "MIGRAgEBMBwGByqGSM49AQIwEQIBcQYJKoZIzj0BAgMCAgEJMDkEDwAwiCUMpufH"
+ "/mSc6Fgg9wQPAOi+5NPiJgdEGIvg6ccjAxUAEOcjqxTWluZ2h1YVF1b+v4/LSakE"
+ "HwQAnXNhbzX0qxQH1zViwQ8ApSgwJ3lY7oTRMV7TGIYCDwEAAAAAAAAA2czsijnl"
+ "bwIBAg=="
+ )
+
+ with self.assertRaises(UnknownCurveError) as e:
+ Curve.from_der(base64.b64decode(sect113r1_explicit))
+
+ self.assertIn("Characteristic 2 curves unsupported", str(e.exception))
+
+ def test_decode_malformed_named_curve(self):
+ bad_der = der.encode_oid(*NIST256p.oid) + der.encode_integer(1)
+
+ with self.assertRaises(der.UnexpectedDER) as e:
+ Curve.from_der(bad_der)
+
+ self.assertIn("Unexpected data after OID", str(e.exception))
+
+ def test_decode_malformed_explicit_garbage_after_ECParam(self):
+ bad_der = bytes(
+ base64.b64decode(self.base64_params)
+ ) + der.encode_integer(1)
+
+ with self.assertRaises(der.UnexpectedDER) as e:
+ Curve.from_der(bad_der)
+
+ self.assertIn("Unexpected data after ECParameters", str(e.exception))
+
+ def test_decode_malformed_unknown_version_number(self):
+ bad_der = der.encode_sequence(der.encode_integer(2))
+
+ with self.assertRaises(der.UnexpectedDER) as e:
+ Curve.from_der(bad_der)
+
+ self.assertIn("Unknown parameter encoding format", str(e.exception))
+
+ def test_decode_malformed_unknown_field_type(self):
+ curve_p = NIST256p.curve.p()
+ bad_der = der.encode_sequence(
+ der.encode_integer(1),
+ der.encode_sequence(
+ der.encode_oid(1, 2, 3), der.encode_integer(curve_p)
+ ),
+ der.encode_sequence(
+ der.encode_octet_string(
+ number_to_string(NIST256p.curve.a() % curve_p, curve_p)
+ ),
+ der.encode_octet_string(
+ number_to_string(NIST256p.curve.b(), curve_p)
+ ),
+ ),
+ der.encode_octet_string(
+ NIST256p.generator.to_bytes("uncompressed")
+ ),
+ der.encode_integer(NIST256p.generator.order()),
+ )
+
+ with self.assertRaises(UnknownCurveError) as e:
+ Curve.from_der(bad_der)
+
+ self.assertIn("Unknown field type: (1, 2, 3)", str(e.exception))
+
+ def test_decode_malformed_garbage_after_prime(self):
+ curve_p = NIST256p.curve.p()
+ bad_der = der.encode_sequence(
+ der.encode_integer(1),
+ der.encode_sequence(
+ der.encode_oid(*PRIME_FIELD_OID),
+ der.encode_integer(curve_p),
+ der.encode_integer(1),
+ ),
+ der.encode_sequence(
+ der.encode_octet_string(
+ number_to_string(NIST256p.curve.a() % curve_p, curve_p)
+ ),
+ der.encode_octet_string(
+ number_to_string(NIST256p.curve.b(), curve_p)
+ ),
+ ),
+ der.encode_octet_string(
+ NIST256p.generator.to_bytes("uncompressed")
+ ),
+ der.encode_integer(NIST256p.generator.order()),
+ )
+
+ with self.assertRaises(der.UnexpectedDER) as e:
+ Curve.from_der(bad_der)
+
+ self.assertIn("Prime-p element", str(e.exception))
+
+
+class TestCurveSearching(unittest.TestCase):
+ def test_correct_name(self):
+ c = curve_by_name("NIST256p")
+ self.assertIs(c, NIST256p)
+
+ def test_openssl_name(self):
+ c = curve_by_name("prime256v1")
+ self.assertIs(c, NIST256p)
+
+ def test_unknown_curve(self):
+ with self.assertRaises(UnknownCurveError) as e:
+ curve_by_name("foo bar")
+
+ self.assertIn(
+ "name 'foo bar' unknown, only curves supported: "
+ "['NIST192p', 'NIST224p'",
+ str(e.exception),
+ )
+
+ def test_with_None_as_parameter(self):
+ with self.assertRaises(UnknownCurveError) as e:
+ curve_by_name(None)
+
+ self.assertIn(
+ "name None unknown, only curves supported: "
+ "['NIST192p', 'NIST224p'",
+ str(e.exception),
+ )
+
+
[email protected]("curve", curves, ids=[i.name for i in curves])
+def test_curve_params_encode_decode_named(curve):
+ ret = Curve.from_der(curve.to_der("named_curve"))
+
+ assert curve == ret
+
+
[email protected]("curve", curves, ids=[i.name for i in curves])
+def test_curve_params_encode_decode_explicit(curve):
+ if isinstance(curve.curve, CurveEdTw):
+ with pytest.raises(UnknownCurveError):
+ curve.to_der("explicit")
+ else:
+ ret = Curve.from_der(curve.to_der("explicit"))
+
+ assert curve == ret
+
+
[email protected]("curve", curves, ids=[i.name for i in curves])
+def test_curve_params_encode_decode_default(curve):
+ ret = Curve.from_der(curve.to_der())
+
+ assert curve == ret
+
+
[email protected]("curve", curves, ids=[i.name for i in curves])
+def test_curve_params_encode_decode_explicit_compressed(curve):
+ if isinstance(curve.curve, CurveEdTw):
+ with pytest.raises(UnknownCurveError):
+ curve.to_der("explicit", "compressed")
+ else:
+ ret = Curve.from_der(curve.to_der("explicit", "compressed"))
+
+ assert curve == ret