Last active
October 27, 2022 00:12
-
-
Save lrvick/d1682c57a79ca71b5dcf85989dc58e12 to your computer and use it in GitHub Desktop.
Example of basic AES256 envelope encryption using ECDH via NIST p-256 in Rust.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "ecdh_p256" | |
version = "1.0.0" | |
[dependencies] | |
p256={version = "0.11.1", features = ["ecdh"]} | |
hex="0.4.3" | |
aes-gcm="0.10.1" | |
rand_chacha="0.3.1" | |
rand="0.8.5" | |
sha2="0.10.6" | |
[[bin]] | |
name="main" | |
path="main.rs" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate p256; | |
extern crate aes_gcm; | |
extern crate rand; | |
extern crate rand_chacha; | |
extern crate sha2; | |
use p256::{EncodedPoint, PublicKey, ecdh::EphemeralSecret}; | |
use aes_gcm::{Nonce, KeyInit, Aes256Gcm}; | |
use aes_gcm::aes::cipher::consts::U12; | |
use aes_gcm::aead::{Aead}; | |
use rand::{RngCore,SeedableRng}; | |
use rand_chacha::ChaCha20Rng; | |
use sha2::{Sha512,Digest}; | |
fn main() { | |
// Choose a simple RNG source | |
let mut rng: ChaCha20Rng = ChaCha20Rng::from_entropy(); | |
// Alice generates a random asymmetric keypair | |
let alice_private = EphemeralSecret::random(&mut rng); | |
let alice_private_ep = EncodedPoint::from(alice_private.public_key()); | |
let alice_public = PublicKey::from_sec1_bytes(alice_private_ep.as_ref()).expect("Alice's public key invalid"); | |
println!("\nAlice public key {:x?}",hex::encode(alice_private_ep.as_ref())); | |
// Bob generates a random asymmetric keypair | |
let bob_private = EphemeralSecret::random(&mut rng); | |
let bob_private_ep = EncodedPoint::from(bob_private.public_key()); | |
let bob_public = PublicKey::from_sec1_bytes(bob_private_ep.as_ref()).expect("Bob's public key invalid"); | |
println!("\nBob public key {:x?}",hex::encode(bob_private_ep.as_ref())); | |
// Alice and bob agree on a shared one-time-use number as a nonce. | |
let nonce_bytes_as_u32: Vec<u32> = (0..3).map(|_| rng.next_u32()).collect(); | |
let nonce_bytes: Vec<u8> = nonce_bytes_as_u32.iter().flat_map(|x| x.to_be_bytes()).collect(); | |
let nonce = Nonce::<U12>::from_slice(&nonce_bytes); | |
// Bob generates a shared secret using Alice's public key via Diffie Hellman | |
let bob_shared_dh = bob_private.diffie_hellman(&alice_public); | |
let bob_shared_bytes = bob_shared_dh.raw_secret_bytes(); | |
let bob_shared_sha512 = Sha512::digest(&bob_shared_bytes).to_vec(); | |
let bob_shared_secret = &bob_shared_sha512[..32]; | |
// Bob generates a shared AES key from this shared secret with the shared IV | |
let bob_shared_cipher = Aes256Gcm::new_from_slice(&bob_shared_secret).unwrap(); | |
//// Bob encrypts a secret to Alice with the shared AES key | |
let message = String::from("Secret message"); | |
let encrypted_message = bob_shared_cipher.encrypt(nonce, message.as_bytes()).unwrap(); | |
println!("\nEncrypted message: {:?}",hex::encode(&encrypted_message)); | |
// Alice derives the same shared secret as Bob | |
let alice_shared_dh = alice_private.diffie_hellman(&bob_public); | |
let alice_shared_bytes = alice_shared_dh.raw_secret_bytes(); | |
let alice_shared_sha512 = Sha512::digest(&alice_shared_bytes).to_vec(); | |
let alice_shared_secret = &alice_shared_sha512[..32]; | |
// Alice generates the same AES key as Bob from this shared secret and the shared IV | |
let alice_shared_cipher = Aes256Gcm::new_from_slice(&alice_shared_secret).unwrap(); | |
// Alice decrypts Bob's message | |
let decrypted_message = alice_shared_cipher.decrypt(nonce, &encrypted_message[..]).unwrap(); | |
println!("\nDecrypted message: {:?}",String::from_utf8_lossy(&decrypted_message)); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Alice public key "046c61a6de7b51e771e689e995be8ee0a2bdf5da0a46d192acdac68c064bd3126053509b4570f9499e106044aedc1eb8380fd602294dd18f5249a64db40e862e7f" | |
Bob public key "04bc345ca0b9a18d6e44d8b1d538cede0173d2dafdf97393b92af218b7962331947a6406a817ab108752ee862764fddbd7383b84a91ca81bce40c9785426b71592" | |
Encrypted message: "95e47d6a8a3de04f380e066f8888ab3fb3f876f421e6334a7ee752fc90b3" | |
Decrypted message: "Secret message" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment