use digest algorithm from rust-crypto

This commit is contained in:
Y. T. Chung
2016-11-23 00:02:06 +08:00
parent 45f1344c13
commit e1aaa0b49d
6 changed files with 97 additions and 87 deletions

View File

@@ -1,6 +1,6 @@
[package]
name = "shadowsocks-rust"
version = "1.0.1"
version = "1.0.2"
authors = ["Y. T. CHUNG <zonyitoo@gmail.com>"]
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
repository = "https://github.com/zonyitoo/shadowsocks-rust"

View File

@@ -34,7 +34,7 @@ use crypto::rc4_md5;
use crypto::dummy;
use crypto::crypto::CryptoCipher;
use crypto::digest::{self, DigestType};
use crypto::digest::{self, DigestType, Digest};
use openssl::crypto::symm;
@@ -225,31 +225,31 @@ impl CipherType {
/// Extends key to match the required key length
pub fn bytes_to_key(&self, key: &[u8]) -> Vec<u8> {
let iv_len = self.block_size();
let iv_len = self.iv_size();
let key_len = self.key_size();
let mut m: Vec<Vec<u8>> = Vec::with_capacity((key_len + iv_len) / DigestType::Md5.digest_len() + 1);
let mut i = 0;
while m.len() * DigestType::Md5.digest_len() < (key_len + iv_len) {
let mut md5 = digest::with_type(DigestType::Md5);
if i > 0 {
let mut vkey = m[i - 1].clone();
vkey.extend_from_slice(key);
md5.update(&vkey[..]);
} else {
md5.update(key);
}
let mut digest = digest::with_type(DigestType::Md5);
m.push(md5.digest());
i += 1
let mut result = Vec::new();
let mut m = Vec::new();
let mut loop_count = 0;
while loop_count * digest.digest_len() < (key_len + iv_len) {
let mut vkey = m.clone();
vkey.extend_from_slice(key);
digest.update(&vkey);
m.clear();
digest.digest(&mut m);
loop_count += 1;
digest.reset();
result.extend_from_slice(&m[..]);
}
let whole = m.iter().fold(Vec::new(), |mut a, b| {
a.extend_from_slice(b);
a
});
let key = whole[0..key_len].to_vec();
key
result.resize(key_len, 0);
result
}
/// Symmetric crypto initialize vector size

View File

@@ -21,7 +21,8 @@
//! Message digest algorithm
use crypto::openssl;
use rust_crypto::md5::Md5;
use rust_crypto::sha1::Sha1;
/// Digest trait
pub trait Digest: Send {
@@ -29,7 +30,13 @@ pub trait Digest: Send {
fn update(&mut self, data: &[u8]);
/// Generates digest
fn digest(&mut self) -> Vec<u8>;
fn digest(&mut self, buf: &mut Vec<u8>);
/// Length of digest
fn digest_len(&self) -> usize;
/// Reset digest
fn reset(&mut self);
}
/// Type of defined digests
@@ -40,22 +47,61 @@ pub enum DigestType {
Sha,
}
impl DigestType {
/// Length of digest
pub fn digest_len(&self) -> usize {
match *self {
DigestType::Md5 => 16,
DigestType::Sha1 => 20,
DigestType::Sha => 20,
}
/// Create digest with type
pub fn with_type(t: DigestType) -> DigestVariant {
match t {
DigestType::Md5 => DigestVariant::Md5(Md5::new()),
DigestType::Sha1 | DigestType::Sha => DigestVariant::Sha1(Sha1::new()),
}
}
/// Create digest with type
pub fn with_type(t: DigestType) -> Box<Digest + Send> {
match t {
DigestType::Md5 | DigestType::Sha1 | DigestType::Sha => {
Box::new(openssl::OpenSSLDigest::new(t)) as Box<Digest + Send>
/// Variant of supported digest
pub enum DigestVariant {
Md5(Md5),
Sha1(Sha1),
}
impl Digest for DigestVariant {
fn update(&mut self, data: &[u8]) {
use rust_crypto::digest::Digest;
match self {
&mut DigestVariant::Md5(ref mut d) => d.input(data),
&mut DigestVariant::Sha1(ref mut d) => d.input(data),
}
}
}
fn digest(&mut self, buf: &mut Vec<u8>) {
use rust_crypto::digest::Digest;
let output_bytes = match &*self {
&DigestVariant::Md5(ref d) => d.output_bytes(),
&DigestVariant::Sha1(ref d) => d.output_bytes(),
};
let orig_len = buf.len();
buf.resize(orig_len + output_bytes, 0);
match self {
&mut DigestVariant::Md5(ref mut d) => d.result(&mut buf[orig_len..]),
&mut DigestVariant::Sha1(ref mut d) => d.result(&mut buf[orig_len..]),
}
}
fn digest_len(&self) -> usize {
use rust_crypto::digest::Digest;
match self {
&DigestVariant::Md5(ref d) => d.output_bytes(),
&DigestVariant::Sha1(ref d) => d.output_bytes(),
}
}
fn reset(&mut self) {
use rust_crypto::digest::Digest;
match self {
&mut DigestVariant::Md5(ref mut d) => d.reset(),
&mut DigestVariant::Sha1(ref mut d) => d.reset(),
}
}
}

View File

@@ -22,17 +22,13 @@
//! Cipher defined with Rust binding for libcrypto (OpenSSL)
use std::convert::From;
use std::io::Write;
use crypto::cipher::{Cipher, CipherType, CipherResult};
use crypto::cipher;
use crypto::digest::Digest;
use crypto::digest;
use crypto::CryptoMode;
use openssl::crypto::symm;
use openssl::crypto::hash;
/// Core cipher of OpenSSL
pub struct OpenSSLCrypto {
@@ -148,34 +144,3 @@ impl Cipher for OpenSSLCipher {
self.worker.finalize(out)
}
}
/// Digest provided by OpenSSL
pub struct OpenSSLDigest {
inner: hash::Hasher,
}
impl OpenSSLDigest {
/// Creates by type
pub fn new(t: digest::DigestType) -> OpenSSLDigest {
let t = match t {
digest::DigestType::Md5 => hash::Type::MD5,
digest::DigestType::Sha => hash::Type::SHA512,
digest::DigestType::Sha1 => hash::Type::SHA1,
};
OpenSSLDigest { inner: hash::Hasher::new(t).unwrap() }
}
}
unsafe impl Send for OpenSSLDigest {}
impl Digest for OpenSSLDigest {
fn update(&mut self, data: &[u8]) {
let _ = self.inner.write(data);
}
fn digest(&mut self) -> Vec<u8> {
// TODO: Check error
self.inner.finish().unwrap()
}
}

View File

@@ -21,9 +21,9 @@
//! Rc4Md5 cipher definition
use crypto::openssl::{OpenSSLCrypto, OpenSSLDigest};
use crypto::openssl::OpenSSLCrypto;
use crypto::cipher::{Cipher, CipherType, CipherResult};
use crypto::digest::{Digest, DigestType};
use crypto::digest::{self, Digest, DigestType};
use crypto::CryptoMode;
/// Rc4Md5 Cipher
@@ -33,14 +33,13 @@ pub struct Rc4Md5Cipher {
impl Rc4Md5Cipher {
pub fn new(key: &[u8], iv: &[u8], mode: CryptoMode) -> Rc4Md5Cipher {
let mut md5_digest = OpenSSLDigest::new(DigestType::Md5);
let mut md5_digest = digest::with_type(DigestType::Md5);
md5_digest.update(key);
md5_digest.update(iv);
let key = md5_digest.digest();
let mut key = Vec::new();
md5_digest.digest(&mut key);
Rc4Md5Cipher {
crypto: OpenSSLCrypto::new(CipherType::Rc4, &key[..], b"", mode)
}
Rc4Md5Cipher { crypto: OpenSSLCrypto::new(CipherType::Rc4, &key[..], b"", mode) }
}
}
@@ -73,14 +72,14 @@ mod test {
let mut enc = Rc4Md5Cipher::new(key, &iv[..], CryptoMode::Encrypt);
let mut encrypted_msg = Vec::new();
enc.update(msg, &mut encrypted_msg)
.and_then(|_| enc.finalize(&mut encrypted_msg))
.unwrap();
.and_then(|_| enc.finalize(&mut encrypted_msg))
.unwrap();
let mut dec = Rc4Md5Cipher::new(key, &iv[..], CryptoMode::Decrypt);
let mut decrypted_msg = Vec::new();
dec.update(&encrypted_msg[..], &mut decrypted_msg)
.and_then(|_| dec.finalize(&mut decrypted_msg))
.unwrap();
.and_then(|_| dec.finalize(&mut decrypted_msg))
.unwrap();
assert_eq!(msg, &decrypted_msg[..]);
}

View File

@@ -24,8 +24,7 @@
use std::io::BufReader;
use crypto::cipher::{Cipher, CipherResult};
use crypto::digest;
use crypto::digest::DigestType;
use crypto::digest::{self, DigestType, Digest};
use crypto::CryptoMode;
use byteorder::{ReadBytesExt, LittleEndian};
@@ -42,7 +41,8 @@ impl TableCipher {
pub fn new(key: &[u8], mode: CryptoMode) -> TableCipher {
let mut md5_digest = digest::with_type(DigestType::Md5);
md5_digest.update(key);
let key_digest = md5_digest.digest();
let mut key_digest = Vec::new();
md5_digest.digest(&mut key_digest);
let mut bufr = BufReader::new(&key_digest[..]);
let a = bufr.read_u64::<LittleEndian>().unwrap();