End 2 End Encryption
Project description
E2EE
End-to-end encryption helper built on elliptic-curve Diffie-Hellman (ECDH), PBKDF2 key derivation, and Fernet symmetric encryption. The E2EE class coordinates server/client key exchange, mutual authentication, and message confidentiality.
Features
- ECDH (SECP521R1) key agreement for both a public key and a salt key-pair
- Server-signed public material to prevent tampering (ECDSA with SHA-224)
- PBKDF2-HMAC-SHA256 derivation of a 256-bit Fernet key from the dual shared secrets
- Simple
encrypt/decrypthelpers that emit URL-safe Base64 strings
Prerequisites
- Python
>=3.9.10 cryptographylibrary (pulled automatically viapyproject.toml)- DER-encoded ECDSA key pair available on disk:
PRIVATE_KEYenvironment variable -> path to the server signing key (PKCS#8 DER)PUBLIC_KEYenvironment variable -> path to the public key distributed to clients (SubjectPublicKeyInfo DER)
These files are used exactly as in the tests/conftest.py fixture.
Key-Exchange Workflow
- Server bootstrap: instantiate
E2EE()with no arguments. It becomes the authoritative peer, loading its private signing key and generating ephemeral public key/salt pairs. - Publish public material: the server exposes
server.public_keyandserver.public_salt. Each property returns the Base32-encoded point alongside a Base32 signature. - Client bootstrap: instantiate
E2EE(server.public_key, server.public_salt)on the client. The client verifies the signatures with the server's public signing key (pointed to byPUBLIC_KEY), generates its own ephemeral key material, and sets up symmetric encryption. - Mutual exchange: the client shares its unsigned public key/salt. The server calls
load_peer_public_key(client.public_key, client.public_salt)to complete ECDH. - Secure channel: both peers derive the same Fernet key from the combined secrets and can call
encrypt/decryptto exchange ciphertexts.
The round-trip mirrors tests/test_e2ee.py and can be summarized as:
server = E2EE()
client = E2EE(server.public_key, server.public_salt)
server.load_peer_public_key(client.public_key, client.public_salt)
ciphertext = server.encrypt("hello")
plaintext = client.decrypt(ciphertext)
Quickstart Example
- Generate signing keys (dev only):
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.serialization import Encoding, NoEncryption, PrivateFormat, PublicFormat
priv = ec.generate_private_key(ec.SECP521R1())
pub = priv.public_key()
open("/tmp/ecdsa_private_key.pem", "wb").write(
priv.private_bytes(Encoding.DER, PrivateFormat.PKCS8, NoEncryption())
)
open("/tmp/ecdsa_public_key.pem", "wb").write(
pub.public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo)
)
- Export the paths:
export PRIVATE_KEY=/tmp/ecdsa_private_key.pem
export PUBLIC_KEY=/tmp/ecdsa_public_key.pem
- Exchange messages:
from e2ee import E2EE
server = E2EE()
client = E2EE(server.public_key, server.public_salt)
server.load_peer_public_key(client.public_key, client.public_salt)
secret_from_server = server.encrypt("SECRET MESSAGE FROM SERVER!")
print(client.decrypt(secret_from_server))
secret_from_client = client.encrypt("SECRET MESSAGE FROM CLIENT!")
print(server.decrypt(secret_from_client))
API Reference
E2EE(public_key=None, public_salt=None): Creates a server instance when called with no arguments; otherwise acts as a client that immediately verifies and loads the remote public key material.public_key/public_salt: Base32-encoded strings (plus signatures on the server). Client values do not include signatures.load_peer_public_key(public_key, public_salt, exchange=True): Imports peer material. For clients, the tuple must include(encoded_key, signature)pairs; servers expect plain Base32 strings. Whenexchangeis true (default) the instance computes shared secrets and arms Fernet encryption.encrypt(message: str) -> str: Encrypts UTF-8 strings and returns URL-safe Base64 ciphertext, ideal for transport over JSON/HTTP.decrypt(encoded_ciphertext: str) -> str: Reversesencryptand returns the original plaintext string.
Running the Test Suite
pip install -e .[dev]
pytest
The unit test in tests/test_e2ee.py performs the full server/client dance, so it serves as an executable example as well as a regression check.
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 e2ee-0.0.4.tar.gz.
File metadata
- Download URL: e2ee-0.0.4.tar.gz
- Upload date:
- Size: 42.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
308b0186bb5fa1f41a67cad5ca524c0db6afc91aa8a247c257d5fc97a8366934
|
|
| MD5 |
30367c1cabd8cfc918d36fdfd8b17ea7
|
|
| BLAKE2b-256 |
7566f7339ad59d8d6a9e4242fed0a790c65b7093f0e67095c944d9de925f527c
|
File details
Details for the file e2ee-0.0.4-py3-none-any.whl.
File metadata
- Download URL: e2ee-0.0.4-py3-none-any.whl
- Upload date:
- Size: 29.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
92c83cacde8d862993aa79ea244e67b250fee628fe97e641bb1ab8f3b8822513
|
|
| MD5 |
39d38691da48e1eab6343328906afa04
|
|
| BLAKE2b-256 |
6ad64416ee005ce49cfbac6fdd9dd9f903e495b0af37063c942f25050a7db378
|