Skip to content

Commit

Permalink
Merge pull request #21 from isakruas/feature/update-dependencies-and-…
Browse files Browse the repository at this point in the history
…cache-config

Feature/update dependencies and cache config
  • Loading branch information
isakruas authored Oct 4, 2024
2 parents 41628d3 + 024939f commit d4cc871
Show file tree
Hide file tree
Showing 18 changed files with 294 additions and 43 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml → .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ jobs:
pip install -r requirements-tests.txt
pip install pytest pytest-cov
- name: Export environment variable
run: echo "LRU_CACHE_MAXSIZE=0" >> $GITHUB_ENV

- name: Run tests with coverage
env:
LRU_CACHE_MAXSIZE: ${{ env.LRU_CACHE_MAXSIZE }}
run: pytest --cov tests

- name: Upload coverage reports to Codecov
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ on:
pull_request:
branches:
- master
types:
- closed

jobs:
build:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest

steps:
Expand Down Expand Up @@ -39,4 +42,4 @@ jobs:
permissions:
id-token: write
contents: read
contents: read
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [v1.1.2] - 2024-10-03

### Changed
- Updated test and documentation dependencies, expanded test coverage for the code, and added the ability to configure LRU cache size via an environment variable.

## [v1.1.1] - 2024-09-30

### Security
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ It's essential that your contributions are well-tested:

```bash
pytest --cov=ecutils tests/
pytest --cov=ecutils --cov-report=html tests/
```

Ensure that your contributions pass all tests and that the overall test coverage isn’t compromised.
Expand Down
1 change: 1 addition & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Use this section to tell people about which versions of your project are current

| Version | Supported |
| ------- | ------------------ |
| 1.1.2 | :white_check_mark: |
| 1.1.1 | :white_check_mark: |
| 1.1.0 | :white_check_mark: |
| 1.0.0 | :white_check_mark: |
Expand Down
7 changes: 3 additions & 4 deletions requirements-docs.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
mkdocs==1.5.3
mkdocs-material==9.5.1
mkdocs==1.6.1
mkdocs-material==9.5.39
mkdocs-material-extensions==1.3.1
mkdocs-minify-plugin==0.7.1
zipp>=3.19.1 # not directly required, pinned by Snyk to avoid a vulnerability
mkdocs-minify-plugin==0.8.0
7 changes: 3 additions & 4 deletions requirements-tests.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
coverage==7.3.2
pytest==7.4.3
pytest-cov==4.1.0
zipp>=3.19.1 # not directly required, pinned by Snyk to avoid a vulnerability
coverage==7.6.1
pytest==8.3.3
pytest-cov==5.0.0
2 changes: 1 addition & 1 deletion src/ecutils/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.1.1"
__version__ = "1.1.2"
15 changes: 8 additions & 7 deletions src/ecutils/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from ecutils.core import EllipticCurve, Point
from ecutils.curves import get as get_curve
from ecutils.settings import LRU_CACHE_MAXSIZE


@dataclass(frozen=True)
Expand All @@ -22,7 +23,7 @@ class Koblitz:
curve_name: str = "secp521r1"

@property
@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def curve(self) -> EllipticCurve:
"""Retrieves the elliptic curve associated with this `Koblitz` instance.
Expand All @@ -34,7 +35,7 @@ def curve(self) -> EllipticCurve:
"""
return get_curve(self.curve_name)

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def encode(
self, message: str, alphabet_size: int = 2**8, lengthy=False
) -> Union[Tuple[Tuple[Point, int]], Tuple[Point, int]]:
Expand Down Expand Up @@ -108,7 +109,7 @@ def encode(

return tuple(encoded_messages)

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def decode(
self,
encoded: Union[Point, tuple[Tuple[Point, int]]],
Expand Down Expand Up @@ -200,7 +201,7 @@ class DigitalSignature:
curve_name: str = "secp192k1"

@property
@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def curve(self) -> EllipticCurve:
"""Retrieves the elliptic curve associated with this `DigitalSignature` instance.
Expand All @@ -214,7 +215,7 @@ def curve(self) -> EllipticCurve:
return get_curve(self.curve_name)

@property
@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def public_key(self) -> Point:
"""Computes and returns the public key corresponding to the private key.
Expand All @@ -230,7 +231,7 @@ def public_key(self) -> Point:
"""
return self.curve.multiply_point(self.private_key, self.curve.G)

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def generate_signature(self, message_hash: int) -> Tuple[int, int]:
"""Generates an ECDSA signature for a given message hash using the private key.
Expand Down Expand Up @@ -261,7 +262,7 @@ def generate_signature(self, message_hash: int) -> Tuple[int, int]:
) % self.curve.n
return r, s

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def verify_signature(
self, public_key: Point, message_hash: int, r: int, s: int
) -> bool:
Expand Down
29 changes: 16 additions & 13 deletions src/ecutils/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from functools import lru_cache
from typing import Optional

from ecutils.settings import LRU_CACHE_MAXSIZE


@dataclass(frozen=True)
class Point:
Expand Down Expand Up @@ -36,7 +38,7 @@ class EllipticCurveOperations:

use_projective_coordinates: bool = True

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def add_points(self, p1: Point, p2: Point) -> Point:
"""Add two points on an elliptic curve.
Expand Down Expand Up @@ -81,7 +83,7 @@ def add_points(self, p1: Point, p2: Point) -> Point:
y_3 = (s * (p1.x - x_3) - p1.y) % self.p
return Point(x_3, y_3)

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def double_point(self, p: Point) -> Point:
"""Double a point on an elliptic curve."""
if p.x is None or p.y is None:
Expand All @@ -94,16 +96,17 @@ def double_point(self, p: Point) -> Point:

n = (3 * p.x**2 + self.a) % self.p
d = (2 * p.y) % self.p
try:
inv = pow(d, -1, self.p)
except ValueError:
return Point() # Point at infinity
# try:
# inv = pow(d, -1, self.p)
# except ValueError:
# return Point() # Point at infinity
inv = pow(d, -1, self.p)
s = (n * inv) % self.p
x_3 = (s**2 - p.x - p.x) % self.p
y_3 = (s * (p.x - x_3) - p.y) % self.p
return Point(x_3, y_3)

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def multiply_point(self, k: int, p: Point) -> Point:
"""Multiply a point on an elliptic curve by an integer scalar.
Expand Down Expand Up @@ -154,7 +157,7 @@ def multiply_point(self, k: int, p: Point) -> Point:
r = self.add_points(r, p)
return r

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def jacobian_add_points(
self, p1: JacobianPoint, p2: JacobianPoint
) -> JacobianPoint:
Expand Down Expand Up @@ -187,7 +190,7 @@ def jacobian_add_points(

return JacobianPoint(x, y, z)

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def jacobian_double_point(self, p: JacobianPoint) -> JacobianPoint:
"""Double a point on an elliptic curve using Jacobian coordinates."""
if p.x is None or p.y is None:
Expand All @@ -206,7 +209,7 @@ def jacobian_double_point(self, p: JacobianPoint) -> JacobianPoint:

return JacobianPoint(nx, ny, nz)

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def jacobian_multiply_point(self, k: int, p: JacobianPoint) -> JacobianPoint:
"""Multiply a point on an elliptic curve by an integer scalar using repeated addition."""
if k == 0 or p.x is None or p.y is None:
Expand All @@ -222,7 +225,7 @@ def jacobian_multiply_point(self, k: int, p: JacobianPoint) -> JacobianPoint:
return result

@staticmethod
@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def to_jacobian(point: Point) -> JacobianPoint:
"""Converts a point from affine coordinates to Jacobian coordinates.
Expand All @@ -236,7 +239,7 @@ def to_jacobian(point: Point) -> JacobianPoint:
return JacobianPoint()
return JacobianPoint(point.x, point.y, 1)

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def to_affine(self, point: JacobianPoint) -> Point:
"""Converts a point from Jacobian coordinates to affine coordinates.
Expand All @@ -251,7 +254,7 @@ def to_affine(self, point: JacobianPoint) -> Point:
inv_z = pow(point.z, -1, self.p)
return Point((point.x * inv_z**2) % self.p, (point.y * inv_z**3) % self.p)

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def is_point_on_curve(self, p: Point) -> bool:
"""Check if a point lies on the elliptic curve.
Expand Down
3 changes: 2 additions & 1 deletion src/ecutils/curves.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from functools import lru_cache

from ecutils.core import EllipticCurve, Point
from ecutils.settings import LRU_CACHE_MAXSIZE

secp192k1 = EllipticCurve(
p=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37,
Expand Down Expand Up @@ -101,7 +102,7 @@
)


@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def get(name) -> EllipticCurve:
"""Retrieve an EllipticCurve instance by its standard name.
Expand Down
17 changes: 9 additions & 8 deletions src/ecutils/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from ecutils.core import EllipticCurve, Point
from ecutils.curves import get as get_curve
from ecutils.settings import LRU_CACHE_MAXSIZE


@dataclass(frozen=True)
Expand All @@ -18,7 +19,7 @@ class DiffieHellman:
curve_name: str = "secp192k1"

@property
@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def curve(self) -> EllipticCurve:
"""Retrieves the elliptic curve associated with this `DiffieHellman` instance.
Expand All @@ -32,7 +33,7 @@ def curve(self) -> EllipticCurve:
return get_curve(self.curve_name)

@property
@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def public_key(self) -> Point:
"""Computes and returns the public key corresponding to the private key.
Expand All @@ -48,7 +49,7 @@ def public_key(self) -> Point:
"""
return self.curve.multiply_point(self.private_key, self.curve.G)

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def compute_shared_secret(self, other_public_key: Point) -> Point:
"""Computes the shared secret using the private key and the other party's public key.
Expand All @@ -75,7 +76,7 @@ class MasseyOmura:
curve_name: str = "secp192k1"

@property
@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def curve(self) -> EllipticCurve:
"""Retrieves the elliptic curve associated with this `MasseyOmura` instance.
Expand All @@ -89,7 +90,7 @@ def curve(self) -> EllipticCurve:
return get_curve(self.curve_name)

@property
@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def public_key(self) -> Point:
"""Computes and returns the public key corresponding to the private key.
Expand All @@ -105,19 +106,19 @@ def public_key(self) -> Point:
"""
return self.curve.multiply_point(self.private_key, self.curve.G)

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def first_encryption_step(self, message: Point) -> Point:
"""Encrypts the message with the sender's private key."""

return self.curve.multiply_point(self.private_key, message)

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def second_encryption_step(self, received_encrypted_message: Point) -> Point:
"""Applies the receiver's private key on the received encrypted message."""

return self.first_encryption_step(received_encrypted_message)

@lru_cache(maxsize=1024, typed=True)
@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def partial_decryption_step(self, encrypted_message: Point) -> Point:
"""Partial decryption using the inverse of the sender's private key."""

Expand Down
4 changes: 4 additions & 0 deletions src/ecutils/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import os

# Default value for LRU cache maxsize
LRU_CACHE_MAXSIZE = os.environ.get("LRU_CACHE_MAXSIZE", 1024)
4 changes: 3 additions & 1 deletion src/ecutils/utils.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import hashlib
from functools import lru_cache

from ecutils.settings import LRU_CACHE_MAXSIZE

@lru_cache(maxsize=1024, typed=True)

@lru_cache(maxsize=LRU_CACHE_MAXSIZE, typed=True)
def calculate_file_hash(file_name: str, block_size: int = 16384) -> int:
"""Calculates the SHA-256 hash of a file efficiently.
Expand Down
Loading

0 comments on commit d4cc871

Please sign in to comment.