Skip to content

Commit daa61e1

Browse files
authored
Merge pull request #36 from lc6chang/2.0.0
Release 2.0.0 version
2 parents fc22df2 + c6e1559 commit daa61e1

File tree

16 files changed

+487
-515
lines changed

16 files changed

+487
-515
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
1-
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2-
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
3-
41
name: Lint, Type Check, and Unittest
52

63
on:
7-
push:
8-
branches: [ master ]
9-
pull_request:
10-
branches: [ master ]
4+
push
115

126
jobs:
137
build:

README.md

Lines changed: 56 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
# ecc-pycrypto
2-
This is a Python package for ECC and ElGamal elliptic curve encryption.
2+
This Python package provides easy-to-understand implementations of ECC (Elliptic Curve Cryptography) and ElGamal elliptic curve encryption.
33

44
## Introduction
55

6-
+ [ElGamal encryption](https://en.wikipedia.org/wiki/ElGamal_encryption) is a public-key cryptosystem. It uses asymmetric key encryption for communicating between two parties and encrypting the message.
6+
+ [Elliptic-curve cryptography (ECC)](https://en.wikipedia.org/wiki/Elliptic_curve_cryptography) is a form of public-key cryptography based on the algebraic structure of elliptic curves over finite fields.
7+
+ [SafeCurves](https://safecurves.cr.yp.to/) provides a list of safe elliptic curves.
8+
+ The three common types of elliptic curves are: [Weierstrass Curve](https://en.wikipedia.org/wiki/Elliptic_curve), [Montgomery Curve](https://en.wikipedia.org/wiki/Montgomery_curve) and [Twisted Edwards Curve](https://en.wikipedia.org/wiki/Twisted_Edwards_curve).
79

8-
+ [Elliptic-curve cryptography (ECC)](https://en.wikipedia.org/wiki/Elliptic_curve_cryptography) is an approach to public-key cryptography based on the algebraic structure of elliptic curves over finite fields.
9-
+ [SafeCurves](https://safecurves.cr.yp.to/) shows us the safety Elliptic curve.
10-
+ There are three typical curves: [Weierstrass Curve](https://en.wikipedia.org/wiki/Elliptic_curve), [Montgomery Curve](https://en.wikipedia.org/wiki/Montgomery_curve) and [Twisted Edwards Curve](https://en.wikipedia.org/wiki/Twisted_Edwards_curve).
11-
12-
+ For ElGamal elliptic curve crypto, please refer to [Architectural Evaluation of Algorithms RSA, ECC and MQQ in Arm Processors](https://www.researchgate.net/publication/269672660_Architectural_Evaluation_of_Algorithms_RSA_ECC_and_MQQ_in_Arm_Processors).
10+
+ [ElGamal encryption](https://en.wikipedia.org/wiki/ElGamal_encryption) is a public-key cryptosystem that enables secure communication between two parties. The ElGamal elliptic curve variant can be explored further in the paper [Architectural Evaluation of Algorithms RSA, ECC and MQQ in Arm Processors](https://www.researchgate.net/publication/269672660_Architectural_Evaluation_of_Algorithms_RSA_ECC_and_MQQ_in_Arm_Processors).
1311

1412
## Warning
1513

16-
This project only aims to help you learn and understand what is ECC and how the algorithm works. **Do not use it directly in the production environment!**
14+
This project is intended as an educational tool to help you learn and understand the concepts of ECC and how the algorithm works. **Do not use it in production environments!**
1715

18-
Some cons: The operations of curve points are just implemented in a common way. We don't implement them using [Jacobian Coordinates](https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates). Also, we implement them in pure Python. It will be slower than C.
1916

2017
## Installation
2118

@@ -25,70 +22,68 @@ $ cd ecc-pycrypto
2522
$ pip3 install .
2623
```
2724

28-
## Test
25+
or
2926

3027
```bash
31-
$ python3 -m unittest discover tests
28+
$ pip3 install git+https://github.com/lc6chang/ecc-pycrypto.git
3229
```
3330

3431
## Usages
3532

36-
### ElGamal elliptic curve encryption and decryption
33+
### Elliptic curve operations
3734

3835
```python
39-
from ecc.curve import Curve25519
40-
from ecc.key import gen_keypair
41-
from ecc.cipher import ElGamal
42-
43-
44-
# Plaintext
45-
plaintext = b"I am plaintext."
46-
# Generate key pair
47-
pri_key, pub_key = gen_keypair(Curve25519)
48-
# Encrypt using ElGamal algorithm
49-
cipher_elg = ElGamal(Curve25519)
50-
C1, C2 = cipher_elg.encrypt(plaintext, pub_key)
51-
# Decrypt
52-
new_plaintext = cipher_elg.decrypt(pri_key, C1, C2)
53-
54-
print(new_plaintext == plaintext)
55-
# >> True
36+
from ecc import curve, registry
37+
38+
# Choose a curve from registry
39+
P256 = registry.P256
40+
# Define a point on the curve
41+
P = curve.AffinePoint(
42+
curve=P256,
43+
x=0x9d8b7f25322574b60f9914b240d79bf35ba7284d0c93a0b76acac49b931cbde6,
44+
y=0x2aae8628ed337a97cecead2e61d0c188a979a4d1383382a3696b29b449072069,
45+
)
46+
# The base point
47+
G = P256.G # AffinePoint(curve=P256, x=484395..., y=361342...)
48+
# The neutral point
49+
O = P256.O # InfinityPoint(curve=P256)
50+
# Operations
51+
assert P + O == P
52+
assert P - P == O
53+
assert 100 * O == O
54+
assert P + P == 2 * P
55+
print(20 * P - 5 * G) # >>> AffinePoint(curve=P256, x=280875..., y=737429...)
56+
# Define a custom curve
57+
MY_CURVE = curve.ShortWeierstrassCurve(
58+
name="MY_CURVE",
59+
a=...,
60+
b=...,
61+
p=...,
62+
n=...,
63+
G_x=...,
64+
G_y=...,
65+
)
5666
```
5767

58-
## Common elliptic curve
5968

60-
```python
61-
from ecc.curve import P256, Point
62-
63-
# Common point
64-
P = Point(0x9d8b7f25322574b60f9914b240d79bf35ba7284d0c93a0b76acac49b931cbde6,
65-
0x2aae8628ed337a97cecead2e61d0c188a979a4d1383382a3696b29b449072069,
66-
P256)
67-
# Base point
68-
G = P256.G
69-
# Point at infinity
70-
INF = P256.INF
71-
72-
assert P + INF == P
73-
assert G - G == INF
74-
assert 100 * INF == INF
75-
76-
print(P + G)
77-
print(20 * P - 5 * G)
78-
```
69+
### ElGamal elliptic curve encryption
7970

8071
```python
81-
from ecc.curve import ShortWeierstrassCurve
82-
83-
# You could also write your own Curve
84-
YOUR_CURVE = ShortWeierstrassCurve(
85-
name=CURVE_NAME,
86-
a=A,
87-
b=B,
88-
p=P,
89-
n=N,
90-
G_x=G_X,
91-
G_y=G_Y
92-
)
72+
from ecc import curve, registry, key, cipher
73+
74+
# Plaintext bytes
75+
plaintext_bytes = b"I am plaintext."
76+
# Generate a key pair
77+
pri_key, pub_key = key.gen_key_pair(registry.Curve25519)
78+
# Encode plaintext bytes into a point on the curve
79+
plaintext_point = curve.encode(plaintext_bytes, registry.Curve25519)
80+
# Encrypt using ElGamal algorithm
81+
C1, C2 = cipher.elgamal_encrypt(plaintext_point, pub_key)
82+
# Decrypt
83+
plaintext_point_decrypted = cipher.elgamal_decrypt(pri_key, C1, C2)
84+
# Decode the decrypted point back to plaintext bytes
85+
plaintext_bytes_decrypted = curve.decode(plaintext_point_decrypted)
86+
# Verify
87+
assert plaintext_bytes_decrypted == plaintext_bytes
9388
```
9489

ecc/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +0,0 @@
1-
# We shouldn't do versioning. We should roll.
2-
__version__ = "1.0.0" # noqa

ecc/cipher.py

Lines changed: 24 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,31 @@
1-
import random
2-
from os import urandom
3-
from typing import Callable, Tuple
4-
from dataclasses import dataclass
1+
import os
2+
import typing
53

6-
from ecc.curve import Curve, Point
4+
from ecc import curve
5+
from ecc import utils
76

87

9-
@dataclass
10-
class ElGamal:
11-
curve: Curve
8+
def elgamal_encrypt(
9+
plaintext: curve.Point,
10+
public_key: curve.Point,
11+
rand_func: typing.Callable[[int], bytes] | None = None,
12+
) -> tuple[curve.Point, curve.Point]:
13+
rand_func = rand_func or os.urandom
14+
curve_ = public_key.curve
1215

13-
def encrypt(self, plaintext: bytes, public_key: Point,
14-
randfunc: Callable | None = None) -> Tuple[Point, Point]:
15-
return self.encrypt_bytes(plaintext, public_key, randfunc)
16+
G = curve_.G # Base point G
17+
M = plaintext
18+
k = utils.random_int_exclusive(curve_.n, rand_func)
1619

17-
def decrypt(self, private_key: int, C1: Point, C2: Point) -> bytes:
18-
return self.decrypt_bytes(private_key, C1, C2)
20+
C1 = k * G
21+
C2 = M + k * public_key
22+
return C1, C2
1923

20-
def encrypt_bytes(self, plaintext: bytes, public_key: Point,
21-
randfunc: Callable | None = None) -> Tuple[Point, Point]:
22-
# Encode plaintext into a curve point
23-
M = self.curve.encode_point(plaintext)
24-
return self.encrypt_point(M, public_key, randfunc)
2524

26-
def decrypt_bytes(self, private_key: int, C1: Point, C2: Point) -> bytes:
27-
M = self.decrypt_point(private_key, C1, C2)
28-
return self.curve.decode_point(M)
29-
30-
def encrypt_point(self, plaintext: Point, public_key: Point,
31-
randfunc: Callable | None = None) -> Tuple[Point, Point]:
32-
randfunc = randfunc or urandom
33-
# Base point G
34-
G = self.curve.G
35-
M = plaintext
36-
37-
random.seed(randfunc(1024))
38-
k = random.randint(1, self.curve.n)
39-
40-
C1 = k * G
41-
C2 = M + k * public_key
42-
return C1, C2
43-
44-
def decrypt_point(self, private_key: int, C1: Point, C2: Point) -> Point:
45-
M = C2 + (self.curve.n - private_key) * C1
46-
return M
25+
def elgamal_decrypt(
26+
private_key: int,
27+
C1: curve.Point,
28+
C2: curve.Point,
29+
) -> curve.Point:
30+
M = C2 + (C1.curve.n - private_key) * C1
31+
return M

0 commit comments

Comments
 (0)