Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #1

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions ECL/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@
from ECL import point, curve, std_curves, point_with_order, koblitz, elgamal, diffie_hellman, ecdsa
from ECL.curve import Curve
from ECL.point import Point
from ECL.utility import EclException
from ECL.utility import EclError
from ECL.diffie_hellman import DiffieHellman
from ECL.point_with_order import PointWOrder

__author__ = 'ivansarno'
__version__ = 'V.5.2'
__all__ = ["Curve", "Point", "PointWOrder", "EclException"]
__doc__ = """ ECL: library includes basic operations on Elliptic curves, 2 cipher and a digital signature protocol.
__version__ = 'V.5.5'
__all__ = ["Curve", "Point", "PointWOrder", "EclError"]
__doc__ = """ ECL: library includes basic operations on Elliptic Curves, 2 ciphers and a digital signature protocol.

includes:
class: Point, PointWOrder, Curve
algorithm: Diffie-Hellman, ElGamal, Koblitz, ECDSA
built-in: Nist's standard curves and points
exception: EclException, DiffieHellmanError, KoblitzFailError, ECDSAError, ElGamalError
exception: EclError, DiffieHellmanError, KoblitzFailError, ECDSAError, ElGamalError
"""
5 changes: 2 additions & 3 deletions ECL/curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
limitations under the License.
"""
__author__ = 'ivansarno'
__version__ = 'V.5.2'
__version__ = 'V.5.5'
__doc__ = """Implementation of Prime Elliptic Curves"""


Expand Down Expand Up @@ -62,8 +62,7 @@ def copy(self):
:return: Curve copy of self
:rtype: Curve
"""
ris = Curve(self.__a, self.__b, self.__prime)
return ris
return Curve(self.__a, self.__b, self.__prime)

def __str__(self):
return "a: %x\nb: 0x%x\nprime: 0x%x\n" % (self.__a, self.__b, self.__prime)
Expand Down
22 changes: 11 additions & 11 deletions ECL/diffie_hellman.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,18 @@
limitations under the License.
"""
from typing import Callable
from ECL.utility import EclException

import sys

from ECL.utility import EclError
from ECL.point import Point
from ECL.point_with_order import PointWOrder

__author__ = 'ivansarno'
__version__ = 'V.5.2'
__version__ = 'V.5.5'
__doc__ = """Diffie-Hellman's public key system.

class: DiffieHellman

exception: DiffieHellmanError
"""

Expand All @@ -39,7 +41,7 @@ class DiffieHellman:
def __init__(self, base_point: PointWOrder, generator: Callable[[int], int]):
"""
:param base_point: Point used as base, can be used a standard point from ECL.std_curves
:param generator: random number generator, return a random int of size passed by parameter
:param generator: random number generator, return a random int of size in bits passed by parameter
"""

self.__point = base_point
Expand All @@ -54,11 +56,13 @@ def step1(self) -> Point:
:return: Point to sand to partner
"""
self.__secret = self.__gen(self.__point.order.bit_length()) % self.__point.order
while self.__secret < sys.maxsize:
self.__secret = self.__gen(self.__point.order.bit_length()) % self.__point.order
self.__sync = True
return self.__point * self.__secret

def step2(self, partner_point: Point) -> Point:
"""Take result of partner step1 and return the key as Point
"""Take result of partner's step1 and return the key as Point

:param partner_point: Point received by partner
:return: the key
Expand All @@ -79,10 +83,6 @@ def key(self) -> Point:
return self.__key


class DiffieHellmanError(EclException):
class DiffieHellmanError(EclError):
"""DiffieHellman algorithm fail."""
def __init__(self, value):
self.value = value

def __str__(self):
return self.value.__repr__()
pass
75 changes: 54 additions & 21 deletions ECL/ecdsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@
"""
import hashlib
from typing import Callable, Tuple

import sys

from ECL.point import Point
from ECL.point_with_order import PointWOrder
from ECL.utility import inverse, EclException
from ECL.utility import inverse, EclError

__author__ = 'ivansarno'
__version__ = 'V.5.2'
__version__ = 'V.5.5'
__doc__ = """ECDSA digital signature algorithm

classes: PrivateKey, PublicKey, Signature
Expand All @@ -31,9 +34,18 @@
"""


def _standard_hash(message: bytearray) -> Tuple[int, int]:
"""Default hash fun, sha512, little endian, unsigned"""
sha = hashlib.sha512()
sha.update(message)
message_hash = int.from_bytes(sha.digest(), byteorder='little', signed=False)
return message_hash, 512


class Signature:
def __init__(self, first: int, second: int):
"""This constructor is for internal use, user must resume a message from a representation string"""
"""This constructor is for internal use, user must resume a message from
a representation string or use deserialization"""
self.__first = first
self.__second = second

Expand All @@ -55,7 +67,7 @@ def __repr__(self):
class PublicKey:
def __init__(self, base_point: PointWOrder, key_point: Point):
"""This constructor is for internal use, user must generates the public key from a PrivateKey object
or resume it from a representation string"""
or resume it from a representation string or use deserialization"""
self.__key = key_point
self.__base = base_point

Expand Down Expand Up @@ -85,12 +97,28 @@ def check(self, message: bytearray, signature: Signature, hash_fun=_standard_has
p = (self.__base * u1) + (self.__key * u2)
return signature.first == p.x % self.__base.order

def try_unlock_key(self, secret: int):
"""Try to recovers the private key associated to this public key using a possible secret number,
return None if fails.

:return: a PrivateKey or None
:param secret: a great positive number, it must be the original secret number
:rtype: PrivateKey
"""
secret %= self.__base.order
if secret < 2:
return None
if self.__base * secret == self.__key:
return PrivateKey(self.__base, secret)
else:
return None


class PrivateKey:
def __init__(self, base_point: PointWOrder, key: int):
def __init__(self, base_point: PointWOrder, secret: int):
"""This constructor is for internal use, user must generates the private key with keygen method
or resume it from a representation string"""
self.__key = key
or resume it from a representation string or use deserialization"""
self.__key = secret
self.__base = base_point

@staticmethod
Expand All @@ -103,10 +131,26 @@ def keygen(base_point: PointWOrder, generator: Callable[[int], int]):
if base_point.order.bit_length() > 512:
raise ECDSAError("bit length of order of base point > 512")
secret = generator(base_point.order.bit_length()) % base_point.order
while secret < 2:
while secret < sys.maxsize:
secret = generator(base_point.order.bit_length()) % base_point.order
return PrivateKey(base_point, secret)

@staticmethod
def keycreate(base_point: PointWOrder, secret: int):
"""Create a PrivateKey from a secret number.

:param secret: secret number, it must be a great positive number
:return: a Private Key
:raise ECDSAError: bit length of order of base point > 512, or key too small
:rtype: PrivateKey
"""
if base_point.order.bit_length() > 512:
raise ECDSAError("bit length of order of base point > 512")
secret %= base_point.order
if secret < sys.maxsize:
raise ECDSAError("the secret number not pass the security tests")
return PrivateKey(base_point, secret)

@property
def public_key(self) -> PublicKey:
return PublicKey(self.__base, self.__base * self.__key)
Expand Down Expand Up @@ -136,18 +180,7 @@ def __repr__(self):
return "ECL.ecdsa.PrivateKey( %s, 0x%x)" % (self.__base.__repr__(), self.__key)


class ECDSAError(EclException):
class ECDSAError(EclError):
"""ECDSAError algorithm fail."""
def __init__(self, value):
self.value = value

def __str__(self):
return self.value.__repr__()
pass


def _standard_hash(message: bytearray) -> Tuple[int, int]:
"""Default hash fun, sha512, little endian, unsigned"""
sha = hashlib.sha512()
sha.update(message)
message_hash = int.from_bytes(sha.digest(), byteorder='little', signed=False)
return message_hash, 512
57 changes: 43 additions & 14 deletions ECL/elgamal.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@
See the License for the specific language governing permissions and
limitations under the License.
"""
from typing import Callable
from typing import Callable, Tuple

import sys

from ECL import koblitz
from ECL.utility import EclException
from ECL.utility import EclError
from ECL.point import Point
from ECL.point_with_order import PointWOrder

__author__ = 'ivansarno'
__version__ = 'V.5.2'
__version__ = 'V.5.5'
__doc__ = """El Gamal's cipher.

classes: ElGamalMessage, PublicKey, PrivateKey
Expand All @@ -34,7 +36,8 @@

class ElGamalMessage:
def __init__(self, first: Point, second: Point, padding: int):
"""This constructor is for internal use, user must resume a message from a representation string"""
"""This constructor is for internal use, user must resume a message from a
representation string or use deserialization"""
self.__first = first
self.__second = second
self.__padding = padding
Expand All @@ -61,7 +64,7 @@ def __repr__(self):
class PublicKey:
def __init__(self, base_point: PointWOrder, key_point: Point):
"""This constructor is for internal use, user must generates the public key from a PrivateKey object
or resume it from a representation string"""
or resume it from a representation string or use deserialization"""
self.__key = key_point
self.__base = base_point

Expand All @@ -74,18 +77,34 @@ def encrypt(self, message: int, generator: Callable[[int], int]) -> ElGamalMessa

message, padding = koblitz.iterative_encode(message, self.__base.curve)
fact = generator(self.__base.order.bit_length()) % self.__base.order
while fact < 2:
while fact < sys.maxsize:
fact = generator(self.__base.order.bit_length()) % self.__base.order
return ElGamalMessage(self.__base * fact, message + self.__key * fact, padding)

def try_unlock_key(self, secret: int):
"""Try to recovers the private key associated to this public key using a possible secret number,
return None if fails.

:return: a PrivateKey or None
:param secret: a great positive number, it must be the original secret number
:rtype: PrivateKey
"""
secret %= self.__base.order
if secret < sys.maxsize:
return None
if self.__base * secret == self.__key:
return PrivateKey(self.__base, secret)
else:
return None

def __repr__(self):
return "ECL.elgamal.PublicKey( %s, %s)" % (self.__base.__repr__(), self.__key.__repr__())


class PrivateKey:
def __init__(self, base_point: PointWOrder, key: int):
"""This constructor is for internal use, user must generates the private key with keygen method
or resume it from a representation string"""
or resume it from a representation string or use deserialization"""
self.__key = key
self.__base = base_point

Expand All @@ -95,10 +114,24 @@ def keygen(base_point: PointWOrder, generator: Callable[[int], int]):
:param generator: random number generator, return a positive integer with bit length passed as parameter
"""
secret = generator(base_point.order.bit_length()) % base_point.order
while secret < 2:
while secret < sys.maxsize:
secret = generator(base_point.order.bit_length()) % base_point.order
return PrivateKey(base_point, secret)

@staticmethod
def keycreate(base_point: PointWOrder, key: int):
"""Create a PrivateKey from a secret number.

:param key: secret number, it must be a great positive number
:return: a Private Key
:raise ElGamalError: bit length of order of base point > 512, or key too small
:rtype: PrivateKey
"""
key %= base_point.order
if key < sys.maxsize:
raise ElGamalError("key, the secret number, not pass the security tests")
return PrivateKey(base_point, key)

@property
def public_key(self) -> PublicKey:
return PublicKey(self.__base, self.__base * self.__key)
Expand All @@ -112,10 +145,6 @@ def __repr__(self):
return "ECL.elgamal.PrivateKey( %s, 0x%x)" % (self.__base.__repr__(), self.__key)


class ElGamalError(EclException):
class ElGamalError(EclError):
"""ElGamal algorithm fail."""
def __init__(self, value):
self.value = value

def __str__(self):
return self.value.__repr__()
pass
16 changes: 6 additions & 10 deletions ECL/koblitz.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
"""
from typing import Tuple
from ECL.curve import Curve
from ECL.utility import is_square, EclException, square_root
from ECL.utility import is_square, EclError, square_root
from ECL.point import Point

__author__ = 'ivansarno'
__version__ = 'V.5.2'
__version__ = 'V.5.5'
__doc__ = """Implementation of Koblitz algorithm.

functions: encode, decode, iterative_encode
Expand All @@ -35,11 +35,11 @@ def encode(message: int, padding: int, curve: Curve) -> Point:

:param curve: Curve of point returned
:return: Point of curve
:raise: KoblitzFailError
:raise KoblitzFailError:

All curves are supported but performances depends on prime number
"""
if message * (padding + 1) < curve.prime:
if message * (padding + 1) < curve.prime and padding > 0:
message *= padding
i = 0
x = message
Expand Down Expand Up @@ -83,10 +83,6 @@ def iterative_encode(message: int, curve: Curve) -> Tuple[Point, int]:
return point, padding


class KoblitzFailError(EclException):
class KoblitzFailError(EclError):
"""Koblitz algorithm fail, point not found."""
def __init__(self, value):
self.value = value

def __str__(self):
return self.value.__repr__()
pass
Loading