#cryptocurrency #ecc #crypto #secp256k1

no-std ecies

Elliptic Curve Integrated Encryption Scheme for secp256k1 in Rust

13 releases

0.2.6 Jul 29, 2023
0.2.3 Sep 24, 2022
0.2.2 Nov 23, 2021
0.2.1 Jan 14, 2021
0.1.1 Nov 13, 2019

#101 in Cryptography

Download history 780/week @ 2023-12-11 583/week @ 2023-12-18 273/week @ 2023-12-25 596/week @ 2024-01-01 687/week @ 2024-01-08 668/week @ 2024-01-15 595/week @ 2024-01-22 514/week @ 2024-01-29 2427/week @ 2024-02-05 2990/week @ 2024-02-12 5702/week @ 2024-02-19 1574/week @ 2024-02-26 919/week @ 2024-03-04 716/week @ 2024-03-11 919/week @ 2024-03-18 796/week @ 2024-03-25

3,397 downloads per month
Used in 13 crates (9 directly)

MIT license

33KB
479 lines

eciesrs

Codacy Badge License CI Crates Doc

Elliptic Curve Integrated Encryption Scheme for secp256k1 in Rust, based on pure Rust implementation of secp256k1.

ECIES functionalities are built upon AES-GCM-256 and HKDF-SHA256.

This is the Rust version of eciespy.

This library can be compiled to the WASM target at your option, see WASM compatibility.

Quick Start

no_std is enabled by default. You can enable std with std feature.

ecies = {version = "0.2", features = ["std"]}
use ecies::{decrypt, encrypt, utils::generate_keypair};

const MSG: &str = "helloworld";
let (sk, pk) = generate_keypair();
let (sk, pk) = (&sk.serialize(), &pk.serialize());

let msg = MSG.as_bytes();
assert_eq!(
    msg,
    decrypt(sk, &encrypt(pk, msg).unwrap()).unwrap().as_slice()
);

Optional pure Rust AES backend

You can choose to use OpenSSL implementation or pure Rust implementation of AES-256-GCM:

ecies = {version = "0.2", default-features = false, features = ["pure"]}

Due to some performance problem, OpenSSL is the default backend.

Pure Rust implementation is sometimes useful, such as building on WASM:

cargo build --no-default-features --features pure --target=wasm32-unknown-unknown

If you select the pure Rust backend on modern CPUs, consider building with

RUSTFLAGS="-Ctarget-cpu=sandybridge -Ctarget-feature=+aes,+sse2,+sse4.1,+ssse3"

to speed up AES encryption/decryption. This would be no longer necessary when aes-gcm supports automatic CPU detection.

WASM compatibility

It's also possible to build to the wasm32-unknown-unknown target with the pure Rust backend. Check out this repo for more details.

Configuration

You can enable 12 bytes nonce by specify aes-12bytes-nonce feature.

ecies = {version = "0.2", features = ["aes-12bytes-nonce"]} # it also works for "pure"

You can also enable a pure Rust XChaCha20-Poly1305 backend.

ecies = {version = "0.2", default-features = false, features = ["xchacha20"]}

Other behaviors can be configured by global static variable:

pub struct Config {
    pub is_ephemeral_key_compressed: bool,
    pub is_hkdf_key_compressed: bool
}

If you set is_ephemeral_key_compressed: true, the payload would be like: 33 Bytes + AES instead of 65 Bytes + AES.

If you set 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).

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.

Security

Why AES-GCM-256 and HKDF-SHA256

AEAD scheme like AES-GCM-256 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 to be more secure than simple hash functions like SHA256.

Why XChaCha20-Poly1305 instead of AES-GCM-256

XChaCha20-Poly1305 is a competitive alternative to AES-256-GCM because it's fast and constant-time without hardware acceleration (resistent to cache-timing attacks). It also has longer nonce length.

Cross-language compatibility

All functionalities are mutually checked among different languages: Python, Rust, JavaScript and Golang.

Security audit

Following dependencies are audited:

Benchmark

On MacBook Pro Mid 2015 (15-inch, 2.8 GHz Quad-Core Intel Core i7) on July 19, 2023.

AES backend (OpenSSL)

$ cargo bench --no-default-features --features openssl
encrypt 100M            time:   [100.21 ms 100.79 ms 101.80 ms]

encrypt 200M            time:   [377.84 ms 384.42 ms 390.58 ms]
Found 2 outliers among 10 measurements (20.00%)
  2 (20.00%) high mild

decrypt 100M            time:   [52.430 ms 55.605 ms 60.900 ms]
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) high severe

decrypt 200M            time:   [157.87 ms 158.98 ms 160.01 ms]
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) high mild

AES backend (Pure Rust)

$ export RUSTFLAGS="-Ctarget-cpu=sandybridge -Ctarget-feature=+aes,+sse2,+sse4.1,+ssse3"
$ cargo bench --no-default-features --features pure
encrypt 100M            time:   [196.63 ms 205.63 ms 222.25 ms]
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) high severe

Benchmarking encrypt 200M: Warming up for 3.0000 s
encrypt 200M            time:   [587.78 ms 590.71 ms 592.46 ms]
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) high mild

decrypt 100M            time:   [144.78 ms 145.54 ms 147.17 ms]
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) high mild

decrypt 200M            time:   [363.14 ms 364.48 ms 365.74 ms]

XChaCha20 backend

$ cargo bench --no-default-features --features xchacha20
encrypt 100M            time:   [149.52 ms 150.06 ms 150.59 ms]
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) high mild

encrypt 200M            time:   [482.27 ms 484.95 ms 487.45 ms]
Found 3 outliers among 10 measurements (30.00%)
  2 (20.00%) low severe
  1 (10.00%) high severe

decrypt 100M            time:   [98.232 ms 100.37 ms 105.65 ms]
Found 1 outliers among 10 measurements (10.00%)
  1 (10.00%) high severe

decrypt 200M            time:   [265.62 ms 268.02 ms 269.85 ms]

Changelog

See CHANGELOG.md.

Dependencies

~4–11MB
~106K SLoC