2018-07-25 17:55:12 +00:00
|
|
|
"""
|
|
|
|
This file is part of pyUmbral.
|
|
|
|
|
|
|
|
pyUmbral is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
pyUmbral is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with pyUmbral. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
"""
|
|
|
|
|
2018-07-11 07:51:01 +00:00
|
|
|
from cryptography.hazmat.backends import default_backend
|
2018-06-26 08:26:36 +00:00
|
|
|
|
2018-07-19 21:05:41 +00:00
|
|
|
from umbral import openssl
|
2018-07-07 05:08:52 +00:00
|
|
|
|
|
|
|
|
2018-06-26 08:26:36 +00:00
|
|
|
class Curve:
|
|
|
|
"""
|
|
|
|
Acts as a container to store constant variables such as the OpenSSL
|
2018-07-21 21:46:11 +00:00
|
|
|
curve_nid, the EC_GROUP struct, and the order of the curve.
|
2018-07-20 19:53:08 +00:00
|
|
|
|
|
|
|
Contains a whitelist of supported elliptic curves used in pyUmbral.
|
|
|
|
|
2018-06-26 08:26:36 +00:00
|
|
|
"""
|
2018-06-26 08:43:44 +00:00
|
|
|
|
2018-07-19 21:05:41 +00:00
|
|
|
_supported_curves = {
|
2018-07-20 19:53:08 +00:00
|
|
|
415: 'secp256r1',
|
|
|
|
714: 'secp256k1',
|
|
|
|
715: 'secp384r1'
|
2018-07-19 21:05:41 +00:00
|
|
|
}
|
|
|
|
|
2018-07-20 19:53:08 +00:00
|
|
|
def __init__(self, nid: int) -> None:
|
2018-06-26 20:01:01 +00:00
|
|
|
"""
|
2018-07-21 21:46:11 +00:00
|
|
|
Instantiates an OpenSSL curve with the provided curve_nid and derives
|
2018-06-26 20:01:01 +00:00
|
|
|
the proper EC_GROUP struct and order. You can _only_ instantiate curves
|
|
|
|
with supported nids (see `Curve.supported_curves`).
|
|
|
|
"""
|
2018-07-20 19:53:08 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
self.__curve_name = self._supported_curves[nid]
|
|
|
|
except KeyError:
|
2018-07-19 21:05:41 +00:00
|
|
|
raise NotImplementedError("Curve NID {} is not supported.".format(nid))
|
2018-06-26 08:43:44 +00:00
|
|
|
|
2018-07-19 21:05:41 +00:00
|
|
|
# set only once
|
|
|
|
self.__curve_nid = nid
|
|
|
|
self.__ec_group = openssl._get_ec_group_by_curve_nid(self.__curve_nid)
|
|
|
|
self.__order = openssl._get_ec_order_by_group(self.ec_group)
|
|
|
|
self.__generator = openssl._get_ec_generator_by_group(self.ec_group)
|
2018-06-26 08:35:59 +00:00
|
|
|
|
2018-07-21 21:12:59 +00:00
|
|
|
# Init cache
|
2018-10-08 16:24:17 +00:00
|
|
|
self.__field_order_size_in_bytes = 0
|
|
|
|
self.__group_order_size_in_bytes = 0
|
2018-07-21 21:12:59 +00:00
|
|
|
|
2018-07-20 19:56:09 +00:00
|
|
|
@classmethod
|
|
|
|
def from_name(cls, name: str) -> 'Curve':
|
|
|
|
"""
|
2018-07-21 21:46:11 +00:00
|
|
|
Alternate constructor to generate a curve instance by its name.
|
|
|
|
|
2018-07-20 19:56:09 +00:00
|
|
|
Raises NotImplementedError if the name cannot be mapped to a known
|
|
|
|
supported curve NID.
|
2018-07-19 21:05:41 +00:00
|
|
|
|
2018-07-20 19:56:09 +00:00
|
|
|
"""
|
2018-07-19 21:05:41 +00:00
|
|
|
|
2018-07-20 19:56:09 +00:00
|
|
|
name = name.casefold() # normalize
|
2018-07-19 21:05:41 +00:00
|
|
|
|
2018-07-20 19:56:09 +00:00
|
|
|
for supported_nid, supported_name in cls._supported_curves.items():
|
|
|
|
if name == supported_name:
|
|
|
|
instance = cls(nid=supported_nid)
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
message = "{} is not supported curve name.".format(name)
|
|
|
|
raise NotImplementedError(message)
|
2018-07-19 21:05:41 +00:00
|
|
|
|
2018-07-20 19:56:09 +00:00
|
|
|
return instance
|
2018-06-26 20:01:01 +00:00
|
|
|
|
2018-06-27 21:23:28 +00:00
|
|
|
def __eq__(self, other):
|
2018-07-19 21:05:41 +00:00
|
|
|
return self.__curve_nid == other.curve_nid
|
2018-06-27 21:23:28 +00:00
|
|
|
|
2018-07-07 05:12:23 +00:00
|
|
|
def __repr__(self):
|
2018-07-20 19:56:52 +00:00
|
|
|
return "<OpenSSL Curve(nid={}, name={})>".format(self.__curve_nid, self.__curve_name)
|
2018-07-07 05:12:23 +00:00
|
|
|
|
2018-07-20 19:56:09 +00:00
|
|
|
#
|
|
|
|
# Immutable Curve Data
|
|
|
|
#
|
|
|
|
|
|
|
|
@property
|
2018-07-21 21:12:59 +00:00
|
|
|
def field_order_size_in_bytes(self) -> int:
|
2018-10-08 16:24:17 +00:00
|
|
|
if not self.__field_order_size_in_bytes:
|
2018-07-21 21:12:59 +00:00
|
|
|
size_in_bits = openssl._get_ec_group_degree(self.__ec_group)
|
|
|
|
self.__field_order_size_in_bytes = (size_in_bits + 7) // 8
|
|
|
|
return self.__field_order_size_in_bytes
|
2018-07-11 07:51:01 +00:00
|
|
|
|
2018-07-30 10:19:02 +00:00
|
|
|
@property
|
|
|
|
def group_order_size_in_bytes(self) -> int:
|
2018-10-08 16:24:17 +00:00
|
|
|
if not self.__group_order_size_in_bytes:
|
2018-07-30 10:19:02 +00:00
|
|
|
BN_num_bytes = default_backend()._lib.BN_num_bytes
|
|
|
|
self.__group_order_size_in_bytes = BN_num_bytes(self.order)
|
|
|
|
return self.__group_order_size_in_bytes
|
|
|
|
|
2018-07-20 19:56:09 +00:00
|
|
|
@property
|
|
|
|
def curve_nid(self) -> int:
|
|
|
|
return self.__curve_nid
|
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self) -> str:
|
|
|
|
return self.__curve_name
|
|
|
|
|
|
|
|
@property
|
2018-08-10 15:09:00 +00:00
|
|
|
def ec_group(self):
|
2018-07-20 19:56:09 +00:00
|
|
|
return self.__ec_group
|
|
|
|
|
|
|
|
@property
|
2018-08-10 15:09:00 +00:00
|
|
|
def order(self):
|
2018-07-20 19:56:09 +00:00
|
|
|
return self.__order
|
|
|
|
|
|
|
|
@property
|
2018-08-10 15:09:00 +00:00
|
|
|
def generator(self):
|
2018-07-20 19:56:09 +00:00
|
|
|
return self.__generator
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# Global Curve Instances
|
|
|
|
#
|
2018-07-11 07:51:01 +00:00
|
|
|
|
2018-07-19 21:05:41 +00:00
|
|
|
SECP256R1 = Curve.from_name('secp256r1')
|
|
|
|
SECP256K1 = Curve.from_name('secp256k1')
|
|
|
|
SECP384R1 = Curve.from_name('secp384r1')
|
2018-07-20 19:56:09 +00:00
|
|
|
|
2018-07-19 21:05:41 +00:00
|
|
|
CURVES = (SECP256K1, SECP256R1, SECP384R1)
|