aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2019-01-20 15:02:59 -0600
committerAlex Gaynor <alex.gaynor@gmail.com>2019-01-20 15:02:59 -0600
commita07b1f5463361570c3248c1096ffd8b3bff0bfa5 (patch)
tree66bc3e076557579ad062dea6a08a716519857b11 /src
parent5fe88ea0500c6e418492f4b166c0d4a24e9632cc (diff)
downloadcryptography-a07b1f5463361570c3248c1096ffd8b3bff0bfa5.tar.gz
cryptography-a07b1f5463361570c3248c1096ffd8b3bff0bfa5.tar.bz2
cryptography-a07b1f5463361570c3248c1096ffd8b3bff0bfa5.zip
add support for encoding compressed points (#4638)
* add support for encoding compressed points * review feedback
Diffstat (limited to 'src')
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py11
-rw-r--r--src/cryptography/hazmat/backends/openssl/ec.py57
-rw-r--r--src/cryptography/hazmat/primitives/serialization/base.py3
3 files changed, 64 insertions, 7 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index ab0daa28..b5232ba0 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -1690,6 +1690,10 @@ class Backend(object):
"format must be an item from the PrivateFormat enum"
)
+ # X9.62 encoding is only valid for EC public keys
+ if encoding is serialization.Encoding.X962:
+ raise ValueError("X9.62 format is only valid for EC public keys")
+
# Raw format and encoding are only valid for X25519, Ed25519, X448, and
# Ed448 keys. We capture those cases before this method is called so if
# we see those enum values here it means the caller has passed them to
@@ -1792,6 +1796,13 @@ class Backend(object):
if not isinstance(encoding, serialization.Encoding):
raise TypeError("encoding must be an item from the Encoding enum")
+ # Compressed/UncompressedPoint are only valid for EC keys and those
+ # cases are handled by the ECPublicKey public_bytes method before this
+ # method is called
+ if format in (serialization.PublicFormat.UncompressedPoint,
+ serialization.PublicFormat.CompressedPoint):
+ raise ValueError("Point formats are not valid for this key type")
+
# Raw format and encoding are only valid for X25519, Ed25519, X448, and
# Ed448 keys. We capture those cases before this method is called so if
# we see those enum values here it means the caller has passed them to
diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py
index 852b4918..a8d69bdf 100644
--- a/src/cryptography/hazmat/backends/openssl/ec.py
+++ b/src/cryptography/hazmat/backends/openssl/ec.py
@@ -275,19 +275,62 @@ class _EllipticCurvePublicKey(object):
curve=self._curve
)
+ def _encode_point(self, format):
+ if format is serialization.PublicFormat.CompressedPoint:
+ conversion = self._backend._lib.POINT_CONVERSION_COMPRESSED
+ else:
+ assert format is serialization.PublicFormat.UncompressedPoint
+ conversion = self._backend._lib.POINT_CONVERSION_UNCOMPRESSED
+
+ group = self._backend._lib.EC_KEY_get0_group(self._ec_key)
+ self._backend.openssl_assert(group != self._backend._ffi.NULL)
+ point = self._backend._lib.EC_KEY_get0_public_key(self._ec_key)
+ self._backend.openssl_assert(point != self._backend._ffi.NULL)
+ with self._backend._tmp_bn_ctx() as bn_ctx:
+ buflen = self._backend._lib.EC_POINT_point2oct(
+ group, point, conversion, self._backend._ffi.NULL, 0, bn_ctx
+ )
+ self._backend.openssl_assert(buflen > 0)
+ buf = self._backend._ffi.new("char[]", buflen)
+ res = self._backend._lib.EC_POINT_point2oct(
+ group, point, conversion, buf, buflen, bn_ctx
+ )
+ self._backend.openssl_assert(buflen == res)
+
+ return self._backend._ffi.buffer(buf)[:]
+
def public_bytes(self, encoding, format):
if format is serialization.PublicFormat.PKCS1:
raise ValueError(
"EC public keys do not support PKCS1 serialization"
)
- return self._backend._public_key_bytes(
- encoding,
- format,
- self,
- self._evp_pkey,
- None
- )
+ if (
+ encoding is serialization.Encoding.X962 or
+ format is serialization.PublicFormat.CompressedPoint or
+ format is serialization.PublicFormat.UncompressedPoint
+ ):
+ if (
+ encoding is not serialization.Encoding.X962 or
+ format not in (
+ serialization.PublicFormat.CompressedPoint,
+ serialization.PublicFormat.UncompressedPoint
+ )
+ ):
+ raise ValueError(
+ "X962 encoding must be used with CompressedPoint or "
+ "UncompressedPoint format"
+ )
+
+ return self._encode_point(format)
+ else:
+ return self._backend._public_key_bytes(
+ encoding,
+ format,
+ self,
+ self._evp_pkey,
+ None
+ )
def verify(self, signature, data, signature_algorithm):
_check_signature_algorithm(signature_algorithm)
diff --git a/src/cryptography/hazmat/primitives/serialization/base.py b/src/cryptography/hazmat/primitives/serialization/base.py
index 1670fd18..4218ea82 100644
--- a/src/cryptography/hazmat/primitives/serialization/base.py
+++ b/src/cryptography/hazmat/primitives/serialization/base.py
@@ -41,6 +41,7 @@ class Encoding(Enum):
DER = "DER"
OpenSSH = "OpenSSH"
Raw = "Raw"
+ X962 = "ANSI X9.62"
class PrivateFormat(Enum):
@@ -54,6 +55,8 @@ class PublicFormat(Enum):
PKCS1 = "Raw PKCS#1"
OpenSSH = "OpenSSH"
Raw = "Raw"
+ CompressedPoint = "X9.62 Compressed Point"
+ UncompressedPoint = "X9.62 Uncompressed Point"
class ParameterFormat(Enum):