Adding asymetric encryption proof of concept

This commit is contained in:
David E. Perez Negron R. 2024-05-21 22:26:18 -06:00
parent d7eb76e7e8
commit ccd2f2ef03
5 changed files with 146 additions and 2 deletions

12
Cargo.toml Normal file
View File

@ -0,0 +1,12 @@
[package]
name = "meca"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ethers = "2.0.11"
tokio = { version = "1.35.0", features = ["full", "rt-multi-thread"] }
dotenv = "0.15"
ecies = {version = "0.2.7", default-features = false, features = ["xchacha20"]}

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2024 p1r0
Copyright (c) 2024 David E. Perez Negron R.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -1,3 +1,19 @@
# MECA
Make Ethereum Cypherpunk Again: Asymmetric Encryption using an EOA, by using the ECIES on ECDSA
Make Ethereum Cypherpunk Again: Asymmetric Encryption using an EOA, by using the ECIES on ECDSA
## Use Case Example
1. Bob and Alice publish their ecdsa key paired with his public address in a smart contract
2. Alice gets Bob public address and ecdsa key.
3. Alice writes a message to Bob.
4. Alice encrypts the message using ecies with ecdsa bobs public address
5. Alice stores the encrypted message in IPFS and gets an CID.
6. Alice signs an push a transaction with the encrypted message CID using Bobs public ethereum address
7. Bob verifies signature and get the CID file fetching it from IPFS.
8. Bob decripts the CID fetche message using his ecdsa private key.
## References
1. https://eips.ethereum.org/EIPS/eip-5630
2. https://docs.rs/ecies/0.2.7/ecies/index.html
3. https://ethereum.stackexchange.com/questions/56253/where-does-ethereum-store-eoas-and-public-keys

29
env.example Normal file
View File

@ -0,0 +1,29 @@
# Deploy
PROVIDER_URL="HTTP://127.0.0.1:8545"
CHAIN_ID=31337
SC_ADDR="0x5FbDB2315678afecb367f032d93F642f64180aa3"
# Anvil Accounts
ACC0="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
ACC1="0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
ACC2="0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"
ACC3="0x90F79bf6EB2c4f870365E785982E1f101E93b906"
ACC4="0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65"
ACC5="0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc"
ACC6="0x976EA74026E726554dB657fA54763abd0C3a0aa9"
ACC7="0x14dC79964da2C08b23698B3D3cc7Ca32193d9955"
ACC8="0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f"
ACC9="0xa0Ee7A142d267C1f36714E4a8F75612F20a79720"
# Anvil Private Keys
PK0="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
PK1="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
PK2="0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a"
PK3="0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6"
PK4="0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a"
PK5="0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba"
PK6="0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e"
PK7="0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356"
PK8="0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97"
PK9="0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6"

87
src/main.rs Normal file
View File

@ -0,0 +1,87 @@
use ethers::core::k256::ecdsa::VerifyingKey;
use ethers::prelude::*;
use ethers::utils;
use ecies;
use dotenv::dotenv;
use std::env;
fn main() {
// Until now we just do a Proof of concept of ecdsa_ecies encryption/decryption.
// 1. Alice and Bob exchange their public address and ecdsa key.
// 2. Alice writes a message to Bob.
// 3. Alice encrypts the message using ecies with ecdsa bobs public address
// 4. Bob decripts the using his ecdsa private key.
// Alice = account 1
// Bob = account 2
// ToDo. Add the signature section to verify the message
// Step 1: Fetch ecdsa Private Keys (Ethereum Private Keys from .env)
dotenv().ok();
let private_key_1: String = env::var("PK0").unwrap().parse()
.expect("error fetching the env variable PK0");
let private_key_2: String = env::var("PK1").unwrap().parse()
.expect("error fetching the env variable PK0");
// Create a wallets from the private key
let wallet_1: LocalWallet = private_key_1.parse().unwrap();
let wallet_2: LocalWallet = private_key_2.parse().unwrap();
// Private Keys as non zero scalar
println!("Signer1 Private Key is: {}", wallet_1.signer().as_nonzero_scalar());
println!("Signer2 Private Key is: {}", wallet_2.signer().as_nonzero_scalar());
// Access the full ecdsa public key
// NOTE: this is public key is the required for ECIES to provide
// asymmetric encryption
let ecdsa_public_key_1 = wallet_1.signer().verifying_key();
let ecdsa_public_key_2 = wallet_2.signer().verifying_key();
// Print the full uncompressed ECDSA public key
println!("Full Public Key of signer 1: {}", ecdsa_public_key_1.to_encoded_point(false));
println!("Full Public Key of signer 2: {}", ecdsa_public_key_2.to_encoded_point(false));
// Print Full Public Address (without checksum) 32 Bytes keccak256 digest
// Ethereum Wallet Conversion public key 1
println!("Account1 eth address(full keccak256 digest): {:?}", public_key_to_full_address(ecdsa_public_key_1));
println!("Account2 eth address(full keccak256 digest): {:?}", public_key_to_full_address(ecdsa_public_key_2));
// TODO verify checksum
// https://github.com/ethereum/ercs/blob/master/ERCS/erc-55.md
// Print Ethereum address (unsure if has checksum)
let address_1 = utils::public_key_to_address(ecdsa_public_key_1);
let address_2 = utils::public_key_to_address(ecdsa_public_key_2);
println!("Address 1: {:?}", address_1);
println!("Address 2: {:?}", address_2);
// Step 2: Encrypt a message using ECIES with public key of address2
let message = b"Bob. Lets make Ethereum Cypherpunk Again!";
let encrypted_message = ecies::encrypt(&ecdsa_public_key_2
.to_encoded_point(false)
.as_bytes()[1..], message)
.expect("Encryption failed");
println!("Encrypted message: {:?}", encrypted_message);
let signer_2_private_key=wallet_2.signer().as_nonzero_scalar().to_bytes();
// Step 4: Decrypt the message using private key of address2
let decrypted_message = ecies::decrypt(&signer_2_private_key, &encrypted_message)
.expect("Decryption failed");
println!("Decrypted message: {:?}", std::str::from_utf8(&decrypted_message).unwrap());
}
pub fn public_key_to_full_address(pubkey: &VerifyingKey) -> H256 {
let pubkey = pubkey.to_encoded_point(false);
let pubkey = &pubkey.as_bytes()[1..];
assert_eq!(pubkey.len(), 64, "raw public key must be 64 bytes");
let digest = utils::keccak256(pubkey);
H256::from_slice(&digest)
}
//ToDo
//pub fn ecdsa_pk_to_ecies(pubkey: &VerifyingKey) -> [u8] {
//}