From 467072f7d50778f064f192b4e318c19c6cf98293 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 25 Oct 2015 15:44:29 -0500 Subject: add support for encoding/decoding elliptic curve points Based on the work of @ronf in #2346. --- .../hazmat/primitives/asymmetric/utils.py | 34 ++++++++++++++++++++++ src/cryptography/utils.py | 7 +++-- 2 files changed, 39 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cryptography/hazmat/primitives/asymmetric/utils.py b/src/cryptography/hazmat/primitives/asymmetric/utils.py index bad9ab73..b62eadf0 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/utils.py +++ b/src/cryptography/hazmat/primitives/asymmetric/utils.py @@ -13,6 +13,7 @@ from pyasn1.type import namedtype, univ import six from cryptography import utils +from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurve class _DSSSigValue(univ.Sequence): @@ -71,3 +72,36 @@ def encode_dss_signature(r, s): sig.setComponentByName('r', r) sig.setComponentByName('s', s) return encoder.encode(sig) + + +def encode_ec_point(curve, x, y): + if not isinstance(curve, EllipticCurve): + raise TypeError("curve must be an EllipticCurve instance") + + if x is None: + return b'\x00' + else: + # Get the ceiling of curve.key_size / 8 + byte_length = (curve.key_size + 7) // 8 + return ( + b'\x04' + utils.int_to_bytes(x, byte_length) + + utils.int_to_bytes(y, byte_length) + ) + + +def decode_ec_point(curve, data): + if not isinstance(curve, EllipticCurve): + raise TypeError("curve must be an EllipticCurve instance") + + if data == b'\x00': + return None, None + elif data.startswith(b'\x04'): + # Get the ceiling of curve.key_size / 8 + byte_length = (curve.key_size + 7) // 8 + if len(data) == 2 * byte_length + 1: + return (utils.int_from_bytes(data[1:byte_length + 1], 'big'), + utils.int_from_bytes(data[byte_length + 1:], 'big')) + else: + raise ValueError('Invalid elliptic curve point data length') + else: + raise ValueError('Unsupported elliptic curve point type') diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index dac4046d..dbd961f7 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -48,9 +48,12 @@ else: return result -def int_to_bytes(integer): +def int_to_bytes(integer, length=None): hex_string = '%x' % integer - n = len(hex_string) + if length is None: + n = len(hex_string) + else: + n = length * 2 return binascii.unhexlify(hex_string.zfill(n + (n & 1))) -- cgit v1.2.3 From e4150bcc07fb2c68e3c860c31766b4282bba8740 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 27 Oct 2015 12:29:58 +0900 Subject: remove support for null points, improve docs --- src/cryptography/hazmat/primitives/asymmetric/utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/cryptography/hazmat/primitives/asymmetric/utils.py b/src/cryptography/hazmat/primitives/asymmetric/utils.py index b62eadf0..57dea41a 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/utils.py +++ b/src/cryptography/hazmat/primitives/asymmetric/utils.py @@ -79,9 +79,9 @@ def encode_ec_point(curve, x, y): raise TypeError("curve must be an EllipticCurve instance") if x is None: - return b'\x00' + raise ValueError("null points are not supported") else: - # Get the ceiling of curve.key_size / 8 + # key_size is in bits. Convert to bytes and round up byte_length = (curve.key_size + 7) // 8 return ( b'\x04' + utils.int_to_bytes(x, byte_length) + @@ -94,9 +94,9 @@ def decode_ec_point(curve, data): raise TypeError("curve must be an EllipticCurve instance") if data == b'\x00': - return None, None + raise ValueError("null points are not supported") elif data.startswith(b'\x04'): - # Get the ceiling of curve.key_size / 8 + # key_size is in bits. Convert to bytes and round up byte_length = (curve.key_size + 7) // 8 if len(data) == 2 * byte_length + 1: return (utils.int_from_bytes(data[1:byte_length + 1], 'big'), -- cgit v1.2.3 From 13d4e74b13832b495ddfdff043376144d8ada66a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 27 Oct 2015 16:47:55 +0900 Subject: modify approach to use EllipticCurvePublicNumbers methods --- .../hazmat/primitives/asymmetric/ec.py | 28 ++++++++++++++++++ .../hazmat/primitives/asymmetric/utils.py | 34 ---------------------- 2 files changed, 28 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index c6f83667..f25ea6de 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -259,6 +259,34 @@ class EllipticCurvePublicNumbers(object): def public_key(self, backend): return backend.load_elliptic_curve_public_numbers(self) + def encode_point(self): + # key_size is in bits. Convert to bytes and round up + byte_length = (self.curve.key_size + 7) // 8 + return ( + b'\x04' + utils.int_to_bytes(self.x, byte_length) + + utils.int_to_bytes(self.y, byte_length) + ) + + @classmethod + def from_encoded_point(cls, curve, data): + if not isinstance(curve, EllipticCurve): + raise TypeError("curve must be an EllipticCurve instance") + + if data == b'\x00': + raise ValueError("null points are not supported") + elif data.startswith(b'\x04'): + # key_size is in bits. Convert to bytes and round up + byte_length = (curve.key_size + 7) // 8 + if len(data) == 2 * byte_length + 1: + x = utils.int_from_bytes(data[1:byte_length + 1], 'big') + y = utils.int_from_bytes(data[byte_length + 1:], 'big') + else: + raise ValueError('Invalid elliptic curve point data length') + else: + raise ValueError('Unsupported elliptic curve point type') + + return cls(x, y, curve) + curve = utils.read_only_property("_curve") x = utils.read_only_property("_x") y = utils.read_only_property("_y") diff --git a/src/cryptography/hazmat/primitives/asymmetric/utils.py b/src/cryptography/hazmat/primitives/asymmetric/utils.py index 57dea41a..bad9ab73 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/utils.py +++ b/src/cryptography/hazmat/primitives/asymmetric/utils.py @@ -13,7 +13,6 @@ from pyasn1.type import namedtype, univ import six from cryptography import utils -from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurve class _DSSSigValue(univ.Sequence): @@ -72,36 +71,3 @@ def encode_dss_signature(r, s): sig.setComponentByName('r', r) sig.setComponentByName('s', s) return encoder.encode(sig) - - -def encode_ec_point(curve, x, y): - if not isinstance(curve, EllipticCurve): - raise TypeError("curve must be an EllipticCurve instance") - - if x is None: - raise ValueError("null points are not supported") - else: - # key_size is in bits. Convert to bytes and round up - byte_length = (curve.key_size + 7) // 8 - return ( - b'\x04' + utils.int_to_bytes(x, byte_length) + - utils.int_to_bytes(y, byte_length) - ) - - -def decode_ec_point(curve, data): - if not isinstance(curve, EllipticCurve): - raise TypeError("curve must be an EllipticCurve instance") - - if data == b'\x00': - raise ValueError("null points are not supported") - elif data.startswith(b'\x04'): - # key_size is in bits. Convert to bytes and round up - byte_length = (curve.key_size + 7) // 8 - if len(data) == 2 * byte_length + 1: - return (utils.int_from_bytes(data[1:byte_length + 1], 'big'), - utils.int_from_bytes(data[byte_length + 1:], 'big')) - else: - raise ValueError('Invalid elliptic curve point data length') - else: - raise ValueError('Unsupported elliptic curve point type') -- cgit v1.2.3 From 197db3367ceecdbaf0adc5eaa9339b934b10acfe Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 28 Oct 2015 10:09:49 +0900 Subject: address review feedback --- src/cryptography/hazmat/primitives/asymmetric/ec.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index f25ea6de..7782133c 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -272,21 +272,18 @@ class EllipticCurvePublicNumbers(object): if not isinstance(curve, EllipticCurve): raise TypeError("curve must be an EllipticCurve instance") - if data == b'\x00': - raise ValueError("null points are not supported") - elif data.startswith(b'\x04'): + if data.startswith(b'\x04'): # key_size is in bits. Convert to bytes and round up byte_length = (curve.key_size + 7) // 8 if len(data) == 2 * byte_length + 1: x = utils.int_from_bytes(data[1:byte_length + 1], 'big') y = utils.int_from_bytes(data[byte_length + 1:], 'big') + return cls(x, y, curve) else: raise ValueError('Invalid elliptic curve point data length') else: raise ValueError('Unsupported elliptic curve point type') - return cls(x, y, curve) - curve = utils.read_only_property("_curve") x = utils.read_only_property("_x") y = utils.read_only_property("_y") -- cgit v1.2.3