https://github.com/ecies/rs
Elliptic Curve Integrated Encryption Scheme for secp256k1 in Rust
https://github.com/ecies/rs
bitcoin crates ecies elliptic-curves elliptic-curves-cryptography ethereum rust
Last synced: 7 days ago
JSON representation
Elliptic Curve Integrated Encryption Scheme for secp256k1 in Rust
- Host: GitHub
- URL: https://github.com/ecies/rs
- Owner: ecies
- License: mit
- Created: 2019-08-07T07:47:17.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2025-04-02T18:42:19.000Z (about 2 months ago)
- Last Synced: 2025-04-12T06:05:58.232Z (about 1 month ago)
- Topics: bitcoin, crates, ecies, elliptic-curves, elliptic-curves-cryptography, ethereum, rust
- Language: Rust
- Homepage: https://ecies.org/rs
- Size: 149 KB
- Stars: 84
- Watchers: 2
- Forks: 23
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# eciesrs
[](https://app.codacy.com/gh/ecies/rs/dashboard)
[](https://github.com/ecies/rs)
[](https://crates.io/crates/ecies)
[](https://lib.rs/crates/ecies)
[](https://docs.rs/ecies/latest/ecies/)
[](https://github.com/ecies/rs/actions)
[](https://codecov.io/gh/ecies/rs)Elliptic Curve Integrated Encryption Scheme for secp256k1/curve25519 in Rust, based on pure-Rust secp256k1/curve25519 implementation.
ECIES functionalities are built upon AES-256-GCM/XChaCha20-Poly1305 and HKDF-SHA256.
This is the Rust version of [eciesjs](https://github.com/ecies/js).
This library can be compiled to the WASM target at your option, see [WASM compatibility](#wasm-compatibility).
## Quick start
`no_std` is enabled by default. You can enable `std` with `std` feature.
```toml
ecies = {version = "0.2", features = ["std"]} # MSRV is 1.65
``````rust
use ecies::{decrypt, encrypt, utils::generate_keypair};const MSG: &str = "hello world🌍";
let (sk, pk) = generate_keypair();
#[cfg(all(not(feature = "x25519"), not(feature = "ed25519")))]
let (sk, pk) = (&sk.serialize(), &pk.serialize());
#[cfg(feature = "x25519")]
let (sk, pk) = (sk.as_bytes(), pk.as_bytes());
#[cfg(feature = "ed25519")]
let (sk, pk) = (&sk, &pk);let msg = MSG.as_bytes();
assert_eq!(
msg,
decrypt(sk, &encrypt(pk, msg).unwrap()).unwrap().as_slice()
);
```## Elliptic curve configuration
### Optional x25519/ed25519 support
You can choose to use x25519 (key exchange function on curve25519) or ed25519 (signature algorithm on curve25519) instead of secp256k1:
```toml
ecies = {version = "0.2", features = ["x25519"]} # recommended
ecies = {version = "0.2", features = ["ed25519"]} # or if you know what you are doing
```### Secp256k1-specific configuration
Some behaviors can be configured by global static variable:
```rust
pub struct Config {
pub is_ephemeral_key_compressed: bool,
pub is_hkdf_key_compressed: bool
}
```On `is_ephemeral_key_compressed: true`, the payload would be like: `33 Bytes + AES` instead of `65 Bytes + AES`.
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)`.
```rust
use ecies::config::{Config, update_config};update_config(Config {
is_ephemeral_key_compressed: true,
is_hkdf_key_compressed: true
});
```For compatibility, make sure different applications share the same configuration. Normally configuration is only updated once on initialization, if not, beware of race condition.
## Symmetric cipher configuration
### Optional pure Rust AES backend
You can choose to use OpenSSL implementation or [pure Rust implementation](https://github.com/RustCrypto/AEADs) of AES-256-GCM:
```toml
ecies = {version = "0.2", default-features = false, features = ["aes-rust"]}
```Due to some [performance problem](https://github.com/RustCrypto/AEADs/issues/243), OpenSSL is the default backend.
Pure Rust implementation is sometimes useful, such as building on WASM:
```bash
cargo build --no-default-features --features aes-rust --target=wasm32-unknown-unknown
```#### Build on x86 CPUs
If you select the pure Rust backend on modern x86 CPUs, consider building with
```bash
RUSTFLAGS="-Ctarget-cpu=sandybridge -Ctarget-feature=+aes,+sse2,+sse4.1,+ssse3"
```It can speed up AES encryption/decryption. This would be no longer necessary when [`aes-gcm` supports automatic CPU detection](https://github.com/RustCrypto/AEADs/issues/243#issuecomment-738821935).
#### Build on ARM CPUs
On ARM CPUs (like Apple), consider building with
```bash
RUSTFLAGS="--cfg aes_armv8"
```### Optional pure Rust XChaCha20-Poly1305 backend
You can also enable a pure Rust [XChaCha20-Poly1305](https://github.com/RustCrypto/AEADs/tree/master/chacha20poly1305) backend.
```toml
ecies = {version = "0.2", default-features = false, features = ["xchacha20"]}
```On ARM CPUs, enable SIMD with
```bash
RUSTFLAGS="--cfg chacha20_force_neon"
```## WASM compatibility
It's also possible to build to the `wasm32-unknown-unknown` target (or `wasm32-wasip2`) with the pure Rust backend. Check out [this repo](https://github.com/ecies/rs-wasm) for more details.
## Security
### Why AES-256-GCM and HKDF-SHA256
AEAD scheme like AES-256-GCM should be your first option for symmetric ciphers, with unique IVs in each encryption.
For key derivation functions on shared points between two asymmetric keys, HKDFs are [proven](https://github.com/ecies/py/issues/82) to be more secure than simple hash functions like SHA256.
### Why XChaCha20-Poly1305 instead of AES-256-GCM
XChaCha20-Poly1305 is a competitive alternative to AES-256-GCM because it's fast and constant-time without dedicated hardware acceleration (resistant to cache-timing attacks). It also has longer nonce length to alleviate the risk of birthday attacks when nonces are generated randomly.
### Cross-language compatibility
All functionalities are mutually checked among [different languages](https://github.com/ecies): Python, Rust, JavaScript and Golang.
### Security audit
Following dependencies are audited:
- [aes-gcm and chacha20poly1305](https://research.nccgroup.com/2020/02/26/public-report-rustcrypto-aes-gcm-and-chacha20poly1305-implementation-review/)
- [OpenSSL](https://ostif.org/the-ostif-and-quarkslab-audit-of-openssl-is-complete/)## Benchmark
On Mac mini M4 Pro (24 GB) on Apr 2, 2025, secp256k1 only.
Rust version: 1.85.0 (4d91de4e4 2025-02-17)
### AES backend (OpenSSL)
```bash
$ cargo bench --no-default-features --features aes-opensslencrypt 100M time: [29.237 ms 29.827 ms 30.628 ms]
Found 2 outliers among 10 measurements (20.00%)
1 (10.00%) low mild
1 (10.00%) high mildencrypt 200M time: [86.005 ms 88.055 ms 89.282 ms]
decrypt 100M time: [17.222 ms 17.568 ms 17.977 ms]
Found 1 outliers among 10 measurements (10.00%)
1 (10.00%) high milddecrypt 200M time: [38.884 ms 39.324 ms 39.693 ms]
Found 1 outliers among 10 measurements (10.00%)
1 (10.00%) high mild
```### AES backend (Pure Rust)
```bash
$ export RUSTFLAGS="--cfg aes_armv8"
$ cargo bench --no-default-features --features aes-rustencrypt 100M time: [120.40 ms 122.63 ms 127.09 ms]
Found 1 outliers among 10 measurements (10.00%)
1 (10.00%) high severeencrypt 200M time: [253.86 ms 256.43 ms 258.01 ms]
decrypt 100M time: [113.73 ms 114.05 ms 114.39 ms]
decrypt 200M time: [236.41 ms 237.82 ms 239.12 ms]
```### XChaCha20 backend
```bash
$ export RUSTFLAGS="--cfg chacha20_force_neon"
$ cargo bench --no-default-features --features xchacha20encrypt 100M time: [120.24 ms 120.98 ms 121.63 ms]
encrypt 200M time: [257.24 ms 261.22 ms 264.06 ms]
decrypt 100M time: [114.39 ms 114.94 ms 116.03 ms]
decrypt 200M time: [238.09 ms 240.60 ms 242.55 ms]
```## Changelog
See [CHANGELOG.md](./CHANGELOG.md).