Skip to content
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
Cargo.lock

# Generated by Cargo
**/target/
12 changes: 11 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,18 @@ edition = "2018"
[dependencies]
ring = "0.14.6"
quick-error = "1.2"
rust-crypto = "0.2.36"
primitives = { git = "https://github.com/CodeChain-io/rust-codechain-primitives.git", version = "0.4" }
sha-1 = "0.8.2"
sha2 = "0.8.1"
sha3 = "0.8.2"
ripemd160 = "0.8.0"
digest = "0.8"
blake2 = "0.8.1"
block-modes = "0.3.3"
aes = "0.3.2"
ctr = "0.3.2"
hex = "0.4.0"
scrypt = { version = "0.2", default-features = false }

[dev-dependencies]
rand = "0.6.1"
99 changes: 53 additions & 46 deletions src/aes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,68 +14,45 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use aes::{Aes128, Aes256};
use block_modes::block_padding::Pkcs7;
use block_modes::InvalidKeyIvLength;
use block_modes::{BlockMode, Cbc};
use ctr;
use ctr::stream_cipher::generic_array::GenericArray;
use ctr::stream_cipher::{NewStreamCipher, SyncStreamCipher, SyncStreamCipherSeek};
use primitives::H256;
use rcrypto::aes::KeySize::KeySize256;
use rcrypto::aes::{cbc_decryptor, cbc_encryptor};
use rcrypto::aessafe::AesSafe128Encryptor;
use rcrypto::blockmodes::{CtrMode, PkcsPadding};
use rcrypto::buffer::{BufferResult, ReadBuffer, RefReadBuffer, RefWriteBuffer, WriteBuffer};
pub use rcrypto::symmetriccipher::SymmetricCipherError;
use rcrypto::symmetriccipher::{Decryptor, Encryptor};

use super::error::SymmError;

fn is_underflow(result: BufferResult) -> bool {
match result {
BufferResult::BufferUnderflow => true,
BufferResult::BufferOverflow => false,
}
}

// AES-256/CBC/Pkcs encryption.
pub fn encrypt(data: &[u8], key: &H256, iv: &u128) -> Result<Vec<u8>, SymmetricCipherError> {
let mut encryptor = cbc_encryptor(KeySize256, key, &iv.to_be_bytes(), PkcsPadding);

let mut final_result = Vec::<u8>::new();
let mut read_buffer = RefReadBuffer::new(data);
let mut buffer = [0; 4096];
let mut write_buffer = RefWriteBuffer::new(&mut buffer);

type Aes256Cbc = Cbc<Aes256, Pkcs7>;
type Aes128Ctr = ctr::Ctr128<Aes128>;

let mut finish = false;
while !finish {
finish = is_underflow(encryptor.encrypt(&mut read_buffer, &mut write_buffer, true)?);
final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().cloned());
}
// AES-256/CBC/Pkcs encryption.
pub fn encrypt(data: &[u8], key: &H256, iv: &u128) -> Result<Vec<u8>, InvalidKeyIvLength> {
let cipher = Aes256Cbc::new_var(&key, &iv.to_be_bytes())?;
let result = cipher.encrypt_vec(data);

Ok(final_result)
Ok(result)
}

// AES-256/CBC/Pkcs decryption.
pub fn decrypt(encrypted_data: &[u8], key: &H256, iv: &u128) -> Result<Vec<u8>, SymmetricCipherError> {
let mut decryptor = cbc_decryptor(KeySize256, key, &iv.to_be_bytes(), PkcsPadding);

let mut final_result = Vec::<u8>::new();
let mut read_buffer = RefReadBuffer::new(encrypted_data);
let mut buffer = [0; 4096];
let mut write_buffer = RefWriteBuffer::new(&mut buffer);

let mut finish = false;
while !finish {
finish = is_underflow(decryptor.decrypt(&mut read_buffer, &mut write_buffer, true)?);
final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().cloned());
}
pub fn decrypt(encrypted_data: &[u8], key: &H256, iv: &u128) -> Result<Vec<u8>, InvalidKeyIvLength> {
let cipher = Aes256Cbc::new_var(&key, &iv.to_be_bytes())?;
let result = cipher.decrypt_vec(&encrypted_data.to_vec()).unwrap();

Ok(final_result)
Ok(result)
}

/// Encrypt a message (CTR mode).
///
/// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each.
/// An error is returned if the input lengths are invalid.
pub fn encrypt_128_ctr(k: &[u8], iv: &[u8], plain: &[u8], dest: &mut [u8]) -> Result<(), SymmError> {
let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec());
encryptor.encrypt(&mut RefReadBuffer::new(plain), &mut RefWriteBuffer::new(dest), true)?;
let mut cipher = Aes128Ctr::new(&GenericArray::from_slice(k), &GenericArray::from_slice(iv));
dest.copy_from_slice(plain);
cipher.apply_keystream(dest);
Ok(())
}

Expand All @@ -84,8 +61,10 @@ pub fn encrypt_128_ctr(k: &[u8], iv: &[u8], plain: &[u8], dest: &mut [u8]) -> Re
/// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each.
/// An error is returned if the input lengths are invalid.
pub fn decrypt_128_ctr(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) -> Result<(), SymmError> {
let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec());
encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true)?;
let mut cipher = Aes128Ctr::new(&GenericArray::from_slice(k), &GenericArray::from_slice(iv));
dest.copy_from_slice(encrypted);
cipher.seek(0);
cipher.apply_keystream(dest);
Ok(())
}

Expand Down Expand Up @@ -146,4 +125,32 @@ mod tests {
let decrypted = decrypt(&encrypted, &key, &iv).unwrap();
assert_eq!(input, decrypted);
}

#[test]
fn aes_256_cbc_encrypt_decrypt() {
let message = [1, 2, 3, 4, 5, 6, 7, 8];
let key = H256([0; 32]);
let iv = 0;

let encrypted_data = encrypt(&message, &key, &iv).ok().unwrap();
assert_eq!(encrypted_data, [45, 34, 87, 122, 38, 50, 190, 242, 253, 245, 138, 7, 196, 24, 58, 91]);

let decrypted_data = decrypt(&encrypted_data[..], &key, &iv).ok().unwrap();
assert_eq!(message, &decrypted_data[..]);
}

#[test]
fn aes_128_ctr_encrypt_decrypt() {
let plaintext = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let key = [1; 16];
let iv = [1; 16];
let mut dest = [0; 10];

let _ = encrypt_128_ctr(&key, &iv, &plaintext, &mut dest);
assert_eq!(dest, [94, 118, 231, 156, 139, 128, 146, 51, 129, 171]);

let ciphertext = dest;
let _ = decrypt_128_ctr(&key, &iv, &ciphertext, &mut dest);
assert_eq!(plaintext, dest);
}
}
29 changes: 12 additions & 17 deletions src/blake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use blake2::digest::{Input, VariableOutput};
use blake2::VarBlake2b;
use primitives::{H128, H160, H256, H512};
use rcrypto::blake2b::Blake2b;
use rcrypto::digest::Digest;

/// BLAKE128
pub fn blake128<T: AsRef<[u8]>>(s: T) -> H128 {
Expand Down Expand Up @@ -51,32 +51,27 @@ pub trait Blake {
}

macro_rules! implement_blake {
($self:ident) => {
($self:ident, $size:expr) => {
impl Blake for $self {
fn blake<T: AsRef<[u8]>>(s: T) -> Self {
let input = s.as_ref();
let mut result = Self::default();
let mut hasher = Blake2b::new(result.len());
hasher.input(input);
hasher.result(&mut *result);
result
Self::blake_with_key(s, &[])
}
fn blake_with_key<T: AsRef<[u8]>>(s: T, key: &[u8]) -> Self {
let input = s.as_ref();
let mut result = Self::default();
let mut hasher = Blake2b::new_keyed(result.len(), &key);
let mut hasher = VarBlake2b::new_keyed(&key, $size);
hasher.input(input);
hasher.result(&mut *result);
result
let mut result: [u8; $size] = [0; $size];
result.copy_from_slice(&hasher.vec_result());
Self(result)
}
}
};
}

implement_blake!(H128);
implement_blake!(H160);
implement_blake!(H256);
implement_blake!(H512);
implement_blake!(H128, 16);
implement_blake!(H160, 20);
implement_blake!(H256, 32);
implement_blake!(H512, 64);

/// Get the 256-bits BLAKE2b hash of the empty bytes string.
pub const BLAKE_EMPTY: H256 = H256([
Expand Down
26 changes: 22 additions & 4 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,24 @@ quick_error! {
InvalidP {
display("Invalid p argument of the scrypt encryption")
}
InvalidOutputLen {
display("Invalid length of output")
}
InvalidParams {
display("Invalid parameters")
}
}
}

#[allow(deprecated)]
mod errors {
use rcrypto;
use crate::error::ScryptError;
use ring;

quick_error! {
#[derive(Debug)]
pub enum SymmError wraps PrivSymmErr {
RustCrypto(e: rcrypto::symmetriccipher::SymmetricCipherError) {
RustCrypto(e: block_modes::InvalidKeyIvLength) {
display("symmetric crypto error")
from()
}
Expand All @@ -74,10 +80,22 @@ mod errors {
}
}

impl From<rcrypto::symmetriccipher::SymmetricCipherError> for SymmError {
fn from(e: rcrypto::symmetriccipher::SymmetricCipherError) -> SymmError {
impl From<block_modes::InvalidKeyIvLength> for SymmError {
fn from(e: block_modes::InvalidKeyIvLength) -> SymmError {
SymmError(PrivSymmErr::RustCrypto(e))
}
}

impl From<scrypt::errors::InvalidOutputLen> for ScryptError {
fn from(_e: scrypt::errors::InvalidOutputLen) -> ScryptError {
ScryptError::InvalidOutputLen
}
}

impl From<scrypt::errors::InvalidParams> for ScryptError {
fn from(_e: scrypt::errors::InvalidParams) -> ScryptError {
ScryptError::InvalidParams
}
}
}
pub use self::errors::SymmError;
36 changes: 18 additions & 18 deletions src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,55 +14,55 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use digest::Digest;
use primitives::{H160, H256};
use rcrypto::digest::Digest;
use rcrypto::ripemd160::Ripemd160;
use rcrypto::sha1::Sha1;
use rcrypto::sha2::Sha256;
use rcrypto::sha3::Sha3;
use ripemd160::Ripemd160;
use sha1::Sha1;
use sha2::Sha256;
use sha3::Keccak256;

/// RIPEMD160
#[inline]
pub fn ripemd160<T: AsRef<[u8]>>(s: T) -> H160 {
let input = s.as_ref();
let mut result = H160::default();
let mut hasher = Ripemd160::new();
hasher.input(input);
hasher.result(&mut *result);
result
let mut array: [u8; 20] = [0; 20];
array.copy_from_slice(&hasher.result());
H160(array)
}

/// SHA-1
#[inline]
pub fn sha1<T: AsRef<[u8]>>(s: T) -> H160 {
let input = s.as_ref();
let mut result = H160::default();
let mut hasher = Sha1::new();
hasher.input(input);
hasher.result(&mut *result);
result
let mut array: [u8; 20] = [0; 20];
array.copy_from_slice(&hasher.result());
H160(array)
}

/// SHA-256
#[inline]
pub fn sha256<T: AsRef<[u8]>>(s: T) -> H256 {
let input = s.as_ref();
let mut result = H256::default();
let mut hasher = Sha256::new();
hasher.input(input);
hasher.result(&mut *result);
result
let mut array: [u8; 32] = [0; 32];
array.copy_from_slice(&hasher.result());
H256(array)
}

/// KECCAK256
#[inline]
pub fn keccak256<T: AsRef<[u8]>>(s: T) -> H256 {
let input = s.as_ref();
let mut result = H256::default();
let mut hasher = Sha3::keccak256();
let mut hasher = Keccak256::new();
hasher.input(input);
hasher.result(&mut result);
result
let mut array: [u8; 32] = [0; 32];
array.copy_from_slice(&hasher.result());
H256(array)
}

#[cfg(test)]
Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.


extern crate crypto as rcrypto;
extern crate primitives;
#[macro_use]
extern crate quick_error;
Expand Down
Loading