ECIES without MAC (#1948)
* Use random IV for ECIES AES * ECIES encrypt/decrypt for a single message * Derive IV from shared secret
This commit is contained in:
parent
d279794c32
commit
8159d743ef
@ -311,6 +311,7 @@ pub mod ecies {
|
|||||||
use hash::*;
|
use hash::*;
|
||||||
use bytes::*;
|
use bytes::*;
|
||||||
use crypto::*;
|
use crypto::*;
|
||||||
|
use sha3::Hashable;
|
||||||
|
|
||||||
/// 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<Bytes, CryptoError> {
|
pub fn encrypt(public: &Public, shared_mac: &[u8], plain: &[u8]) -> Result<Bytes, CryptoError> {
|
||||||
@ -334,9 +335,11 @@ pub mod ecies {
|
|||||||
{
|
{
|
||||||
let msgd = &mut msg[1..];
|
let msgd = &mut msg[1..];
|
||||||
r.public().copy_to(&mut msgd[0..64]);
|
r.public().copy_to(&mut msgd[0..64]);
|
||||||
|
let iv = H128::random();
|
||||||
|
iv.copy_to(&mut msgd[64..(64+16)]);
|
||||||
{
|
{
|
||||||
let cipher = &mut msgd[(64 + 16)..(64 + 16 + plain.len())];
|
let cipher = &mut msgd[(64 + 16)..(64 + 16 + plain.len())];
|
||||||
aes::encrypt(ekey, &H128::new(), plain, cipher);
|
aes::encrypt(ekey, &iv, plain, cipher);
|
||||||
}
|
}
|
||||||
let mut hmac = Hmac::new(Sha256::new(), &mkey);
|
let mut hmac = Hmac::new(Sha256::new(), &mkey);
|
||||||
{
|
{
|
||||||
@ -349,6 +352,33 @@ pub mod ecies {
|
|||||||
Ok(msg)
|
Ok(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Encrypt a message with a public key
|
||||||
|
pub fn encrypt_single_message(public: &Public, plain: &[u8]) -> Result<Bytes, CryptoError> {
|
||||||
|
use ::rcrypto::digest::Digest;
|
||||||
|
use ::rcrypto::sha2::Sha256;
|
||||||
|
let r = try!(KeyPair::create());
|
||||||
|
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.sha3()[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<Bytes, CryptoError> {
|
pub fn decrypt(secret: &Secret, shared_mac: &[u8], encrypted: &[u8]) -> Result<Bytes, CryptoError> {
|
||||||
use ::rcrypto::digest::Digest;
|
use ::rcrypto::digest::Digest;
|
||||||
@ -394,6 +424,36 @@ pub mod ecies {
|
|||||||
Ok(msg)
|
Ok(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Decrypt single message with a secret key
|
||||||
|
pub fn decrypt_single_message(secret: &Secret, encrypted: &[u8]) -> Result<Bytes, CryptoError> {
|
||||||
|
use ::rcrypto::digest::Digest;
|
||||||
|
use ::rcrypto::sha2::Sha256;
|
||||||
|
|
||||||
|
let meta_len = 64;
|
||||||
|
if encrypted.len() < meta_len {
|
||||||
|
return Err(CryptoError::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.sha3()[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]) {
|
||||||
use ::rcrypto::digest::Digest;
|
use ::rcrypto::digest::Digest;
|
||||||
use ::rcrypto::sha2::Sha256;
|
use ::rcrypto::sha2::Sha256;
|
||||||
@ -487,4 +547,14 @@ mod tests {
|
|||||||
let decrypted = ecies::decrypt(kp.secret(), shared, &encrypted).unwrap();
|
let decrypted = ecies::decrypt(kp.secret(), shared, &encrypted).unwrap();
|
||||||
assert_eq!(decrypted[..message.len()], message[..]);
|
assert_eq!(decrypted[..message.len()], message[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ecies_shared_single() {
|
||||||
|
let kp = KeyPair::create().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