Revert removing ecies (#2009)
* revert removing ECIES without MAC * removed reverted change in encrypt
This commit is contained in:
parent
3e07135df3
commit
09e0842f56
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -290,7 +290,6 @@ version = "1.4.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"clippy 0.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clippy 0.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethabi 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethabi 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethcore-devtools 1.4.0",
|
|
||||||
"ethcore-rpc 1.4.0",
|
"ethcore-rpc 1.4.0",
|
||||||
"ethcore-util 1.4.0",
|
"ethcore-util 1.4.0",
|
||||||
"hyper 0.9.4 (git+https://github.com/ethcore/hyper)",
|
"hyper 0.9.4 (git+https://github.com/ethcore/hyper)",
|
||||||
|
@ -33,6 +33,7 @@ pub const KEY_LENGTH: usize = 32;
|
|||||||
pub const KEY_ITERATIONS: usize = 10240;
|
pub const KEY_ITERATIONS: usize = 10240;
|
||||||
pub const KEY_LENGTH_AES: usize = KEY_LENGTH / 2;
|
pub const KEY_LENGTH_AES: usize = KEY_LENGTH / 2;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
Secp(SecpError),
|
Secp(SecpError),
|
||||||
InvalidMessage,
|
InvalidMessage,
|
||||||
@ -147,9 +148,9 @@ pub mod ecies {
|
|||||||
use rcrypto::sha2::Sha256;
|
use rcrypto::sha2::Sha256;
|
||||||
use rcrypto::hmac::Hmac;
|
use rcrypto::hmac::Hmac;
|
||||||
use rcrypto::mac::Mac;
|
use rcrypto::mac::Mac;
|
||||||
use bigint::hash::FixedHash;
|
use bigint::hash::{FixedHash, H128};
|
||||||
use ethkey::{Random, Generator, Public, Secret};
|
use ethkey::{Random, Generator, Public, Secret};
|
||||||
use {Error, ecdh, aes};
|
use {Error, ecdh, aes, Keccak256};
|
||||||
|
|
||||||
/// Encrypt a message with a public key
|
/// Encrypt a message with a public key
|
||||||
pub fn encrypt(public: &Public, shared_mac: &[u8], plain: &[u8]) -> Result<Vec<u8>, Error> {
|
pub fn encrypt(public: &Public, shared_mac: &[u8], plain: &[u8]) -> Result<Vec<u8>, Error> {
|
||||||
@ -169,9 +170,11 @@ pub mod ecies {
|
|||||||
{
|
{
|
||||||
let msgd = &mut msg[1..];
|
let msgd = &mut msg[1..];
|
||||||
msgd[0..64].copy_from_slice(r.public());
|
msgd[0..64].copy_from_slice(r.public());
|
||||||
|
let iv = H128::random();
|
||||||
|
msgd[64..80].copy_from_slice(&iv);
|
||||||
{
|
{
|
||||||
let cipher = &mut msgd[(64 + 16)..(64 + 16 + plain.len())];
|
let cipher = &mut msgd[(64 + 16)..(64 + 16 + plain.len())];
|
||||||
aes::encrypt(ekey, &[0u8; 16], plain, cipher);
|
aes::encrypt(ekey, &iv, plain, cipher);
|
||||||
}
|
}
|
||||||
let mut hmac = Hmac::new(Sha256::new(), &mkey);
|
let mut hmac = Hmac::new(Sha256::new(), &mkey);
|
||||||
{
|
{
|
||||||
@ -184,6 +187,31 @@ pub mod ecies {
|
|||||||
Ok(msg)
|
Ok(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Encrypt a message with a public key
|
||||||
|
pub fn encrypt_single_message(public: &Public, plain: &[u8]) -> Result<Vec<u8>, Error> {
|
||||||
|
let r = Random.generate().unwrap();
|
||||||
|
let z = try!(ecdh::agree(r.secret(), public));
|
||||||
|
let mut key = [0u8; 32];
|
||||||
|
let mut mkey = [0u8; 32];
|
||||||
|
kdf(&z, &[0u8; 0], &mut key);
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
let mkey_material = &key[16..32];
|
||||||
|
hasher.input(mkey_material);
|
||||||
|
hasher.result(&mut mkey);
|
||||||
|
let ekey = &key[0..16];
|
||||||
|
|
||||||
|
let mut msgd = vec![0u8; (64 + plain.len())];
|
||||||
|
{
|
||||||
|
r.public().copy_to(&mut msgd[0..64]);
|
||||||
|
let iv = H128::from_slice(&z.keccak256()[0..16]);
|
||||||
|
{
|
||||||
|
let cipher = &mut msgd[64..(64 + plain.len())];
|
||||||
|
aes::encrypt(ekey, &iv, plain, cipher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msgd)
|
||||||
|
}
|
||||||
|
|
||||||
/// Decrypt a message with a secret key
|
/// Decrypt a message with a secret key
|
||||||
pub fn decrypt(secret: &Secret, shared_mac: &[u8], encrypted: &[u8]) -> Result<Vec<u8>, Error> {
|
pub fn decrypt(secret: &Secret, shared_mac: &[u8], encrypted: &[u8]) -> Result<Vec<u8>, Error> {
|
||||||
let meta_len = 1 + 64 + 16 + 32;
|
let meta_len = 1 + 64 + 16 + 32;
|
||||||
@ -224,6 +252,33 @@ pub mod ecies {
|
|||||||
Ok(msg)
|
Ok(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Decrypt single message with a secret key
|
||||||
|
pub fn decrypt_single_message(secret: &Secret, encrypted: &[u8]) -> Result<Vec<u8>, Error> {
|
||||||
|
let meta_len = 64;
|
||||||
|
if encrypted.len() < meta_len {
|
||||||
|
return Err(Error::InvalidMessage); //invalid message: publickey
|
||||||
|
}
|
||||||
|
|
||||||
|
let e = encrypted;
|
||||||
|
let p = Public::from_slice(&e[0..64]);
|
||||||
|
let z = try!(ecdh::agree(secret, &p));
|
||||||
|
let mut key = [0u8; 32];
|
||||||
|
kdf(&z, &[0u8; 0], &mut key);
|
||||||
|
let ekey = &key[0..16];
|
||||||
|
let mkey_material = &key[16..32];
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
let mut mkey = [0u8; 32];
|
||||||
|
hasher.input(mkey_material);
|
||||||
|
hasher.result(&mut mkey);
|
||||||
|
|
||||||
|
let clen = encrypted.len() - meta_len;
|
||||||
|
let cipher = &e[64..(64+clen)];
|
||||||
|
let mut msg = vec![0u8; clen];
|
||||||
|
let iv = H128::from_slice(&z.keccak256()[0..16]);
|
||||||
|
aes::decrypt(ekey, &iv, cipher, &mut msg[..]);
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
|
||||||
fn kdf(secret: &Secret, s1: &[u8], dest: &mut [u8]) {
|
fn kdf(secret: &Secret, s1: &[u8], dest: &mut [u8]) {
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
// SEC/ISO/Shoup specify counter size SHOULD be equivalent
|
// SEC/ISO/Shoup specify counter size SHOULD be equivalent
|
||||||
@ -244,3 +299,35 @@ pub mod ecies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use ethkey::{Random, Generator};
|
||||||
|
use ecies;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ecies_shared() {
|
||||||
|
let kp = Random.generate().unwrap();
|
||||||
|
let message = b"So many books, so little time";
|
||||||
|
|
||||||
|
let shared = b"shared";
|
||||||
|
let wrong_shared = b"incorrect";
|
||||||
|
let encrypted = ecies::encrypt(kp.public(), shared, message).unwrap();
|
||||||
|
assert!(encrypted[..] != message[..]);
|
||||||
|
assert_eq!(encrypted[0], 0x04);
|
||||||
|
|
||||||
|
assert!(ecies::decrypt(kp.secret(), wrong_shared, &encrypted).is_err());
|
||||||
|
let decrypted = ecies::decrypt(kp.secret(), shared, &encrypted).unwrap();
|
||||||
|
assert_eq!(decrypted[..message.len()], message[..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ecies_shared_single() {
|
||||||
|
let kp = Random.generate().unwrap();
|
||||||
|
let message = b"So many books, so little time";
|
||||||
|
let encrypted = ecies::encrypt_single_message(kp.public(), message).unwrap();
|
||||||
|
assert!(encrypted[..] != message[..]);
|
||||||
|
let decrypted = ecies::decrypt_single_message(kp.secret(), &encrypted).unwrap();
|
||||||
|
assert_eq!(decrypted[..message.len()], message[..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user