Source code for mini_cryptography.ecdsa

""" ECDSA file info.
The following script allows users to perform ECC (Elliptic Curve Cryptography)
arithmetic operations, including ECDSA (Elliptic Curve Digital Signature Algorithm)
signature formation and verification.

Pre-requisite :
tiny.ec package to be installed within the Python runtime environment
"""
import random
from tinyec import ec

[docs]class Point: """ A class used to represent an ECC (Elliptic Curve Cryptography) point """ def __init__(self, x:int, y:int): """ Args: x (int): Point coordinate x y (int): Point coordinate y """ self.x = x self.y = y
[docs] def to_array(self): """ Returns point x, y coordinates as array Returns: list[int]: Array of coordinates x, y """ return [self.x, self.y]
def __eq__(self, other): """ Compares two Point class objects Args: other (Point): Other Point class object Returns: bool: Are two objects equal """ if isinstance(other, Point): return (self.x, self.y) == (other.x, other.y) return NotImplemented
[docs]class Field: """ A class used to represent an ECC finite field """ def __init__(self, a:int, b:int, n:int, p:int, G:Point): """ Args: a (int): elliptic curve parameter (equal to q-3 for P-256) b (int): elliptic curve parameter n (int): the order of the base point G p (int): the size of the underlying field G (Point): (xG, y G), a point on the curve, known as the base point """ self.a = a self.b = b self.n = n self.p = p self.g = G.to_array()
[docs]class Ecdsa: """ A class used to do ECC arithmetic operations and ECDSA (Elliptic Curve Digital Signature Algorithm) signature formation and verification """ def __init__(self, field:Field, name:str): """ Args: field (Field): Curve field name (str): Curve name """ self.curve = ec.Curve(a=field.a, b=field.b, field=field, name=name) self.field = field
[docs] def getName(self): """ Returns ECDSA curve name Returns: str: ECDS curve name """ return self.curve.name
[docs] def G_multiplication(self, multiplyer:int): """Multiplies G point from the given multiplier Args: multiplyer (int): Given point multipliers Returns: Point: A new point after multiplication """ newPoint = self.curve.g * multiplyer return Point(newPoint.x, newPoint.y)
[docs] def calculate_public_key(self, private_key:int): """Calculate the public key Args: private_key (int): private key value Returns: Point: A public key """ return self.G_multiplication(private_key)
[docs] def sum_points(self, point1:Point, point2:Point): """ Points sum Args: point1 (Point): First point point2 (Point): Second point Returns: Point: A new point that is the sum of the first and second points """ point1 = ec.Point(curve=self.curve, x=point1.x, y=point1.y) point2 = ec.Point(curve=self.curve, x=point2.x, y=point2.y) newPoint = point1 + point2 return Point(newPoint.x, newPoint.y)
[docs] def multiply_points(self, point:Point, multiplyer:int): """Point multiplication from a given multiplier Args: point (Point): Curve point multiplyer (int): Given point multiplier Returns: Point: A new point after multiplication """ point = ec.Point(curve=self.curve, x=point.x, y=point.y) newPoint = point * multiplyer return Point(newPoint.x, newPoint.y)
[docs] def generate_random_number(self, lower:int, upper:int): """Generates random number [lower, ... upper range] Args: lower (int): lower is the lower limit of the range upper (int): upper is the upper limit of the range Returns: int: generated number """ return random.randint(1, self.field.n-1)
[docs] def k_generator(self): """Generates random k [1, ... n-1] Returns: int: random number k """ return self.generate_random_number(1, self.field.n-1)
[docs] def private_key_generator(self): """Generates random x [1, ... n-1] Returns: int: private key x """ return self.generate_random_number(1, self.field.n-1)
[docs] def sign_message(self, private_key:int, k:int, hash:str): """Create a signature for the given message. Args: private_key (int): private key value k (int): random number k hash (str): message hash value Returns: int, int: e. signature component values r, s bool: 0 if wrong r or 1 if wrong s """ k_Gx = self.G_multiplication(k).x r = k_Gx % self.field.n if r == 0: return 0 s = (pow(k, -1, self.field.n) * (hash + private_key * r)) % self.field.n if s == 0: return 1 return r, s
[docs] def verify_signature(self, r:int, s:int, hash:str, public_key:Point): """Verifies signature validity Args: r (int): Signature component r s (int): Signature component s hash (str): Message hash public_key (Point): Public key Returns: bool: Verification result """ if (s > self.field.n-1 or r > self.field.n-1 or s < 1 or r < 1): #[1, n – 1] return False w = pow(s, -1, self.field.n) u1 = (hash * w) % self.field.n u2 = (r * w) % self.field.n x2 = self.sum_points(self.G_multiplication(u1), self.multiply_points(public_key, u2)).x v = x2 % self.field.n if r == v: return True return False