aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py6
-rw-r--r--src/cryptography/hazmat/backends/openssl/x25519.py93
-rw-r--r--src/cryptography/hazmat/backends/openssl/x448.py7
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/x25519.py10
-rw-r--r--src/cryptography/hazmat/primitives/serialization/__init__.py3
5 files changed, 111 insertions, 8 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index ecebe7b8..9eca5f8a 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -511,6 +511,9 @@ class Backend(object):
elif key_type == getattr(self._lib, "EVP_PKEY_X448", None):
# EVP_PKEY_X448 is not present in OpenSSL < 1.1.1
return _X448PrivateKey(self, evp_pkey)
+ elif key_type == getattr(self._lib, "EVP_PKEY_X25519", None):
+ # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.0
+ return _X25519PrivateKey(self, evp_pkey)
else:
raise UnsupportedAlgorithm("Unsupported key type.")
@@ -545,6 +548,9 @@ class Backend(object):
elif key_type == getattr(self._lib, "EVP_PKEY_X448", None):
# EVP_PKEY_X448 is not present in OpenSSL < 1.1.1
return _X448PublicKey(self, evp_pkey)
+ elif key_type == getattr(self._lib, "EVP_PKEY_X25519", None):
+ # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.0
+ return _X25519PublicKey(self, evp_pkey)
else:
raise UnsupportedAlgorithm("Unsupported key type.")
diff --git a/src/cryptography/hazmat/backends/openssl/x25519.py b/src/cryptography/hazmat/backends/openssl/x25519.py
index 06f3985d..914f5941 100644
--- a/src/cryptography/hazmat/backends/openssl/x25519.py
+++ b/src/cryptography/hazmat/backends/openssl/x25519.py
@@ -4,20 +4,66 @@
from __future__ import absolute_import, division, print_function
+import warnings
+
from cryptography import utils
from cryptography.hazmat.backends.openssl.utils import _evp_pkey_derive
+from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.x25519 import (
X25519PrivateKey, X25519PublicKey
)
+_X25519_KEY_SIZE = 32
+
+
@utils.register_interface(X25519PublicKey)
class _X25519PublicKey(object):
def __init__(self, backend, evp_pkey):
self._backend = backend
self._evp_pkey = evp_pkey
- def public_bytes(self):
+ def public_bytes(self, encoding=None, format=None):
+ if encoding is None or format is None:
+ if encoding is not None or format is not None:
+ raise ValueError("Both encoding and format are required")
+ else:
+ warnings.warn(
+ "public_bytes now requires encoding and format arguments. "
+ "Support for calling without arguments will be removed in "
+ "cryptography 2.7",
+ utils.DeprecatedIn25,
+ )
+ encoding = serialization.Encoding.Raw
+ format = serialization.PublicFormat.Raw
+ if (
+ encoding is serialization.Encoding.Raw or
+ format is serialization.PublicFormat.Raw
+ ):
+ if (
+ encoding is not serialization.Encoding.Raw or
+ format is not serialization.PublicFormat.Raw
+ ):
+ raise ValueError(
+ "When using Raw both encoding and format must be Raw"
+ )
+
+ return self._raw_public_bytes()
+
+ if (
+ encoding in serialization._PEM_DER and
+ format is not serialization.PublicFormat.SubjectPublicKeyInfo
+ ):
+ raise ValueError(
+ "format must be SubjectPublicKeyInfo when encoding is PEM or "
+ "DER"
+ )
+
+ return self._backend._public_key_bytes(
+ encoding, format, self, self._evp_pkey, None
+ )
+
+ def _raw_public_bytes(self):
ucharpp = self._backend._ffi.new("unsigned char **")
res = self._backend._lib.EVP_PKEY_get1_tls_encodedpoint(
self._evp_pkey, ucharpp
@@ -56,3 +102,48 @@ class _X25519PrivateKey(object):
return _evp_pkey_derive(
self._backend, self._evp_pkey, peer_public_key
)
+
+ def private_bytes(self, encoding, format, encryption_algorithm):
+ if (
+ encoding is serialization.Encoding.Raw or
+ format is serialization.PublicFormat.Raw
+ ):
+ if (
+ format is not serialization.PrivateFormat.Raw or
+ encoding is not serialization.Encoding.Raw or not
+ isinstance(encryption_algorithm, serialization.NoEncryption)
+ ):
+ raise ValueError(
+ "When using Raw both encoding and format must be Raw "
+ "and encryption_algorithm must be NoEncryption"
+ )
+
+ return self._raw_private_bytes()
+
+ if (
+ encoding in serialization._PEM_DER and
+ format is not serialization.PrivateFormat.PKCS8
+ ):
+ raise ValueError(
+ "format must be PKCS8 when encoding is PEM or DER"
+ )
+
+ return self._backend._private_key_bytes(
+ encoding, format, encryption_algorithm, self._evp_pkey, None
+ )
+
+ def _raw_private_bytes(self):
+ # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 we can
+ # switch this to EVP_PKEY_new_raw_private_key
+ # The trick we use here is serializing to a PKCS8 key and just
+ # using the last 32 bytes, which is the key itself.
+ bio = self._backend._create_mem_bio_gc()
+ res = self._backend._lib.i2d_PKCS8PrivateKey_bio(
+ bio, self._evp_pkey,
+ self._backend._ffi.NULL, self._backend._ffi.NULL,
+ 0, self._backend._ffi.NULL, self._backend._ffi.NULL
+ )
+ self._backend.openssl_assert(res == 1)
+ pkcs8 = self._backend._read_mem_bio(bio)
+ self._backend.openssl_assert(len(pkcs8) == 48)
+ return pkcs8[-_X25519_KEY_SIZE:]
diff --git a/src/cryptography/hazmat/backends/openssl/x448.py b/src/cryptography/hazmat/backends/openssl/x448.py
index 3792fd79..13e4ce15 100644
--- a/src/cryptography/hazmat/backends/openssl/x448.py
+++ b/src/cryptography/hazmat/backends/openssl/x448.py
@@ -12,9 +12,6 @@ from cryptography.hazmat.primitives.asymmetric.x448 import (
)
_X448_KEY_SIZE = 56
-_PEM_DER = (
- serialization.Encoding.PEM, serialization.Encoding.DER
-)
@utils.register_interface(X448PublicKey)
@@ -39,7 +36,7 @@ class _X448PublicKey(object):
return self._raw_public_bytes()
if (
- encoding in _PEM_DER and
+ encoding in serialization._PEM_DER and
format is not serialization.PublicFormat.SubjectPublicKeyInfo
):
raise ValueError(
@@ -104,7 +101,7 @@ class _X448PrivateKey(object):
return self._raw_private_bytes()
if (
- encoding in _PEM_DER and
+ encoding in serialization._PEM_DER and
format is not serialization.PrivateFormat.PKCS8
):
raise ValueError(
diff --git a/src/cryptography/hazmat/primitives/asymmetric/x25519.py b/src/cryptography/hazmat/primitives/asymmetric/x25519.py
index f4bdf3db..94602261 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/x25519.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/x25519.py
@@ -28,7 +28,7 @@ class X25519PublicKey(object):
return backend.x25519_load_public_bytes(data)
@abc.abstractmethod
- def public_bytes(self):
+ def public_bytes(self, encoding=None, format=None):
"""
The serialized bytes of the public key.
"""
@@ -47,7 +47,7 @@ class X25519PrivateKey(object):
return backend.x25519_generate_key()
@classmethod
- def _from_private_bytes(cls, data):
+ def from_private_bytes(cls, data):
from cryptography.hazmat.backends.openssl.backend import backend
return backend.x25519_load_private_bytes(data)
@@ -58,6 +58,12 @@ class X25519PrivateKey(object):
"""
@abc.abstractmethod
+ def private_bytes(self, encoding, format, encryption_algorithm):
+ """
+ The serialized bytes of the private key.
+ """
+
+ @abc.abstractmethod
def exchange(self, peer_public_key):
"""
Performs a key exchange operation using the provided peer's public key.
diff --git a/src/cryptography/hazmat/primitives/serialization/__init__.py b/src/cryptography/hazmat/primitives/serialization/__init__.py
index 3a34bf8f..f6d4ce99 100644
--- a/src/cryptography/hazmat/primitives/serialization/__init__.py
+++ b/src/cryptography/hazmat/primitives/serialization/__init__.py
@@ -14,6 +14,9 @@ from cryptography.hazmat.primitives.serialization.ssh import (
load_ssh_public_key
)
+
+_PEM_DER = (Encoding.PEM, Encoding.DER)
+
__all__ = [
"load_der_parameters", "load_der_private_key", "load_der_public_key",
"load_pem_parameters", "load_pem_private_key", "load_pem_public_key",