diff options
| author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2019-01-12 21:18:21 -0800 | 
|---|---|---|
| committer | Alex Gaynor <alex.gaynor@gmail.com> | 2019-01-13 00:18:21 -0500 | 
| commit | dbcbffa06c9930a687010ca816596ca3f5cc78e9 (patch) | |
| tree | 27f88222ed222e45784f4c1e6ea0b8d6b9f9d07b /tests/hazmat/primitives | |
| parent | 9b198104db8b53178212b5849919b6a61ca794ab (diff) | |
| download | cryptography-dbcbffa06c9930a687010ca816596ca3f5cc78e9.tar.gz cryptography-dbcbffa06c9930a687010ca816596ca3f5cc78e9.tar.bz2 cryptography-dbcbffa06c9930a687010ca816596ca3f5cc78e9.zip | |
support x448 public/private serialization both raw and pkcs8 (#4653)
* support x448 public/private serialization both raw and pkcs8
* add tests for all other asym key types to prevent Raw
* more tests
* better tests
* fix a test
* funny story, I'm actually illiterate.
* pep8
* require PrivateFormat.Raw or PublicFormat.Raw with Encoding.Raw
* missing docs
* parametrize
* docs fixes
* remove dupe line
* assert something
Diffstat (limited to 'tests/hazmat/primitives')
| -rw-r--r-- | tests/hazmat/primitives/test_dh.py | 31 | ||||
| -rw-r--r-- | tests/hazmat/primitives/test_dsa.py | 29 | ||||
| -rw-r--r-- | tests/hazmat/primitives/test_ec.py | 28 | ||||
| -rw-r--r-- | tests/hazmat/primitives/test_rsa.py | 26 | ||||
| -rw-r--r-- | tests/hazmat/primitives/test_serialization.py | 68 | ||||
| -rw-r--r-- | tests/hazmat/primitives/test_x448.py | 107 | 
6 files changed, 281 insertions, 8 deletions
| diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index a70ae745..c63e520f 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -425,6 +425,20 @@ class TestDHPrivateKeySerialization(object):          assert loaded_priv_num == priv_num      @pytest.mark.parametrize( +        ("encoding", "fmt"), +        [ +            (serialization.Encoding.Raw, serialization.PrivateFormat.PKCS8), +            (serialization.Encoding.DER, serialization.PrivateFormat.Raw), +            (serialization.Encoding.Raw, serialization.PrivateFormat.Raw), +        ] +    ) +    def test_private_bytes_rejects_raw(self, encoding, fmt, backend): +        parameters = dh.generate_parameters(2, 512, backend) +        key = parameters.generate_private_key() +        with pytest.raises(ValueError): +            key.private_bytes(encoding, fmt, serialization.NoEncryption()) + +    @pytest.mark.parametrize(          ("key_path", "loader_func", "encoding", "is_dhx"),          [              ( @@ -806,6 +820,23 @@ class TestDHParameterSerialization(object):          else:              assert parameter_numbers.q is None +    @pytest.mark.parametrize( +        ("encoding", "fmt"), +        [ +            (serialization.Encoding.Raw, serialization.PublicFormat.Raw), +            (serialization.Encoding.PEM, serialization.PublicFormat.Raw), +            ( +                serialization.Encoding.Raw, +                serialization.PublicFormat.SubjectPublicKeyInfo +            ), +        ] +    ) +    def test_public_bytes_rejects_raw(self, encoding, fmt, backend): +        parameters = dh.generate_parameters(2, 512, backend) +        key = parameters.generate_private_key().public_key() +        with pytest.raises(ValueError): +            key.public_bytes(encoding, fmt) +      def test_parameter_bytes_invalid_encoding(self, backend):          parameters = dh.generate_parameters(2, 512, backend)          with pytest.raises(TypeError): diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py index fb415732..5d2f1bd8 100644 --- a/tests/hazmat/primitives/test_dsa.py +++ b/tests/hazmat/primitives/test_dsa.py @@ -714,6 +714,19 @@ class TestDSASerialization(object):          assert loaded_priv_num == priv_num      @pytest.mark.parametrize( +        ("encoding", "fmt"), +        [ +            (serialization.Encoding.Raw, serialization.PrivateFormat.PKCS8), +            (serialization.Encoding.DER, serialization.PrivateFormat.Raw), +            (serialization.Encoding.Raw, serialization.PrivateFormat.Raw), +        ] +    ) +    def test_private_bytes_rejects_raw(self, encoding, fmt, backend): +        key = DSA_KEY_1024.private_key(backend) +        with pytest.raises(ValueError): +            key.private_bytes(encoding, fmt, serialization.NoEncryption()) + +    @pytest.mark.parametrize(          ("fmt", "password"),          [              [serialization.PrivateFormat.PKCS8, b"s"], @@ -951,3 +964,19 @@ class TestDSAPEMPublicKeySerialization(object):              key.public_bytes(                  serialization.Encoding.PEM, serialization.PublicFormat.PKCS1              ) + +    @pytest.mark.parametrize( +        ("encoding", "fmt"), +        [ +            (serialization.Encoding.Raw, serialization.PublicFormat.Raw), +            (serialization.Encoding.PEM, serialization.PublicFormat.Raw), +            ( +                serialization.Encoding.Raw, +                serialization.PublicFormat.SubjectPublicKeyInfo +            ), +        ] +    ) +    def test_public_bytes_rejects_raw(self, encoding, fmt, backend): +        key = DSA_KEY_2048.private_key(backend).public_key() +        with pytest.raises(ValueError): +            key.public_bytes(encoding, fmt) diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index f883d065..830d89a0 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -706,6 +706,20 @@ class TestECSerialization(object):          assert loaded_priv_num == priv_num      @pytest.mark.parametrize( +        ("encoding", "fmt"), +        [ +            (serialization.Encoding.Raw, serialization.PrivateFormat.PKCS8), +            (serialization.Encoding.DER, serialization.PrivateFormat.Raw), +            (serialization.Encoding.Raw, serialization.PrivateFormat.Raw), +        ] +    ) +    def test_private_bytes_rejects_raw(self, encoding, fmt, backend): +        _skip_curve_unsupported(backend, ec.SECP256R1()) +        key = ec.generate_private_key(ec.SECP256R1(), backend) +        with pytest.raises(ValueError): +            key.private_bytes(encoding, fmt, serialization.NoEncryption()) + +    @pytest.mark.parametrize(          ("fmt", "password"),          [              [serialization.PrivateFormat.PKCS8, b"s"], @@ -985,6 +999,20 @@ class TestEllipticCurvePEMPublicKeySerialization(object):                  serialization.PublicFormat.SubjectPublicKeyInfo              ) +    @pytest.mark.parametrize( +        ("encoding", "fmt"), +        [ +            (serialization.Encoding.Raw, serialization.PublicFormat.Raw), +            (serialization.Encoding.PEM, serialization.PublicFormat.Raw), +            (serialization.Encoding.Raw, serialization.PublicFormat.PKCS1), +        ] +    ) +    def test_public_bytes_rejects_raw(self, encoding, fmt, backend): +        _skip_curve_unsupported(backend, ec.SECP256R1()) +        key = ec.generate_private_key(ec.SECP256R1(), backend).public_key() +        with pytest.raises(ValueError): +            key.public_bytes(encoding, fmt) +      def test_public_bytes_invalid_format(self, backend):          _skip_curve_unsupported(backend, ec.SECP256R1())          key = load_vectors_from_file( diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 268ee9d9..0c25bdbb 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -2062,6 +2062,19 @@ class TestRSAPrivateKeySerialization(object):          assert loaded_priv_num == priv_num      @pytest.mark.parametrize( +        ("encoding", "fmt"), +        [ +            (serialization.Encoding.Raw, serialization.PrivateFormat.PKCS8), +            (serialization.Encoding.DER, serialization.PrivateFormat.Raw), +            (serialization.Encoding.Raw, serialization.PrivateFormat.Raw), +        ] +    ) +    def test_private_bytes_rejects_raw(self, encoding, fmt, backend): +        key = RSA_KEY_2048.private_key(backend) +        with pytest.raises(ValueError): +            key.private_bytes(encoding, fmt, serialization.NoEncryption()) + +    @pytest.mark.parametrize(          ("fmt", "password"),          [              [serialization.PrivateFormat.PKCS8, b"s"], @@ -2286,3 +2299,16 @@ class TestRSAPEMPublicKeySerialization(object):          key = RSA_KEY_2048.private_key(backend).public_key()          with pytest.raises(TypeError):              key.public_bytes(serialization.Encoding.PEM, "invalidformat") + +    @pytest.mark.parametrize( +        ("encoding", "fmt"), +        [ +            (serialization.Encoding.Raw, serialization.PublicFormat.Raw), +            (serialization.Encoding.PEM, serialization.PublicFormat.Raw), +            (serialization.Encoding.Raw, serialization.PublicFormat.PKCS1), +        ] +    ) +    def test_public_bytes_rejects_raw(self, encoding, fmt, backend): +        key = RSA_KEY_2048.private_key(backend).public_key() +        with pytest.raises(ValueError): +            key.public_bytes(encoding, fmt) diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index a7355221..81d372fc 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -18,7 +18,9 @@ from cryptography.hazmat.backends.interfaces import (  )  from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa  from cryptography.hazmat.primitives.serialization import ( -    BestAvailableEncryption, load_der_parameters, load_der_private_key, +    BestAvailableEncryption, Encoding, NoEncryption, +    PrivateFormat, PublicFormat, +    load_der_parameters, load_der_private_key,      load_der_public_key, load_pem_parameters, load_pem_private_key,      load_pem_public_key, load_ssh_public_key  ) @@ -1231,3 +1233,67 @@ class TestKeySerializationEncryptionTypes(object):      def test_encryption_with_zero_length_password(self):          with pytest.raises(ValueError):              BestAvailableEncryption(b"") + + +@pytest.mark.supported( +    only_if=lambda backend: backend.x448_supported(), +    skip_message="Requires OpenSSL with X448 support" +) +class TestX448Serialization(object): +    def test_load_der_private_key(self, backend): +        data = load_vectors_from_file( +            os.path.join("asymmetric", "X448", "x448-pkcs8-enc.der"), +            lambda derfile: derfile.read(), +            mode="rb" +        ) +        unencrypted = load_vectors_from_file( +            os.path.join("asymmetric", "X448", "x448-pkcs8.der"), +            lambda derfile: derfile.read(), +            mode="rb" +        ) +        key = load_der_private_key(data, b"password", backend) +        assert key.private_bytes( +            Encoding.DER, PrivateFormat.PKCS8, NoEncryption() +        ) == unencrypted + +    def test_load_pem_private_key(self, backend): +        data = load_vectors_from_file( +            os.path.join("asymmetric", "X448", "x448-pkcs8-enc.pem"), +            lambda pemfile: pemfile.read(), +            mode="rb" +        ) +        unencrypted = load_vectors_from_file( +            os.path.join("asymmetric", "X448", "x448-pkcs8.pem"), +            lambda pemfile: pemfile.read(), +            mode="rb" +        ) +        key = load_pem_private_key(data, b"password", backend) +        assert key.private_bytes( +            Encoding.PEM, PrivateFormat.PKCS8, NoEncryption() +        ) == unencrypted + +    @pytest.mark.parametrize( +        ("key_path", "encoding", "loader"), +        [ +            ( +                ["X448", "x448-pub.pem"], +                Encoding.PEM, +                load_pem_public_key +            ), +            ( +                ["X448", "x448-pub.der"], +                Encoding.DER, +                load_der_public_key +            ), +        ] +    ) +    def test_load_public_key(self, key_path, encoding, loader, backend): +        data = load_vectors_from_file( +            os.path.join("asymmetric", *key_path), +            lambda pemfile: pemfile.read(), +            mode="rb" +        ) +        public_key = loader(data, backend) +        assert public_key.public_bytes( +            encoding, PublicFormat.SubjectPublicKeyInfo +        ) == data diff --git a/tests/hazmat/primitives/test_x448.py b/tests/hazmat/primitives/test_x448.py index 71b25341..1833b03d 100644 --- a/tests/hazmat/primitives/test_x448.py +++ b/tests/hazmat/primitives/test_x448.py @@ -11,6 +11,7 @@ import pytest  from cryptography.exceptions import _Reasons  from cryptography.hazmat.backends.interfaces import DHBackend +from cryptography.hazmat.primitives import serialization  from cryptography.hazmat.primitives.asymmetric.x448 import (      X448PrivateKey, X448PublicKey  ) @@ -50,7 +51,7 @@ class TestX448Exchange(object):          private = binascii.unhexlify(vector["input_scalar"])          public = binascii.unhexlify(vector["input_u"])          shared_key = binascii.unhexlify(vector["output_u"]) -        private_key = X448PrivateKey._from_private_bytes(private) +        private_key = X448PrivateKey.from_private_bytes(private)          public_key = X448PublicKey.from_public_bytes(public)          computed_shared_key = private_key.exchange(public_key)          assert computed_shared_key == shared_key @@ -64,11 +65,11 @@ class TestX448Exchange(object):              b"aa3b4749d55b9daf1e5b00288826c467274ce3ebbdd5c17b975e09d4"              b"af6c67cf10d087202db88286e2b79fceea3ec353ef54faa26e219f38"          ) -        private_key = X448PrivateKey._from_private_bytes(private) +        private_key = X448PrivateKey.from_private_bytes(private)          public_key = X448PublicKey.from_public_bytes(public)          for _ in range(1000):              computed_shared_key = private_key.exchange(public_key) -            private_key = X448PrivateKey._from_private_bytes( +            private_key = X448PrivateKey.from_private_bytes(                  computed_shared_key              )              public_key = X448PublicKey.from_public_bytes(old_private) @@ -103,11 +104,60 @@ class TestX448Exchange(object):              )          ]      ) -    def test_public_bytes(self, private_bytes, public_bytes, backend): -        private_key = X448PrivateKey._from_private_bytes(private_bytes) -        assert private_key.public_key().public_bytes() == public_bytes +    def test_pub_priv_bytes_raw(self, private_bytes, public_bytes, backend): +        private_key = X448PrivateKey.from_private_bytes(private_bytes) +        assert private_key.private_bytes( +            serialization.Encoding.Raw, +            serialization.PrivateFormat.Raw, +            serialization.NoEncryption() +        ) == private_bytes +        assert private_key.public_key().public_bytes( +            serialization.Encoding.Raw, serialization.PublicFormat.Raw +        ) == public_bytes          public_key = X448PublicKey.from_public_bytes(public_bytes) -        assert public_key.public_bytes() == public_bytes +        assert public_key.public_bytes( +            serialization.Encoding.Raw, serialization.PublicFormat.Raw +        ) == public_bytes + +    @pytest.mark.parametrize( +        ("encoding", "fmt", "encryption", "passwd", "load_func"), +        [ +            ( +                serialization.Encoding.PEM, +                serialization.PrivateFormat.PKCS8, +                serialization.BestAvailableEncryption(b"password"), +                b"password", +                serialization.load_pem_private_key +            ), +            ( +                serialization.Encoding.DER, +                serialization.PrivateFormat.PKCS8, +                serialization.BestAvailableEncryption(b"password"), +                b"password", +                serialization.load_der_private_key +            ), +            ( +                serialization.Encoding.PEM, +                serialization.PrivateFormat.PKCS8, +                serialization.NoEncryption(), +                None, +                serialization.load_pem_private_key +            ), +            ( +                serialization.Encoding.DER, +                serialization.PrivateFormat.PKCS8, +                serialization.NoEncryption(), +                None, +                serialization.load_der_private_key +            ), +        ] +    ) +    def test_round_trip_private_serialization(self, encoding, fmt, encryption, +                                              passwd, load_func, backend): +        key = X448PrivateKey.generate() +        serialized = key.private_bytes(encoding, fmt, encryption) +        loaded_key = load_func(serialized, passwd, backend) +        assert isinstance(loaded_key, X448PrivateKey)      def test_generate(self, backend):          key = X448PrivateKey.generate() @@ -125,3 +175,46 @@ class TestX448Exchange(object):          with pytest.raises(ValueError):              X448PublicKey.from_public_bytes(b"a" * 57) + +    def test_invalid_private_bytes(self, backend): +        key = X448PrivateKey.generate() +        with pytest.raises(ValueError): +            key.private_bytes( +                serialization.Encoding.Raw, +                serialization.PrivateFormat.Raw, +                None +            ) + +        with pytest.raises(ValueError): +            key.private_bytes( +                serialization.Encoding.Raw, +                serialization.PrivateFormat.PKCS8, +                None +            ) + +        with pytest.raises(ValueError): +            key.private_bytes( +                serialization.Encoding.PEM, +                serialization.PrivateFormat.Raw, +                serialization.NoEncryption() +            ) + +    def test_invalid_public_bytes(self, backend): +        key = X448PrivateKey.generate().public_key() +        with pytest.raises(ValueError): +            key.public_bytes( +                serialization.Encoding.Raw, +                serialization.PublicFormat.SubjectPublicKeyInfo +            ) + +        with pytest.raises(ValueError): +            key.public_bytes( +                serialization.Encoding.PEM, +                serialization.PublicFormat.PKCS1 +            ) + +        with pytest.raises(ValueError): +            key.public_bytes( +                serialization.Encoding.PEM, +                serialization.PublicFormat.Raw +            ) | 
