Python Library for Elliptic Curve Cryptography: key exchanges (Diffie-Hellman, Massey-Omura), ECDSA signatures, and Koblitz encoding. Suitable for crypto education and secure systems.
Project description
ecutils
Python Library for Elliptic Curve Cryptography: key exchanges (Diffie-Hellman, Massey-Omura), ECDSA signatures, and Koblitz encoding. Suitable for crypto education and secure systems.
Installation
pip install ecutils
Quick start
from ecutils import Point, get_curve, get_generator
curve = get_curve("secp256k1")
G = get_generator("secp256k1")
# Private key → public key
private_key = 0xDEADBEEFCAFE
public_key = private_key * G
print(public_key) # Point(x=..., y=...)
print(public_key.is_on_curve()) # True
Features
Core
Arithmetic operations on elliptic curves y² = x³ + ax + b (mod p) with two internal coordinate systems.
from ecutils import Point, CurveParams, CoordinateSystem
# Jacobian (default — faster)
curve = CurveParams(p=23, a=1, b=1, n=28, h=1)
# Affine (explicit)
curve = CurveParams(p=23, a=1, b=1, n=28, h=1, coord=CoordinateSystem.AFFINE)
P = Point(0, 1, curve)
Q = Point(6, 19, curve)
P + Q # addition
P - Q # subtraction
-P # negation (additive inverse)
5 * P # scalar multiplication
P * 5 # scalar multiplication (commutative)
P == Q # equality
Curves are validated automatically — singular curves (4a³ + 27b² ≡ 0 mod p) are rejected:
CurveParams(p=23, a=0, b=0, n=1) # ❌ ValueError: singular curve
Points are validated on construction:
Point(0, 1, curve) # ✅ valid
Point(0, 5, curve) # ❌ ValueError: not on the curve
Point(curve=curve) # ✅ point at infinity (identity)
Point compression and decompression:
x, parity = P.compress() # (x, y_parity)
recovered = Point.decompress(x, parity, curve) # full point
assert recovered == P
Pre-defined curves
from ecutils import get_curve, get_generator
curve = get_curve("secp256k1")
G = get_generator("secp256k1")
Available curves: secp192k1, secp192r1, secp224k1, secp224r1, secp256k1, secp256r1, secp384r1, secp521r1.
Protocols
Diffie-Hellman (ECDH)
Key exchange between two parties.
from ecutils import DiffieHellman
alice = DiffieHellman(private_key=0xA1, curve_name="secp256k1")
bob = DiffieHellman(private_key=0xB2, curve_name="secp256k1")
# Each party shares their public key
shared_alice = alice.compute_shared_secret(bob.public_key)
shared_bob = bob.compute_shared_secret(alice.public_key)
assert shared_alice == shared_bob # same shared secret
Massey-Omura
Three-pass protocol — no prior public key exchange required.
from ecutils import MasseyOmura, Koblitz
# Encode message as a curve point
kob = Koblitz(curve_name="secp521r1")
M, j = kob.encode("secret message")
alice = MasseyOmura(private_key=0xA1, curve_name="secp521r1")
bob = MasseyOmura(private_key=0xB2, curve_name="secp521r1")
# Three passes
c1 = alice.encrypt(M) # Alice → Bob
c2 = bob.encrypt(c1) # Bob → Alice
c3 = alice.decrypt(c2) # Alice → Bob
plaintext = bob.decrypt(c3) # Bob recovers M
assert kob.decode(plaintext, j) == "secret message"
Algorithms
Digital Signature (ECDSA)
from ecutils import DigitalSignature
signer = DigitalSignature(private_key=123456789, curve_name="secp256k1")
# Sign (SHA-256 hashing is done automatically)
r, s = signer.sign_message(b"hello")
# Verify
assert signer.verify_message(signer.public_key, b"hello", r, s)
For manual hashing, use sign(message_hash) and verify(pub, message_hash, r, s) directly.
Koblitz (message encoding)
Encode text as curve points and decode back.
from ecutils import Koblitz
kob = Koblitz(curve_name="secp521r1")
point, j = kob.encode("Hello, world!")
text = kob.decode(point, j)
assert text == "Hello, world!"
Project structure
ecutils/
├── __init__.py # Public API
├── py.typed # PEP 561 — type checker support
├── core/
│ ├── curve.py # CurveParams, CoordinateSystem
│ ├── point.py # Point
│ └── arithmetic/
│ ├── affine.py # affine coordinate arithmetic
│ └── jacobian.py # Jacobian coordinate arithmetic
├── curves/
│ └── registry.py # pre-defined curves, get_curve(), get_generator()
├── protocols/
│ ├── diffie_hellman.py # DiffieHellman
│ └── massey_omura.py # MasseyOmura
├── algorithms/
│ ├── digital_signature.py # DigitalSignature (ECDSA)
│ └── koblitz.py # Koblitz
└── utils/
├── settings.py # global settings
└── math.py # quadratic residue, modular square root
Contributing
Contributions are welcome! Please read our contributing guidelines to get started.
License
This project is licensed under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ecutils-2.0.0.tar.gz.
File metadata
- Download URL: ecutils-2.0.0.tar.gz
- Upload date:
- Size: 57.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
419befb4db6f1c890b63aba75d39dbc820a67a7424ebdff2090a205379522517
|
|
| MD5 |
77aadaabc9d461dc65db943137827eed
|
|
| BLAKE2b-256 |
c1a2c0aeed72e1dd2b32a0d15ebffb32bc85d0209701b27a36e66524ce64d8a9
|
File details
Details for the file ecutils-2.0.0-py3-none-any.whl.
File metadata
- Download URL: ecutils-2.0.0-py3-none-any.whl
- Upload date:
- Size: 24.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1780372fde099f9438fbc25b4fa8429c2b697f4702d2ae99b2e47f680953f190
|
|
| MD5 |
9acce951dba1757a384bbcc681f816c1
|
|
| BLAKE2b-256 |
203df41ab27c147d2ec800d45287e9cb9db140e6ee0c11b178bc9e22cf205269
|