Skip to main content

eciespy

Codacy Badge License PyPI PyPI - Downloads PyPI - Python Version CI Codecov

Elliptic Curve Integrated Encryption Scheme for secp256k1/curve25519 in Python.

Other language versions (curve25519 is not supported in some versions):

You can also check a web backend demo.

Install

pip install eciespy

Or pip install 'eciespy[eth]' to install eth-keys as well.

Quick Start

Secp256k1

>>> from ecies.keys import PrivateKey
>>> from ecies import encrypt, decrypt
>>> data = 'hello world🌍'.encode()
>>> sk = PrivateKey('secp256k1')
>>> sk_bytes = sk.secret  # bytes
>>> pk_bytes = sk.public_key.to_bytes(True)  # bytes
>>> decrypt(sk_bytes, encrypt(pk_bytes, data)).decode()
'hello world🌍'
>>> sk_hex = sk.to_hex() # hex str
>>> pk_hex = sk.public_key.to_hex(True) # hex str
>>> decrypt(sk_hex, encrypt(pk_hex, data)).decode()
'hello world🌍'

X25519/Ed25519

>>> from ecies.keys import PrivateKey
>>> from ecies import encrypt, decrypt
>>> from ecies.config import ECIES_CONFIG
>>> ECIES_CONFIG.elliptic_curve = 'x25519' # or 'ed25519'
>>> data = 'hello world🌍'.encode()
>>> sk = PrivateKey('x25519') # or 'ed25519'
>>> decrypt(sk.secret, encrypt(sk.public_key.to_bytes(), data)).decode()
'hello world🌍'

Or just use a builtin command eciespy in your favorite command line.

API

ecies.encrypt(receiver_pk: Union[str, bytes], data: bytes, config: Config = ECIES_CONFIG) -> bytes

Parameters:

  • receiver_pk - Receiver's public key (hex str or bytes)
  • data - Data to encrypt
  • config - Optional configuration object

Returns: bytes

ecies.decrypt(receiver_sk: Union[str, bytes], data: bytes, config: Config = ECIES_CONFIG) -> bytes

Parameters:

  • receiver_sk - Receiver's private key (hex str or bytes)
  • data - Data to decrypt
  • config - Optional configuration object

Returns: bytes

Command Line Interface

Show help

$ eciespy -h
usage: eciespy [-h] [-e] [-d] [-g] [-k KEY] [-c {secp256k1,x25519,ed25519}] [-D [DATA]] [-O [OUT]]

Elliptic Curve Integrated Encryption Scheme for secp256k1/curve25519 in Python

options:
  -h, --help            show this help message and exit
  -e, --encrypt         encrypt with public key, exclusive with -d
  -d, --decrypt         decrypt with private key, exclusive with -e
  -g, --generate        generate key pair, for secp256k1, ethereum public key and address will be printed
  -k, --key KEY         public or private key file
  -c, --curve {secp256k1,x25519,ed25519}
                        elliptic curve, default: secp256k1
  -D, --data [DATA]     file to encrypt or decrypt, if not specified, it will read from stdin
  -O, --out [OUT]       encrypted or decrypted file, if not specified, it will write to stdout

Generate eth key

$ eciespy -g
Private: 0x95d3c5e483e9b1d4f5fc8e79b2deaf51362980de62dbb082a9a4257eef653d7d
Public: 0x98afe4f150642cd05cc9d2fa36458ce0a58567daeaf5fde7333ba9b403011140a4e28911fcf83ab1f457a30b4959efc4b9306f514a4c3711a16a80e3b47eb58b
Address: 0x47e801184B3a8ea8E6A4A7A4CFEfEcC76809Da72

Encrypt with public key and decrypt with private key

$ echo '0x95d3c5e483e9b1d4f5fc8e79b2deaf51362980de62dbb082a9a4257eef653d7d' > sk
$ echo '0x98afe4f150642cd05cc9d2fa36458ce0a58567daeaf5fde7333ba9b403011140a4e28911fcf83ab1f457a30b4959efc4b9306f514a4c3711a16a80e3b47eb58b' > pk
$ echo 'hello ecies' | eciespy -e -k pk | eciespy -d -k sk
hello ecies
$ echo 'data to encrypt' > data
$ eciespy -e -k pk -D data -O enc_data
$ eciespy -d -k sk -D enc_data
data to encrypt
$ rm sk pk data enc_data

Configuration

Following configurations are available.

  • Elliptic curve: secp256k1 or curve25519 (x25519/ed25519)
  • Ephemeral key format in the payload: compressed or uncompressed (only for secp256k1)
  • Shared elliptic curve key format in the key derivation: compressed or uncompressed (only for secp256k1)
  • Symmetric cipher algorithm: AES-256-GCM or XChaCha20-Poly1305
  • Symmetric nonce length: 12 or 16 bytes (only for AES-256-GCM)

For compatibility, make sure different applications share the same configuration.

EllipticCurve = Literal["secp256k1", "x25519", "ed25519"]
SymmetricAlgorithm = Literal["aes-256-gcm", "xchacha20"]
NonceLength = Literal[12, 16]  # only for aes-256-gcm, xchacha20 will always be 24


@dataclass()
class Config:
    elliptic_curve: EllipticCurve = "secp256k1"
    is_ephemeral_key_compressed: bool = False
    is_hkdf_key_compressed: bool = False
    symmetric_algorithm: SymmetricAlgorithm = "aes-256-gcm"
    symmetric_nonce_length: NonceLength = 16

    @property
    def ephemeral_key_size(self):
        if self.elliptic_curve == "secp256k1":
            return (
                COMPRESSED_PUBLIC_KEY_SIZE
                if self.is_ephemeral_key_compressed
                else UNCOMPRESSED_PUBLIC_KEY_SIZE
            )
        elif self.elliptic_curve in ("x25519", "ed25519"):
            return CURVE25519_PUBLIC_KEY_SIZE
        else:
            raise NotImplementedError


ECIES_CONFIG = Config()

On ECIES_CONFIG.elliptic_curve = "x25519" or "ed25519", x25519 (key exchange function on curve25519) or ed25519 (signature algorithm on curve25519) will be used for key exchange instead of secp256k1.

In this case, the payload would always be: 32 Bytes + Ciphered.

If you don't know how to choose between x25519 and ed25519, just use the dedicated key exchange function x25519 for efficiency.

Because any 32-byte data is a valid curve25519 public key, the payload would seem random. This property is excellent for circumventing censorship by adversaries.

Secp256k1-specific configuration

On is_ephemeral_key_compressed = True, the payload would be like: 33 Bytes + Ciphered instead of 65 Bytes + Ciphered.

On is_hkdf_key_compressed = True, the hkdf key would be derived from ephemeral public key (compressed) + shared public key (compressed) instead of ephemeral public key (uncompressed) + shared public key (uncompressed).

Symmetric cipher configuration

On symmetric_algorithm = "xchacha20", plaintext data would be encrypted with XChaCha20-Poly1305.

On symmetric_nonce_length = 12, then the nonce of AES-256-GCM would be 12 bytes. XChaCha20-Poly1305's nonce is always 24 bytes.

Which configuration should I choose?

For compatibility with other ecies libraries, start with the default (secp256k1 with AES-256-GCM).

For speed and security, pick x25519 with XChaCha20-Poly1305.

Technical details

See DETAILS.md.

Changelog

See CHANGELOG.md.

Development

uv sync --all-extras
uv run pytest -v
uv run ruff check --fix
uv run ruff format
uv run ty check

Metadata

Release files for eciespy 0.4.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for eciespy 0.4.7
File Size Uploaded Provenance
eciespy-0.4.7.tar.gz 13.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for eciespy 0.4.7
File Interpreter ABI Platform
eciespy-0.4.7-py3-none-any.whl Python 3 none any Details

Total release size: 28.3 kB

Release files / eciespy-0.4.7.tar.gz

Download URL eciespy-0.4.7.tar.gz
Size 13.1 kB
Tags Source
SHA-256 checksum
How to use checksums
a0d32db7d3e617f0d2ba37e313eb1a6d5ff0d2bc5532b46262025d783c31413b
BLAKE2b-256 checksum
How to use checksums
c3f31c221d34293f7ce1f305bf21a61c07c8723aeab6799520e92db7ed10d79a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / eciespy-0.4.7-py3-none-any.whl

Download URL eciespy-0.4.7-py3-none-any.whl
Size 15.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fc6751ec818144e25ab9757f2cfc1e0e4aa8aa911cc8db2ecb0816769f3cb2f3
BLAKE2b-256 checksum
How to use checksums
743c33cd1c8a5e2b5ac094d9c4b0574a9dda49209a3ad35ffdcd3d9c219b4753
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for eciespy 0.4.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.4.7 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page