aboutsummaryrefslogtreecommitdiffstats
path: root/tests/hazmat/primitives/test_serialization.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/hazmat/primitives/test_serialization.py')
-rw-r--r--tests/hazmat/primitives/test_serialization.py648
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())