# Elliptic Curve Integrated Encryption Scheme (ECIES)
This directory contains the implementation of the **Elliptic Curve Integrated Encryption Scheme (ECIES)** for the `dcrypt` library. It provides a modular framework for building secure public-key encryption schemes based on elliptic curve cryptography.
## Overview
ECIES is a hybrid encryption scheme that combines the efficiency of symmetric encryption with the convenience of asymmetric (public-key) encryption. This implementation provides a secure and robust way to encrypt data for a recipient using their public key.
The encryption process follows these general steps:
1. **Key Agreement**: The sender generates a new, temporary (ephemeral) elliptic curve keypair for each encryption operation. An Elliptic Curve Diffie-Hellman (ECDH) key exchange is performed between the sender's ephemeral private key and the recipient's public key. This results in a shared secret point on the curve.
2. **Key Derivation**: The x-coordinate of the shared secret point is used as input to a **HMAC-based Key Derivation Function (HKDF)**. The ephemeral public key is used as a salt for the KDF. This process derives a strong symmetric key suitable for an AEAD (Authenticated Encryption with Associated Data) cipher.
3. **Authenticated Encryption**: The actual plaintext message is encrypted using a secure AEAD cipher (such as `ChaCha20Poly1305` or `AES-256-GCM`) with the derived symmetric key. The AEAD cipher ensures both the confidentiality and the integrity/authenticity of the message.
4. **Ciphertext Composition**: The final ciphertext is a concatenation of the necessary components for decryption: the sender's ephemeral public key, the nonce used by the AEAD cipher, and the resulting authenticated ciphertext.
## Module Structure
The `ecies` module is organized into a generic core and specific implementations for different elliptic curves.
* `mod.rs`: This file is the core of the module. It defines:
* The `EciesCiphertextComponents` struct, which standardizes the structure of the ECIES ciphertext.
* Serialization and deserialization logic for the ciphertext format.
* Generic helper functions for key derivation using HKDF with different hash functions (`derive_symmetric_key_hkdf_sha256`, `derive_symmetric_key_hkdf_sha384`, etc.).
* Re-exports of the concrete ECIES implementations.
* `p192/`, `p224/`, `p256/`, `p384/`, `p521/`: These sub-modules contain the concrete ECIES implementations for the standard NIST elliptic curves. Each module defines a struct (e.g., `EciesP256`) that implements the `dcrypt_api::traits::Pke` trait, bundling a specific curve with a corresponding KDF and AEAD cipher.
### Implemented Schemes
| `EciesP192` | NIST P-192 | HKDF-SHA256 | ChaCha20Poly1305 |
| `EciesP224` | NIST P-224 | HKDF-SHA256 | ChaCha20Poly1305 |
| `EciesP256` | NIST P-256 | HKDF-SHA256 | ChaCha20Poly1305 |
| `EciesP384` | NIST P-384 | HKDF-SHA384 | AES-256-GCM |
| `EciesP521` | NIST P-521 | HKDF-SHA512 | AES-256-GCM |
## Ciphertext Wire Format
The structure of the serialized ECIES ciphertext is defined by `EciesCiphertextComponents::serialize` and is designed to be unambiguous and secure.
The format is: `R_len || R || N_len || N || CT_len || (C||T)`
* `R_len` (1 byte): The length of the ephemeral public key `R`.
* `R` (variable): The uncompressed ephemeral public key generated by the sender.
* `N_len` (1 byte): The length of the AEAD nonce `N`.
* `N` (variable): The nonce used for the AEAD encryption.
* `CT_len` (4 bytes, big-endian): The length of the AEAD ciphertext and tag `(C||T)`.
* `(C||T)` (variable): The output of the AEAD encryption, containing the encrypted message (`C`) followed by its authentication tag (`T`).
This format ensures that all variable-length components are clearly delimited, preventing parsing ambiguities.
## Usage
While this module contains the core logic, users of the `dcrypt-pke` crate typically interact with the ECIES structs that are re-exported at the crate level.
```rust
// Import the desired ECIES implementation and the Pke trait
use dcrypt_pke::EciesP256;
use dcrypt_api::traits::Pke;
use rand::thread_rng;
// Generate a keypair
let (pk, sk) = EciesP256::keypair(&mut thread_rng()).unwrap();
// Encrypt data
let plaintext = b"secret data";
let ciphertext = EciesP256::encrypt(&pk, plaintext, None, &mut thread_rng()).unwrap();
// Decrypt data
let decrypted = EciesP256::decrypt(&sk, &ciphertext, None).unwrap();
assert_eq!(plaintext, decrypted.as_slice());```