Giter VIP home page Giter VIP logo

rs's Introduction

eciesrs

Codacy Badge License CI Codecov Crates Doc

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

ECIES functionalities are built upon AES-256-GCM 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();
#[cfg(not(feature = "x25519"))]
let (sk, pk) = (&sk.serialize(), &pk.serialize());
#[cfg(feature = "x25519")]
let (sk, pk) = (sk.as_bytes(), pk.as_bytes());

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 aes-12bytes-nonce feature on OpenSSL or pure Rust AES backend.

ecies = {version = "0.2", features = ["aes-12bytes-nonce"]} # it also works with "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
}

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).

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.

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 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 hardware acceleration (resistent 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: 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.

rs's People

Contributors

dependabot-preview[bot] avatar dependabot[bot] avatar haoxuan40404 avatar kigawas avatar olegnn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

rs's Issues

Zeroize on SecretKey

I am unsure if this crate overwrites the memory where a SecretKey resides when its lifetime ends.
Overwriting it with zeroes would be one way to to this.
The idea here of course is to disable reading the secret from memory, after it is no longer needed.

Is this possible or planned?

Unable to build with pure backend

Trying to build with default-features=false and features=["pure"] causes error. The OpenSSL backend seems to work fine.

Reproduction steps

  1. Create a new cargo project and add ecies={version="0.2.6", default-features=false, features=["pure"]} to Cargo.toml
  2. cargo build --release the code snippet below

Expected behavior

The build should pass

Actual behavior

The following error is thrown:

error[E0432]: unresolved import `once_cell::sync`
 --> /home/username/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ecies-0.2.6/src/config.rs:1:16
  |
1 | use once_cell::sync::Lazy;
  |                ^^^^ could not find `sync` in `once_cell`

For more information about this error, try `rustc --explain E0432`.
error: could not compile `ecies` (lib) due to 1 previous error

Code

use ecies::{encrypt, decrypt, utils::generate_keypair};

fn main() {
    let msg="Hello, this is a test.";
    let (sk, pk)=generate_keypair();
    let (sk, pk)=(&sk.serialize(), &pk.serialize());

    let encrypted_message=encrypt(pk, msg.as_bytes()).unwrap();

    let original=decrypt(sk, &encrypted_message).unwrap();

    let original=String::from_utf8(original).unwrap();

    println!("{original}");
    }

Environment

* OS: Ubuntu Mate 22.04 64-bit

  • rustc: 1.78.0
    * ecies: 1.2.6

support `no_std`

It would be very nice to support environments without standard library. Embedded devices like target=thumbv6m-none-eabi need no_std

$ cargo build --no-default-features --features pure --target=thumbv6m-none-eabi
   Compiling subtle v2.4.1
   Compiling base64 v0.13.0
   Compiling getrandom v0.2.3
   Compiling generic-array v0.14.4
   Compiling serde v1.0.131
error[E0463]: can't find crate for `std`
  --> /.cargo/registry/src/github.com-1ecc6299db9ec823/subtle-2.4.1/src/lib.rs:88:1
   |
88 | extern crate std;
   | ^^^^^^^^^^^^^^^^^ can't find crate
   |
   = note: the `thumbv6m-none-eabi` target may not support the standard library

error[E0463]: can't find crate for `std`
 --> /.cargo/registry/src/github.com-1ecc6299db9ec823/getrandom-0.2.3/src/error_impls.rs:9:1
  |
9 | extern crate std;
  | ^^^^^^^^^^^^^^^^^ can't find crate
  |
  = note: the `thumbv6m-none-eabi` target may not support the standard library

For more information about this error, try `rustc --explain E0463`.
error: could not compile `subtle` due to previous error
warning: build failed, waiting for other jobs to finish...
error[E0463]: can't find crate for `std`
  |
  = note: the `thumbv6m-none-eabi` target may not support the standard library
  = note: `std` is required by `base64` because it does not declare `#![no_std]`

error[E0463]: can't find crate for `std`
  |
  = note: the `thumbv6m-none-eabi` target may not support the standard library
  = note: `std` is required by `serde` because it does not declare `#![no_std]`

error: build failed

Compatibility

Hi,
Do you think there is hope that this implementation can be compatible with bouncycastle's implementation(s) of ECIES?
Precisely, the goal would be to instantiate ECIES in BC so that the resulting ciphertexts would have the same format as yours (the BC ciphertexts are decryptable in your implementation and viceversa).
The reason is that I need compatibility among different frameworks like Android apps, Windows desktop Apps, web browsers, etc. With BC I can cover most of cases but it would be preferable to use yours to cover websites but before digging into details I would like to ask you an opinion on whether you deem easy to make them compatible each other.
Thanks in advance

multiple definitions

  Compiling ecies v0.2.6
error[E0252]: the name `decrypt` is defined multiple times
  --> /home/kamiyaa/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ecies-0.2.6/src/symmetric/mod.rs:11:16
   |
9  | use openssl_aes::{decrypt, encrypt};
   |                   ------- previous import of the value `decrypt` here
10 | #[cfg(feature = "pure")]
11 | use pure_aes::{decrypt, encrypt};
   |                ^^^^^^^ `decrypt` reimported here
   |
   = note: `decrypt` must be defined only once in the value namespace of this module
help: you can use `as` to change the binding name of the import
   |
11 | use pure_aes::{decrypt as other_decrypt, encrypt};
   |                ~~~~~~~~~~~~~~~~~~~~~~~~

error[E0252]: the name `encrypt` is defined multiple times
  --> /home/kamiyaa/.cargo/registry/src/index.crates.io-6f17d22bba15001f/ecies-0.2.6/src/symmetric/mod.rs:11:25
   |
9  | use openssl_aes::{decrypt, encrypt};
   |                            ------- previous import of the value `encrypt` here
10 | #[cfg(feature = "pure")]
11 | use pure_aes::{decrypt, encrypt};
   |                         ^^^^^^^ `encrypt` reimported here
   |
   = note: `encrypt` must be defined only once in the value namespace of this module
help: you can use `as` to change the binding name of the import
   |
11 | use pure_aes::{decrypt, encrypt as other_encrypt};
   |                         ~~~~~~~~~~~~~~~~~~~~~~~~

For more information about this error, try `rustc --explain E0252`.
error: could not compile `ecies` (lib) due to 2 previous errors

Is there any way we can use `secp256k1` instead?

The reason I ask is because we already include the secp256k1 crate in our WASM binary for BDK, so having multiple implementations for the same thing is suboptimal. Also, according to my tests, the k256 library is substantially slower than the C library, though I'm not sure if this problem is similar for libsecp256k1, and I'm also not sure how many times public keys need to be computed during encryption and decryption.

Issue with `thiserror`

We can't seem to get past this error when updating past 0.2.4-- Versions 0.2.5 and 0.2.6 break with this error:

error[E0599]: the method `as_dyn_error` exists for reference `&SecpError`, but its trait bounds were not satisfied
 --> /home/hunter/.cargo/registry/src/index.crates.io-6f17d22bba15001f/carbonado-0.3.3/src/error.rs:3:10
  |
3 | #[derive(Error, Debug)]
  |          ^^^^^ method cannot be called on `&SecpError` due to unsatisfied trait bounds
  |
 ::: /home/hunter/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libsecp256k1-core-0.3.0/src/error.rs:2:1
  |
2 | pub enum Error {
  | --------------
  | |
  | doesn't satisfy `SecpError: AsDynError<'_>`
  | doesn't satisfy `SecpError: StdError`
  |
  = note: the following trait bounds were not satisfied:
          `SecpError: StdError`
          which is required by `SecpError: AsDynError<'_>`
          `&SecpError: StdError`
          which is required by `&SecpError: AsDynError<'_>`
  = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info)

The code in question uses a crate called thiserror to proxy error details:
https://github.com/diba-io/carbonado/blob/518188593fc2a86bf2fa687f9165b83904c0d64f/src/error.rs#L33-L35

Any idea what might be happening?

Provide an API to work with streams ?

Currently the API takes a &[u8] as input.

It would be nice to be able to process huge files entirely in memory by processing chunks one after another.

Maybe by using std::io::BufReader/std::io::BufWriter ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.