Skip to content

Commit 4b10c53

Browse files
authored
Refactor utils (#391)
1 parent 869c83a commit 4b10c53

24 files changed

+336
-243
lines changed

.cspell.jsonc

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"words": [
33
"bitcointalk",
4+
"chacha",
45
"Cipolla",
56
"Codacy",
67
"Codecov",
@@ -14,12 +15,17 @@
1415
"helloworld",
1516
"hexdigest",
1617
"hkdf",
18+
"keccak",
1719
"pycryptodome",
20+
"pytest",
1821
"readablize",
1922
"secp",
2023
"urandom",
2124
"xcfl",
2225
"xchacha"
2326
],
24-
"ignorePaths": [".cspell.jsonc", "LICENSE"]
27+
"ignorePaths": [
28+
".cspell.jsonc",
29+
"LICENSE"
30+
]
2531
}

.github/dependabot.yml

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
version: 2
22
updates:
3-
- package-ecosystem: pip
4-
directory: "/"
5-
schedule:
6-
interval: monthly
7-
open-pull-requests-limit: 10
3+
- package-ecosystem: pip
4+
directory: "/"
5+
schedule:
6+
interval: monthly
7+
open-pull-requests-limit: 3

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Release Notes
22

3+
## 0.4.4
4+
5+
- Make `eth-keys` optional
6+
- Drop Python 3.8
7+
- Refactor `utils`
8+
- Revamp documentation
9+
- Bump dependencies
10+
311
## 0.4.1 ~ 0.4.3
412

513
- Bump dependencies

DETAILS.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,6 @@ Now we have the shared key, and we can use the `nonce` and `tag` to decrypt. Thi
136136
b'helloworld'
137137
```
138138

139-
> Strictly speaking, `nonce` != `iv`, but this is a little bit off topic, if you are curious, you can check [the comment in `utils/symmetric.py`](./ecies/utils/symmetric.py#L79).
139+
> Strictly speaking, `nonce` != `iv`, but this is a little bit off topic, if you are curious, you can check [the comment in `utils/symmetric.py`](./ecies/utils/symmetric.py#L86).
140140
>
141141
> Warning: it's dangerous to reuse nonce, if you don't know what you are doing, just follow the default setting.

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2018-2024 Weiliang Li
3+
Copyright (c) 2018-2025 Weiliang Li
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

+23-21
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,66 @@
11
# eciespy
22

33
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/2a11aeb9939244019d2c64bce3ff3c4e)](https://app.codacy.com/gh/ecies/py/dashboard)
4+
[![License](https://img.shields.io/github/license/ecies/py.svg)](https://github.com/ecies/py)
5+
[![PyPI](https://img.shields.io/pypi/v/eciespy.svg)](https://pypi.org/project/eciespy/)
6+
[![PyPI - Downloads](https://img.shields.io/pypi/dm/eciespy)](https://pypistats.org/packages/eciespy)
7+
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/eciespy.svg)](https://pypi.org/project/eciespy/)
48
[![CI](https://img.shields.io/github/actions/workflow/status/ecies/py/ci.yml?branch=master)](https://github.com/ecies/py/actions)
59
[![Codecov](https://img.shields.io/codecov/c/github/ecies/py.svg)](https://codecov.io/gh/ecies/py)
6-
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/eciespy.svg)](https://pypi.org/project/eciespy/)
7-
[![PyPI](https://img.shields.io/pypi/v/eciespy.svg)](https://pypi.org/project/eciespy/)
8-
[![License](https://img.shields.io/github/license/ecies/py.svg)](https://github.com/ecies/py)
910

1011
Elliptic Curve Integrated Encryption Scheme for secp256k1 in Python.
1112

1213
Other language versions:
1314

14-
- [Rust](https://github.com/ecies/rs)
1515
- [TypeScript](https://github.com/ecies/js)
16+
- [Rust](https://github.com/ecies/rs)
1617
- [Golang](https://github.com/ecies/go)
1718
- [WASM](https://github.com/ecies/rs-wasm)
19+
- [Java](https://github.com/ecies/java)
20+
- [Dart](https://github.com/ecies/dart)
1821

19-
You can also check a FastAPI web backend demo [here](https://github.com/ecies/py-demo).
22+
You can also check a web backend demo [here](https://github.com/ecies/py-demo).
2023

2124
## Install
2225

2326
`pip install eciespy`
2427

28+
Or `pip install 'eciespy[eth]'` to install `eth-keys` as well.
29+
2530
## Quick Start
2631

2732
```python
28-
>>> from ecies.utils import generate_eth_key, generate_key
33+
>>> from ecies.utils import generate_key
2934
>>> from ecies import encrypt, decrypt
30-
>>> eth_k = generate_eth_key()
31-
>>> sk_hex = eth_k.to_hex() # hex string
32-
>>> pk_hex = eth_k.public_key.to_hex() # hex string
33-
>>> data = b'this is a test'
34-
>>> decrypt(sk_hex, encrypt(pk_hex, data))
35-
b'this is a test'
36-
>>> secp_k = generate_key()
37-
>>> sk_bytes = secp_k.secret # bytes
38-
>>> pk_bytes = secp_k.public_key.format(True) # bytes
39-
>>> decrypt(sk_bytes, encrypt(pk_bytes, data))
40-
b'this is a test'
35+
>>> data = 'hello world🌍'.encode()
36+
>>> sk = generate_key()
37+
>>> sk_bytes = sk.secret # bytes
38+
>>> pk_bytes = sk.public_key.format(True) # bytes
39+
>>> decrypt(sk_bytes, encrypt(pk_bytes, data)).decode()
40+
'hello world🌍'
4141
```
4242

4343
Or just use a builtin command `eciespy` in your favorite [command line](#command-line-interface).
4444

4545
## API
4646

47-
### `ecies.encrypt(receiver_pk: Union[str, bytes], msg: bytes) -> bytes`
47+
### `ecies.encrypt(receiver_pk: Union[str, bytes], data: bytes, config: Config = ECIES_CONFIG) -> bytes`
4848

4949
Parameters:
5050

5151
- **receiver_pk** - Receiver's public key (hex str or bytes)
52-
- **msg** - Data to encrypt
52+
- **data** - Data to encrypt
53+
- **config** - Optional configuration object
5354

5455
Returns: **bytes**
5556

56-
### `ecies.decrypt(receiver_sk: Union[str, bytes], msg: bytes) -> bytes`
57+
### `ecies.decrypt(receiver_sk: Union[str, bytes], data: bytes, config: Config = ECIES_CONFIG) -> bytes`
5758

5859
Parameters:
5960

6061
- **receiver_sk** - Receiver's private key (hex str or bytes)
61-
- **msg** - Data to decrypt
62+
- **data** - Data to decrypt
63+
- **config** - Optional configuration object
6264

6365
Returns: **bytes**
6466

ecies/__init__.py

+19-11
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from .config import ECIES_CONFIG, Config
66
from .utils import (
7-
compat_eth_public_key,
7+
bytes2pk,
88
decapsulate,
99
encapsulate,
1010
generate_key,
@@ -18,7 +18,7 @@
1818

1919

2020
def encrypt(
21-
receiver_pk: Union[str, bytes], msg: bytes, config: Config = ECIES_CONFIG
21+
receiver_pk: Union[str, bytes], data: bytes, config: Config = ECIES_CONFIG
2222
) -> bytes:
2323
"""
2424
Encrypt with receiver's secp256k1 public key
@@ -27,8 +27,10 @@ def encrypt(
2727
----------
2828
receiver_pk: Union[str, bytes]
2929
Receiver's public key (hex str or bytes)
30-
msg: bytes
30+
data: bytes
3131
Data to encrypt
32+
config: Config
33+
Optional configuration object
3234
3335
Returns
3436
-------
@@ -38,20 +40,22 @@ def encrypt(
3840
if isinstance(receiver_pk, str):
3941
pk = hex2pk(receiver_pk)
4042
elif isinstance(receiver_pk, bytes):
41-
pk = PublicKey(compat_eth_public_key(receiver_pk))
43+
pk = bytes2pk(receiver_pk)
4244
else:
4345
raise TypeError("Invalid public key type")
4446

4547
ephemeral_sk = generate_key()
4648
ephemeral_pk = ephemeral_sk.public_key.format(config.is_ephemeral_key_compressed)
4749

48-
sym_key = encapsulate(ephemeral_sk, pk, config)
49-
encrypted = sym_encrypt(sym_key, msg, config)
50+
sym_key = encapsulate(ephemeral_sk, pk, config.is_hkdf_key_compressed)
51+
encrypted = sym_encrypt(
52+
sym_key, data, config.symmetric_algorithm, config.symmetric_nonce_length
53+
)
5054
return ephemeral_pk + encrypted
5155

5256

5357
def decrypt(
54-
receiver_sk: Union[str, bytes], msg: bytes, config: Config = ECIES_CONFIG
58+
receiver_sk: Union[str, bytes], data: bytes, config: Config = ECIES_CONFIG
5559
) -> bytes:
5660
"""
5761
Decrypt with receiver's secp256k1 private key
@@ -60,8 +64,10 @@ def decrypt(
6064
----------
6165
receiver_sk: Union[str, bytes]
6266
Receiver's private key (hex str or bytes)
63-
msg: bytes
67+
data: bytes
6468
Data to decrypt
69+
config: Config
70+
Optional configuration object
6571
6672
Returns
6773
-------
@@ -76,7 +82,9 @@ def decrypt(
7682
raise TypeError("Invalid secret key type")
7783

7884
key_size = config.ephemeral_key_size
79-
ephemeral_pk, encrypted = PublicKey(msg[0:key_size]), msg[key_size:]
85+
ephemeral_pk, encrypted = PublicKey(data[0:key_size]), data[key_size:]
8086

81-
sym_key = decapsulate(ephemeral_pk, sk, config)
82-
return sym_decrypt(sym_key, encrypted, config)
87+
sym_key = decapsulate(ephemeral_pk, sk, config.is_hkdf_key_compressed)
88+
return sym_decrypt(
89+
sym_key, encrypted, config.symmetric_algorithm, config.symmetric_nonce_length
90+
)

ecies/__main__.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import sys
1515

1616
from ecies import decrypt, encrypt
17-
from ecies.utils import generate_eth_key
17+
from ecies.utils import generate_key, to_eth_address, to_eth_public_key
1818

1919
__description__ = "Elliptic Curve Integrated Encryption Scheme for secp256k1 in Python"
2020

@@ -68,11 +68,11 @@ def main():
6868

6969
args = parser.parse_args()
7070
if args.generate:
71-
k = generate_eth_key()
71+
k = generate_key()
7272
sk, pk, addr = (
7373
k.to_hex(),
74-
k.public_key.to_hex(),
75-
k.public_key.to_checksum_address(),
74+
f"0x{to_eth_public_key(k.public_key).hex()}",
75+
to_eth_address(k.public_key),
7676
)
7777
print("Private: {}\nPublic: {}\nAddress: {}".format(sk, pk, addr))
7878
return

ecies/utils/__init__.py

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
1-
from .elliptic import (
2-
compat_eth_public_key,
3-
decapsulate,
4-
encapsulate,
5-
generate_eth_key,
6-
generate_key,
7-
hex2pk,
8-
hex2sk,
9-
)
10-
from .hex import decode_hex, sha256
1+
from .elliptic import bytes2pk, decapsulate, encapsulate, generate_key, hex2pk, hex2sk
2+
from .eth import generate_eth_key, to_eth_address, to_eth_public_key
3+
from .hash import derive_key, sha256
4+
from .hex import decode_hex
115
from .symmetric import sym_decrypt, sym_encrypt
126

137
__all__ = [
14-
"sha256",
15-
"decode_hex",
168
"sym_encrypt",
179
"sym_decrypt",
1810
"generate_key",
19-
"generate_eth_key",
2011
"hex2sk",
2112
"hex2pk",
13+
"bytes2pk",
2214
"decapsulate",
2315
"encapsulate",
24-
"compat_eth_public_key",
16+
# eth
17+
"generate_eth_key",
18+
"to_eth_address",
19+
"to_eth_public_key",
20+
# hex
21+
"decode_hex",
22+
# hash
23+
"sha256",
24+
"derive_key",
2525
]

0 commit comments

Comments
 (0)