Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

[whisper] Move needed aes_gcm crypto in-crate #10647

Merged
merged 1 commit into from
May 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion whisper/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ bitflags = "0.9"
byteorder = "1.0.0"
ethereum-types = "0.4"
ethcore-network = { path = "../util/network" }
parity-crypto = "0.3.0"
ring = "0.14.6"
ethkey = { path = "../accounts/ethkey" }
hex = "0.2"
log = "0.4"
Expand Down
113 changes: 113 additions & 0 deletions whisper/src/aes_gcm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

use ring;

/// AES GCM encryptor.
pub struct Encryptor<'a> {
key: ring::aead::SealingKey,
ad: &'a [u8],
offset: usize,
}

impl<'a> Encryptor<'a> {
pub fn aes_256_gcm(key: &[u8; 32]) -> Result<Encryptor<'a>, ring::error::Unspecified> {
let sk = ring::aead::SealingKey::new(&ring::aead::AES_256_GCM, key)?;
Ok(Encryptor {
key: sk,
ad: &[],
offset: 0,
})
}

/// Optional offset value. Only the slice `[offset..]` will be encrypted.
pub fn offset(&mut self, off: usize) -> &mut Self {
self.offset = off;
self
}

/// Please note that the pair (key, nonce) must never be reused. Using random nonces
/// limits the number of messages encrypted with the same key to 2^32 (cf. [[1]])
///
/// [1]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
pub fn encrypt(&self, nonce: &[u8; 12], mut data: Vec<u8>) -> Result<Vec<u8>, ring::error::Unspecified> {
if self.offset > data.len() {
return Err(ring::error::Unspecified)
}
let tag_len = ring::aead::AES_256_GCM.tag_len();
data.extend(::std::iter::repeat(0).take(tag_len));
let nonce = ring::aead::Nonce::assume_unique_for_key(*nonce);
let aad = ring::aead::Aad::from(self.ad);
let len = ring::aead::seal_in_place(&self.key, nonce, aad, &mut data[self.offset ..], tag_len)?;
data.truncate(self.offset + len);
Ok(data)
}
}

/// AES GCM decryptor.
pub struct Decryptor<'a> {
key: ring::aead::OpeningKey,
ad: &'a [u8],
offset: usize,
}

impl<'a> Decryptor<'a> {
pub fn aes_256_gcm(key: &[u8; 32]) -> Result<Decryptor<'a>, ring::error::Unspecified> {
let ok = ring::aead::OpeningKey::new(&ring::aead::AES_256_GCM, key)?;
Ok(Decryptor {
key: ok,
ad: &[],
offset: 0,
})
}

pub fn decrypt(&self, nonce: &[u8; 12], mut data: Vec<u8>) -> Result<Vec<u8>, ring::error::Unspecified> {
if self.offset > data.len() {
return Err(ring::error::Unspecified)
}
let nonce = ring::aead::Nonce::assume_unique_for_key(*nonce);
let aad = ring::aead::Aad::from(self.ad);
let len = ring::aead::open_in_place(&self.key, nonce, aad, 0, &mut data[self.offset ..])?.len();
data.truncate(self.offset + len);
Ok(data)
}
}

#[cfg(test)]
mod tests {
use super::{Encryptor, Decryptor};

#[test]
fn aes_gcm_256() {
let secret = b"12345678901234567890123456789012";
let nonce = b"123456789012";
let message = b"So many books, so little time";

let ciphertext = Encryptor::aes_256_gcm(secret)
.unwrap()
.encrypt(nonce, message.to_vec())
.unwrap();

assert!(ciphertext != message);

let plaintext = Decryptor::aes_256_gcm(secret)
.unwrap()
.decrypt(nonce, ciphertext)
.unwrap();

assert_eq!(plaintext, message)
}
}
4 changes: 3 additions & 1 deletion whisper/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#![cfg_attr(feature = "time_checked_add", feature(time_checked_add))]

extern crate byteorder;
extern crate parity_crypto as crypto;
extern crate ethcore_network as network;
extern crate ethereum_types;
extern crate ethkey;
Expand All @@ -29,6 +28,7 @@ extern crate memzero;
extern crate ordered_float;
extern crate parking_lot;
extern crate rand;
extern crate ring;
extern crate rlp;
extern crate serde;
extern crate slab;
Expand Down Expand Up @@ -60,3 +60,5 @@ pub use self::net::{Network, MessageHandler};
pub mod message;
pub mod net;
pub mod rpc;

mod aes_gcm;
4 changes: 2 additions & 2 deletions whisper/src/rpc/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

//! Encryption schemes supported by RPC layer.

use crypto::aes_gcm::{Encryptor, Decryptor};
use aes_gcm::{Encryptor, Decryptor};
use ethkey::crypto::ecies;
use ethereum_types::H256;
use ethkey::{self, Public, Secret};
Expand Down Expand Up @@ -77,7 +77,7 @@ impl EncryptionInstance {
EncryptionInner::AES(key, nonce, encode) => {
match encode {
AesEncode::AppendedNonce => {
let mut enc = Encryptor::aes_256_gcm(&*key).ok()?;
let enc = Encryptor::aes_256_gcm(&*key).ok()?;
let mut buf = enc.encrypt(&nonce, plain.to_vec()).ok()?;
buf.extend(&nonce[..]);
Some(buf)
Expand Down