Skip to content

Commit d7050f9

Browse files
authored
Add consts (#394)
1 parent 4b10c53 commit d7050f9

File tree

8 files changed

+56
-41
lines changed

8 files changed

+56
-41
lines changed

README.md

+4-5
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Or just use a builtin command `eciespy` in your favorite [command line](#command
4848

4949
Parameters:
5050

51-
- **receiver_pk** - Receiver's public key (hex str or bytes)
51+
- **receiver_pk** - Receiver's public key (hex `str` or `bytes`)
5252
- **data** - Data to encrypt
5353
- **config** - Optional configuration object
5454

@@ -58,7 +58,7 @@ Returns: **bytes**
5858

5959
Parameters:
6060

61-
- **receiver_sk** - Receiver's private key (hex str or bytes)
61+
- **receiver_sk** - Receiver's private key (hex `str` or `bytes`)
6262
- **data** - Data to decrypt
6363
- **config** - Optional configuration object
6464

@@ -116,12 +116,11 @@ $ rm sk pk data enc_data
116116
Ephemeral key format in the payload and shared key in the key derivation can be configured as compressed or uncompressed format.
117117

118118
```py
119+
from .consts import COMPRESSED_PUBLIC_KEY_SIZE, UNCOMPRESSED_PUBLIC_KEY_SIZE
120+
119121
SymmetricAlgorithm = Literal["aes-256-gcm", "xchacha20"]
120122
NonceLength = Literal[12, 16] # only for aes-256-gcm, xchacha20 will always be 24
121123

122-
COMPRESSED_PUBLIC_KEY_SIZE = 33
123-
UNCOMPRESSED_PUBLIC_KEY_SIZE = 65
124-
125124

126125
@dataclass()
127126
class Config:

ecies/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def encrypt(
2626
Parameters
2727
----------
2828
receiver_pk: Union[str, bytes]
29-
Receiver's public key (hex str or bytes)
29+
Receiver's public key (hex `str` or `bytes`)
3030
data: bytes
3131
Data to encrypt
3232
config: Config
@@ -63,7 +63,7 @@ def decrypt(
6363
Parameters
6464
----------
6565
receiver_sk: Union[str, bytes]
66-
Receiver's private key (hex str or bytes)
66+
Receiver's private key (hex `str` or `bytes`)
6767
data: bytes
6868
Data to decrypt
6969
config: Config

ecies/config.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
from dataclasses import dataclass
22
from typing import Literal
33

4+
from .consts import COMPRESSED_PUBLIC_KEY_SIZE, UNCOMPRESSED_PUBLIC_KEY_SIZE
5+
46
SymmetricAlgorithm = Literal["aes-256-gcm", "xchacha20"]
57
NonceLength = Literal[12, 16] # only for aes-256-gcm, xchacha20 will always be 24
68

7-
COMPRESSED_PUBLIC_KEY_SIZE = 33
8-
UNCOMPRESSED_PUBLIC_KEY_SIZE = 65
9-
109

1110
@dataclass()
1211
class Config:

ecies/consts.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# elliptic
2+
COMPRESSED_PUBLIC_KEY_SIZE = 33
3+
UNCOMPRESSED_PUBLIC_KEY_SIZE = 65
4+
ETH_PUBLIC_KEY_LENGTH = 64
5+
6+
# symmetric
7+
XCHACHA20_NONCE_LENGTH = 24
8+
AEAD_TAG_LENGTH = 16

ecies/utils/eth.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from coincurve import PublicKey
22
from coincurve.utils import get_valid_secret
33

4-
from .hash import keccak_256
5-
6-
ETH_PUBLIC_KEY_LENGTH = 64
4+
from ..consts import ETH_PUBLIC_KEY_LENGTH
5+
from .hash import keccak256
76

87

98
def generate_eth_key():
@@ -23,13 +22,14 @@ def generate_eth_key():
2322
return keys.PrivateKey(get_valid_secret())
2423

2524

25+
# for cli only
2626
def to_eth_public_key(pk: PublicKey) -> bytes:
2727
return pk.format(False)[1:]
2828

2929

3030
def to_eth_address(pk: PublicKey) -> str:
3131
pk_bytes = to_eth_public_key(pk)
32-
return encode_checksum(keccak_256(pk_bytes)[-20:].hex())
32+
return encode_checksum(keccak256(pk_bytes)[-20:].hex())
3333

3434

3535
# private below
@@ -42,7 +42,7 @@ def convert_eth_public_key(data: bytes):
4242
def encode_checksum(raw_address: str) -> str:
4343
# https://github.com/ethereum/ercs/blob/master/ERCS/erc-55.md
4444
address = raw_address.lower().replace("0x", "")
45-
address_hash = keccak_256(address.encode()).hex()
45+
address_hash = keccak256(address.encode()).hex()
4646

4747
res = []
4848
for a, h in zip(address, address_hash):

ecies/utils/hash.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ def sha256(data: bytes) -> bytes:
2525

2626

2727
def derive_key(master: bytes, salt: bytes = b"") -> bytes:
28+
# for aes256 and xchacha20
2829
derived = HKDF(master, 32, salt, SHA256, num_keys=1)
2930
return derived # type: ignore
3031

3132

3233
# private below
33-
def keccak_256(b: bytes) -> bytes:
34+
def keccak256(b: bytes) -> bytes:
3435
h = keccak.new(data=b, digest_bits=256)
3536
return h.digest()

ecies/utils/symmetric.py

+8-11
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,14 @@
33
from Crypto.Cipher import AES, ChaCha20_Poly1305
44

55
from ..config import NonceLength, SymmetricAlgorithm
6-
7-
AES_CIPHER_MODE = AES.MODE_GCM
8-
AEAD_TAG_LENGTH = 16
9-
XCHACHA20_NONCE_LENGTH = 24
6+
from ..consts import AEAD_TAG_LENGTH, XCHACHA20_NONCE_LENGTH
107

118

129
def sym_encrypt(
1310
key: bytes,
1411
plain_text: bytes,
1512
algorithm: SymmetricAlgorithm = "aes-256-gcm",
16-
aes_nonce_length: NonceLength = 16,
13+
nonce_length: NonceLength = 16,
1714
) -> bytes:
1815
"""
1916
Symmetric encryption. AES-256-GCM or XChaCha20-Poly1305.
@@ -33,8 +30,8 @@ def sym_encrypt(
3330
nonce + tag(16 bytes) + encrypted data
3431
"""
3532
if algorithm == "aes-256-gcm":
36-
nonce = os.urandom(aes_nonce_length)
37-
aes_cipher = AES.new(key, AES_CIPHER_MODE, nonce)
33+
nonce = os.urandom(nonce_length)
34+
aes_cipher = AES.new(key, AES.MODE_GCM, nonce)
3835
encrypted, tag = aes_cipher.encrypt_and_digest(plain_text)
3936
elif algorithm == "xchacha20":
4037
nonce = os.urandom(XCHACHA20_NONCE_LENGTH)
@@ -92,11 +89,11 @@ def sym_decrypt(
9289
# If it's 16 bytes, the nonce will be used to hash, so it's meaningless to increment
9390

9491
if algorithm == "aes-256-gcm":
95-
nonce, tag, ciphered_data = _split_cipher_text(cipher_text, nonce_length)
96-
aes_cipher = AES.new(key, AES_CIPHER_MODE, nonce)
92+
nonce, tag, ciphered_data = __split_cipher_text(cipher_text, nonce_length)
93+
aes_cipher = AES.new(key, AES.MODE_GCM, nonce)
9794
return aes_cipher.decrypt_and_verify(ciphered_data, tag)
9895
elif algorithm == "xchacha20":
99-
nonce, tag, ciphered_data = _split_cipher_text(
96+
nonce, tag, ciphered_data = __split_cipher_text(
10097
cipher_text, XCHACHA20_NONCE_LENGTH
10198
)
10299
xchacha_cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce)
@@ -105,7 +102,7 @@ def sym_decrypt(
105102
raise NotImplementedError
106103

107104

108-
def _split_cipher_text(cipher_text: bytes, nonce_length: int):
105+
def __split_cipher_text(cipher_text: bytes, nonce_length: int):
109106
nonce_tag_length = nonce_length + AEAD_TAG_LENGTH
110107
nonce = cipher_text[:nonce_length]
111108
tag = cipher_text[nonce_length:nonce_tag_length]

tests/utils/test_symmetric.py

+25-14
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,30 @@ def test_symmetric_big(algorithm, big_data):
2323
__check_symmetric_random(big_data, algorithm)
2424

2525

26-
def test_aes_known():
27-
key = decode_hex("0000000000000000000000000000000000000000000000000000000000000000")
28-
nonce = decode_hex("0xf3e1ba810d2c8900b11312b7c725565f")
29-
tag = decode_hex("0Xec3b71e17c11dbe31484da9450edcf6c")
30-
encrypted = decode_hex("02d2ffed93b856f148b9")
31-
data = b"".join([nonce, tag, encrypted])
32-
assert b"helloworld" == sym_decrypt(key, data)
33-
26+
@pytest.mark.parametrize(
27+
"key,nonce,tag,encrypted,algorithm",
28+
[
29+
(
30+
"0000000000000000000000000000000000000000000000000000000000000000",
31+
"0xf3e1ba810d2c8900b11312b7c725565f",
32+
"0Xec3b71e17c11dbe31484da9450edcf6c",
33+
"02d2ffed93b856f148b9",
34+
"aes-256-gcm",
35+
),
36+
(
37+
"27bd6ec46292a3b421cdaf8a3f0ca759cbc67bcbe7c5855aa0d1e0700fd0e828",
38+
"0xfbd5dd10431af533c403d6f4fa629931e5f31872d2f7e7b6",
39+
"0X5b5ccc27324af03b7ca92dd067ad6eb5",
40+
"aa0664f3c00a09d098bf",
41+
"xchacha20",
42+
),
43+
],
44+
)
45+
def test_known(key, nonce, tag, encrypted, algorithm):
46+
key = decode_hex(key)
47+
nonce = decode_hex(nonce)
48+
tag = decode_hex(tag)
49+
encrypted = decode_hex(encrypted)
3450

35-
def test_xchacha20_known():
36-
key = decode_hex("27bd6ec46292a3b421cdaf8a3f0ca759cbc67bcbe7c5855aa0d1e0700fd0e828")
37-
nonce = decode_hex("0xfbd5dd10431af533c403d6f4fa629931e5f31872d2f7e7b6")
38-
tag = decode_hex("0X5b5ccc27324af03b7ca92dd067ad6eb5")
39-
encrypted = decode_hex("aa0664f3c00a09d098bf")
4051
data = b"".join([nonce, tag, encrypted])
41-
assert b"helloworld" == sym_decrypt(key, data, "xchacha20")
52+
assert b"helloworld" == sym_decrypt(key, data, algorithm)

0 commit comments

Comments
 (0)