diff options
Diffstat (limited to 'tests/hazmat/primitives/test_serialization.py')
| -rw-r--r-- | tests/hazmat/primitives/test_serialization.py | 648 |
1 files changed, 590 insertions, 58 deletions
diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 22c2145c..8e8e15af 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -16,10 +16,15 @@ from cryptography.hazmat.backends.interfaces import ( DERSerializationBackend, DSABackend, EllipticCurveBackend, PEMSerializationBackend, RSABackend ) -from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa +from cryptography.hazmat.primitives.asymmetric import ( + dsa, ec, ed25519, ed448, rsa, x25519, x448 +) from cryptography.hazmat.primitives.serialization import ( - BestAvailableEncryption, load_der_private_key, load_der_public_key, - load_pem_private_key, load_pem_public_key, load_ssh_public_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 ) @@ -31,6 +36,55 @@ from .utils import ( from ...utils import raises_unsupported_algorithm +class TestBufferProtocolSerialization(object): + @pytest.mark.requires_backend_interface(interface=RSABackend) + @pytest.mark.parametrize( + ("key_path", "password"), + [ + (["DER_Serialization", "enc-rsa-pkcs8.der"], bytearray(b"foobar")), + (["DER_Serialization", "enc2-rsa-pkcs8.der"], bytearray(b"baz")), + (["DER_Serialization", "unenc-rsa-pkcs8.der"], None), + (["DER_Serialization", "testrsa.der"], None), + ] + ) + def test_load_der_rsa_private_key(self, key_path, password, backend): + data = load_vectors_from_file( + os.path.join("asymmetric", *key_path), + lambda derfile: derfile.read(), mode="rb" + ) + key = load_der_private_key(bytearray(data), password, backend) + assert key + assert isinstance(key, rsa.RSAPrivateKey) + _check_rsa_private_numbers(key.private_numbers()) + + @pytest.mark.requires_backend_interface(interface=RSABackend) + @pytest.mark.parametrize( + ("key_path", "password"), + [ + ( + ["PEM_Serialization", "rsa_private_key.pem"], + bytearray(b"123456") + ), + (["PKCS8", "unenc-rsa-pkcs8.pem"], None), + (["PKCS8", "enc-rsa-pkcs8.pem"], bytearray(b"foobar")), + (["PKCS8", "enc2-rsa-pkcs8.pem"], bytearray(b"baz")), + ( + ["Traditional_OpenSSL_Serialization", "key1.pem"], + bytearray(b"123456") + ), + ] + ) + def test_load_pem_rsa_private_key(self, key_path, password, backend): + data = load_vectors_from_file( + os.path.join("asymmetric", *key_path), + lambda pemfile: pemfile.read(), mode="rb" + ) + key = load_pem_private_key(bytearray(data), password, backend) + assert key + assert isinstance(key, rsa.RSAPrivateKey) + _check_rsa_private_numbers(key.private_numbers()) + + @pytest.mark.requires_backend_interface(interface=DERSerializationBackend) class TestDERSerialization(object): @pytest.mark.requires_backend_interface(interface=RSABackend) @@ -53,8 +107,7 @@ class TestDERSerialization(object): ) assert key assert isinstance(key, rsa.RSAPrivateKey) - if isinstance(key, rsa.RSAPrivateKeyWithSerialization): - _check_rsa_private_numbers(key.private_numbers()) + _check_rsa_private_numbers(key.private_numbers()) @pytest.mark.requires_backend_interface(interface=DSABackend) @pytest.mark.parametrize( @@ -76,8 +129,27 @@ class TestDERSerialization(object): ) assert key assert isinstance(key, dsa.DSAPrivateKey) - if isinstance(key, dsa.DSAPrivateKeyWithSerialization): - _check_dsa_private_numbers(key.private_numbers()) + _check_dsa_private_numbers(key.private_numbers()) + + @pytest.mark.parametrize( + "key_path", + [ + ["DER_Serialization", "enc-rsa-pkcs8.der"], + ] + ) + @pytest.mark.requires_backend_interface(interface=RSABackend) + def test_password_not_bytes(self, key_path, backend): + key_file = os.path.join("asymmetric", *key_path) + password = u"this password is not bytes" + + with pytest.raises(TypeError): + load_vectors_from_file( + key_file, + lambda derfile: load_der_private_key( + derfile.read(), password, backend + ), + mode="rb" + ) @pytest.mark.parametrize( ("key_path", "password"), @@ -247,9 +319,8 @@ class TestDERSerialization(object): ) assert key assert isinstance(key, rsa.RSAPublicKey) - if isinstance(key, rsa.RSAPublicKeyWithSerialization): - numbers = key.public_numbers() - assert numbers.e == 65537 + numbers = key.public_numbers() + assert numbers.e == 65537 def test_load_der_invalid_public_key(self, backend): with pytest.raises(ValueError): @@ -293,6 +364,14 @@ class TestDERSerialization(object): assert key.curve.name == "secp256r1" assert key.curve.key_size == 256 + def test_wrong_parameters_format(self, backend): + param_data = b"---- NOT A KEY ----\n" + + with pytest.raises(ValueError): + load_der_parameters( + param_data, backend + ) + @pytest.mark.requires_backend_interface(interface=PEMSerializationBackend) class TestPEMSerialization(object): @@ -330,8 +409,7 @@ class TestPEMSerialization(object): assert key assert isinstance(key, rsa.RSAPrivateKey) - if isinstance(key, rsa.RSAPrivateKeyWithSerialization): - _check_rsa_private_numbers(key.private_numbers()) + _check_rsa_private_numbers(key.private_numbers()) @pytest.mark.parametrize( ("key_path", "password"), @@ -352,8 +430,7 @@ class TestPEMSerialization(object): ) assert key assert isinstance(key, dsa.DSAPrivateKey) - if isinstance(key, dsa.DSAPrivateKeyWithSerialization): - _check_dsa_private_numbers(key.private_numbers()) + _check_dsa_private_numbers(key.private_numbers()) @pytest.mark.parametrize( ("key_path", "password"), @@ -397,9 +474,8 @@ class TestPEMSerialization(object): ) assert key assert isinstance(key, rsa.RSAPublicKey) - if isinstance(key, rsa.RSAPublicKeyWithSerialization): - numbers = key.public_numbers() - assert numbers.e == 65537 + numbers = key.public_numbers() + assert numbers.e == 65537 @pytest.mark.parametrize( ("key_file"), @@ -498,6 +574,43 @@ class TestPEMSerialization(object): ) ) + def test_invalid_encoding_with_traditional(self, backend): + key_file = os.path.join( + "asymmetric", "Traditional_OpenSSL_Serialization", "testrsa.pem" + ) + key = load_vectors_from_file( + key_file, + lambda pemfile: load_pem_private_key( + pemfile.read(), None, backend + ), + mode="rb" + ) + + for enc in (Encoding.OpenSSH, Encoding.Raw, Encoding.X962): + with pytest.raises(ValueError): + key.private_bytes( + enc, PrivateFormat.TraditionalOpenSSL, NoEncryption() + ) + + @pytest.mark.parametrize( + "key_path", + [ + ["Traditional_OpenSSL_Serialization", "testrsa-encrypted.pem"], + ["PKCS8", "enc-rsa-pkcs8.pem"] + ] + ) + def test_password_not_bytes(self, key_path, backend): + key_file = os.path.join("asymmetric", *key_path) + password = u"this password is not bytes" + + with pytest.raises(TypeError): + load_vectors_from_file( + key_file, + lambda pemfile: load_pem_private_key( + pemfile.read().encode(), password, backend + ) + ) + @pytest.mark.parametrize( "key_path", [ @@ -558,6 +671,12 @@ class TestPEMSerialization(object): with pytest.raises(ValueError): load_pem_public_key(key_data, backend) + def test_wrong_parameters_format(self, backend): + param_data = b"---- NOT A KEY ----\n" + + with pytest.raises(ValueError): + load_pem_parameters(param_data, backend) + def test_corrupt_traditional_format(self, backend): # privkey.pem with a bunch of data missing. key_data = textwrap.dedent("""\ @@ -770,41 +889,40 @@ class TestPEMSerialization(object): params = key.parameters() assert isinstance(params, dsa.DSAParameters) - if isinstance(params, dsa.DSAParametersWithNumbers): - num = key.private_numbers() - pub = num.public_numbers - parameter_numbers = pub.parameter_numbers - assert num.x == int("00a535a8e1d0d91beafc8bee1d9b2a3a8de3311203", - 16) - assert pub.y == int( - "2b260ea97dc6a12ae932c640e7df3d8ff04a8a05a0324f8d5f1b23f15fa1" - "70ff3f42061124eff2586cb11b49a82dcdc1b90fc6a84fb10109cb67db5d" - "2da971aeaf17be5e37284563e4c64d9e5fc8480258b319f0de29d54d8350" - "70d9e287914d77df81491f4423b62da984eb3f45eb2a29fcea5dae525ac6" - "ab6bcce04bfdf5b6", - 16 - ) + num = key.private_numbers() + pub = num.public_numbers + parameter_numbers = pub.parameter_numbers + assert num.x == int("00a535a8e1d0d91beafc8bee1d9b2a3a8de3311203", + 16) + assert pub.y == int( + "2b260ea97dc6a12ae932c640e7df3d8ff04a8a05a0324f8d5f1b23f15fa1" + "70ff3f42061124eff2586cb11b49a82dcdc1b90fc6a84fb10109cb67db5d" + "2da971aeaf17be5e37284563e4c64d9e5fc8480258b319f0de29d54d8350" + "70d9e287914d77df81491f4423b62da984eb3f45eb2a29fcea5dae525ac6" + "ab6bcce04bfdf5b6", + 16 + ) - assert parameter_numbers.p == int( - "00aa0930cc145825221caffa28ac2894196a27833de5ec21270791689420" - "7774a2e7b238b0d36f1b2499a2c2585083eb01432924418d867faa212dd1" - "071d4dceb2782794ad393cc08a4d4ada7f68d6e839a5fcd34b4e402d82cb" - "8a8cb40fec31911bf9bd360b034caacb4c5e947992573c9e90099c1b0f05" - "940cabe5d2de49a167", - 16 - ) + assert parameter_numbers.p == int( + "00aa0930cc145825221caffa28ac2894196a27833de5ec21270791689420" + "7774a2e7b238b0d36f1b2499a2c2585083eb01432924418d867faa212dd1" + "071d4dceb2782794ad393cc08a4d4ada7f68d6e839a5fcd34b4e402d82cb" + "8a8cb40fec31911bf9bd360b034caacb4c5e947992573c9e90099c1b0f05" + "940cabe5d2de49a167", + 16 + ) - assert parameter_numbers.q == int( - "00adc0e869b36f0ac013a681fdf4d4899d69820451", 16) + assert parameter_numbers.q == int( + "00adc0e869b36f0ac013a681fdf4d4899d69820451", 16) - assert parameter_numbers.g == int( - "008c6b4589afa53a4d1048bfc346d1f386ca75521ccf72ddaa251286880e" - "e13201ff48890bbfc33d79bacaec71e7a778507bd5f1a66422e39415be03" - "e71141ba324f5b93131929182c88a9fa4062836066cebe74b5c6690c7d10" - "1106c240ab7ebd54e4e3301fd086ce6adac922fb2713a2b0887cba13b9bc" - "68ce5cfff241cd3246", - 16 - ) + assert parameter_numbers.g == int( + "008c6b4589afa53a4d1048bfc346d1f386ca75521ccf72ddaa251286880e" + "e13201ff48890bbfc33d79bacaec71e7a778507bd5f1a66422e39415be03" + "e71141ba324f5b93131929182c88a9fa4062836066cebe74b5c6690c7d10" + "1106c240ab7ebd54e4e3301fd086ce6adac922fb2713a2b0887cba13b9bc" + "68ce5cfff241cd3246", + 16 + ) @pytest.mark.parametrize( ("key_file", "password"), @@ -813,9 +931,7 @@ class TestPEMSerialization(object): ] ) def test_load_bad_oid_key(self, key_file, password, backend): - with raises_unsupported_algorithm( - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM - ): + with pytest.raises(ValueError): load_vectors_from_file( os.path.join( "asymmetric", "PKCS8", key_file), @@ -861,7 +977,18 @@ class TestRSASSHSerialization(object): with pytest.raises(ValueError): load_ssh_public_key(ssh_key, backend) - def test_load_ssh_public_key_rsa_extra_string_after_comment(self, backend): + def test_load_ssh_public_key_truncated_int(self, backend): + ssh_key = b'ssh-rsa AAAAB3NzaC1yc2EAAAA=' + + with pytest.raises(ValueError): + load_ssh_public_key(ssh_key, backend) + + ssh_key = b'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAACKr+IHXo' + + with pytest.raises(ValueError): + load_ssh_public_key(ssh_key, backend) + + def test_load_ssh_public_key_rsa_comment_with_spaces(self, backend): ssh_key = ( b"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDu/XRP1kyK6Cgt36gts9XAk" b"FiiuJLW6RU0j3KKVZSs1I7Z3UmU9/9aVh/rZV43WQG8jaR6kkcP4stOR0DEtll" @@ -873,8 +1000,7 @@ class TestRSASSHSerialization(object): b"2MzHvnbv testkey@localhost extra" ) - with pytest.raises(ValueError): - load_ssh_public_key(ssh_key, backend) + load_ssh_public_key(ssh_key, backend) def test_load_ssh_public_key_rsa_extra_data_after_modulo(self, backend): ssh_key = ( @@ -950,7 +1076,7 @@ class TestDSSSSHSerialization(object): with pytest.raises(ValueError): load_ssh_public_key(ssh_key, backend) - def test_load_ssh_public_key_dss_extra_string_after_comment(self, backend): + def test_load_ssh_public_key_dss_comment_with_spaces(self, backend): ssh_key = ( b"ssh-dss AAAAB3NzaC1kc3MAAACBALmwUtfwdjAUjU2Dixd5DvT0NDcjjr69UD" b"LqSD/Xt5Al7D3GXr1WOrWGpjO0NE9qzRCvMTU7zykRH6XjuNXB6Hvv48Zfm4vm" @@ -964,8 +1090,7 @@ class TestDSSSSHSerialization(object): b"z53N7tPF/IhHTjBHb1Ol7IFu9p9A== testkey@localhost extra" ) - with pytest.raises(ValueError): - load_ssh_public_key(ssh_key, backend) + load_ssh_public_key(ssh_key, backend) def test_load_ssh_public_key_dss_extra_data_after_modulo(self, backend): ssh_key = ( @@ -1169,6 +1294,53 @@ class TestECDSASSHSerialization(object): load_ssh_public_key(ssh_key, backend) +@pytest.mark.supported( + only_if=lambda backend: backend.ed25519_supported(), + skip_message="Requires OpenSSL with Ed25519 support" +) +class TestEd25519SSHSerialization(object): + def test_load_ssh_public_key(self, backend): + ssh_key = ( + b"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG2fgpmpYO61qeAxGd0wgRaN/E4" + b"GR+xWvBmvxjxrB1vG user@chiron.local" + ) + key = load_ssh_public_key(ssh_key, backend) + assert isinstance(key, ed25519.Ed25519PublicKey) + assert key.public_bytes( + Encoding.Raw, PublicFormat.Raw + ) == ( + b"m\x9f\x82\x99\xa9`\xee\xb5\xa9\xe01\x19\xdd0\x81\x16\x8d\xfc" + b"N\x06G\xecV\xbc\x19\xaf\xc6<k\x07[\xc6" + ) + + def test_public_bytes_openssh(self, backend): + ssh_key = ( + b"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG2fgpmpYO61qeAxGd0wgRaN/E4" + b"GR+xWvBmvxjxrB1vG" + ) + key = load_ssh_public_key(ssh_key, backend) + assert isinstance(key, ed25519.Ed25519PublicKey) + assert key.public_bytes( + Encoding.OpenSSH, PublicFormat.OpenSSH + ) == ssh_key + + def test_load_ssh_public_key_not_32_bytes(self, backend): + ssh_key = ( + b"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI22fgpmpYO61qeAxGd0wgRaN/E4" + b"GR+xWvBmvxjxrB1vGaGVs user@chiron.local" + ) + with pytest.raises(ValueError): + load_ssh_public_key(ssh_key, backend) + + def test_load_ssh_public_key_trailing_data(self, backend): + ssh_key = ( + b"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG2fgpmpYO61qeAxGd0wgRa" + b"N/E4GR+xWvBmvxjxrB1vGdHJhaWxpbmdkYXRh user@chiron.local" + ) + with pytest.raises(ValueError): + load_ssh_public_key(ssh_key, backend) + + class TestKeySerializationEncryptionTypes(object): def test_non_bytes_password(self): with pytest.raises(ValueError): @@ -1177,3 +1349,363 @@ 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.ed25519_supported(), + skip_message="Requires OpenSSL with Ed25519 support" +) +class TestEd25519Serialization(object): + def test_load_der_private_key(self, backend): + data = load_vectors_from_file( + os.path.join("asymmetric", "Ed25519", "ed25519-pkcs8-enc.der"), + lambda derfile: derfile.read(), + mode="rb" + ) + unencrypted = load_vectors_from_file( + os.path.join("asymmetric", "Ed25519", "ed25519-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", "Ed25519", "ed25519-pkcs8-enc.pem"), + lambda pemfile: pemfile.read(), + mode="rb" + ) + unencrypted = load_vectors_from_file( + os.path.join("asymmetric", "Ed25519", "ed25519-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"), + [ + ( + ["Ed25519", "ed25519-pub.pem"], + Encoding.PEM, + load_pem_public_key + ), + ( + ["Ed25519", "ed25519-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 + + def test_openssl_serialization_unsupported(self, backend): + key = ed25519.Ed25519PrivateKey.generate() + with pytest.raises(ValueError): + key.private_bytes( + Encoding.PEM, PrivateFormat.TraditionalOpenSSL, NoEncryption(), + ) + with pytest.raises(ValueError): + key.private_bytes( + Encoding.DER, PrivateFormat.TraditionalOpenSSL, NoEncryption(), + ) + + +@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 + + def test_openssl_serialization_unsupported(self, backend): + key = x448.X448PrivateKey.generate() + with pytest.raises(ValueError): + key.private_bytes( + Encoding.PEM, PrivateFormat.TraditionalOpenSSL, NoEncryption(), + ) + with pytest.raises(ValueError): + key.private_bytes( + Encoding.DER, PrivateFormat.TraditionalOpenSSL, NoEncryption(), + ) + + +@pytest.mark.supported( + only_if=lambda backend: backend.x25519_supported(), + skip_message="Requires OpenSSL with X25519 support" +) +class TestX25519Serialization(object): + def test_load_der_private_key(self, backend): + data = load_vectors_from_file( + os.path.join("asymmetric", "X25519", "x25519-pkcs8-enc.der"), + lambda derfile: derfile.read(), + mode="rb" + ) + unencrypted = load_vectors_from_file( + os.path.join("asymmetric", "X25519", "x25519-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", "X25519", "x25519-pkcs8-enc.pem"), + lambda pemfile: pemfile.read(), + mode="rb" + ) + unencrypted = load_vectors_from_file( + os.path.join("asymmetric", "X25519", "x25519-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"), + [ + ( + ["X25519", "x25519-pub.pem"], + Encoding.PEM, + load_pem_public_key + ), + ( + ["X25519", "x25519-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 + + def test_openssl_serialization_unsupported(self, backend): + key = x25519.X25519PrivateKey.generate() + with pytest.raises(ValueError): + key.private_bytes( + Encoding.PEM, PrivateFormat.TraditionalOpenSSL, NoEncryption(), + ) + with pytest.raises(ValueError): + key.private_bytes( + Encoding.DER, PrivateFormat.TraditionalOpenSSL, NoEncryption(), + ) + + +@pytest.mark.supported( + only_if=lambda backend: backend.ed448_supported(), + skip_message="Requires OpenSSL with Ed448 support" +) +class TestEd448Serialization(object): + def test_load_der_private_key(self, backend): + data = load_vectors_from_file( + os.path.join("asymmetric", "Ed448", "ed448-pkcs8-enc.der"), + lambda derfile: derfile.read(), + mode="rb" + ) + unencrypted = load_vectors_from_file( + os.path.join("asymmetric", "Ed448", "ed448-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", "Ed448", "ed448-pkcs8-enc.pem"), + lambda pemfile: pemfile.read(), + mode="rb" + ) + unencrypted = load_vectors_from_file( + os.path.join("asymmetric", "Ed448", "ed448-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"), + [ + ( + ["Ed448", "ed448-pub.pem"], + Encoding.PEM, + load_pem_public_key + ), + ( + ["Ed448", "ed448-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 + + def test_openssl_serialization_unsupported(self, backend): + key = ed448.Ed448PrivateKey.generate() + with pytest.raises(ValueError): + key.private_bytes( + Encoding.PEM, PrivateFormat.TraditionalOpenSSL, NoEncryption(), + ) + with pytest.raises(ValueError): + key.private_bytes( + Encoding.DER, PrivateFormat.TraditionalOpenSSL, NoEncryption(), + ) + + def test_openssh_serialization_unsupported(self, backend): + key = ed448.Ed448PrivateKey.generate() + with pytest.raises(ValueError): + key.public_key().public_bytes( + Encoding.OpenSSH, PublicFormat.OpenSSH, + ) + + +class TestDHSerialization(object): + """Test all options with least-supported key type. + """ + def test_dh_public_key(self, backend): + data = load_vectors_from_file( + os.path.join("asymmetric", "DH", "dhkey.pem"), + lambda pemfile: pemfile.read(), + mode="rb" + ) + public_key = load_pem_private_key(data, None, backend).public_key() + for enc in ( + Encoding.PEM, Encoding.DER, Encoding.OpenSSH, + Encoding.Raw, Encoding.X962 + ): + for fmt in ( + PublicFormat.SubjectPublicKeyInfo, PublicFormat.PKCS1, + PublicFormat.OpenSSH, PublicFormat.Raw, + PublicFormat.CompressedPoint, PublicFormat.UncompressedPoint, + ): + if ( + enc in (Encoding.PEM, Encoding.DER) and + fmt == PublicFormat.SubjectPublicKeyInfo + ): + # tested elsewhere + continue + with pytest.raises(ValueError): + public_key.public_bytes(enc, fmt) + + def test_dh_private_key(self, backend): + data = load_vectors_from_file( + os.path.join("asymmetric", "DH", "dhkey.pem"), + lambda pemfile: pemfile.read(), + mode="rb" + ) + private_key = load_pem_private_key(data, None, backend) + for enc in ( + Encoding.PEM, Encoding.DER, Encoding.OpenSSH, + Encoding.Raw, Encoding.X962 + ): + for fmt in ( + PrivateFormat.PKCS8, PrivateFormat.TraditionalOpenSSL, + PrivateFormat.Raw + ): + if ( + enc in (Encoding.PEM, Encoding.DER) and + fmt is PrivateFormat.PKCS8 + ): + # tested elsewhere + continue + with pytest.raises(ValueError): + private_key.private_bytes(enc, fmt, NoEncryption()) |
