add rc4-md5 method, fixed bugs

This commit is contained in:
Y. T. Chung
2014-10-28 02:22:51 +08:00
parent dde336138b
commit 2bb0df72ff
6 changed files with 202 additions and 13 deletions
+4 -3
View File
@@ -16,6 +16,8 @@ default = [
"cipher-cast5-cfb",
"cipher-des-cfb",
"cipher-rc2-cfb",
"cipher-rc4",
"cipher-rc4-md5",
]
cipher-aes-cfb = []
@@ -27,6 +29,8 @@ cipher-cast5-cfb = []
cipher-des-cfb = []
cipher-idea-cfb = []
cipher-rc2-cfb = []
cipher-rc4 = []
cipher-rc4-md5 = []
cipher-seed-cfb = []
[[bin]]
@@ -38,6 +42,3 @@ path = "src/bin/local.rs"
name = "ssserver"
path = "src/bin/server.rs"
[dependencies.rust-crypto]
git = "https://github.com/DaGenix/rust-crypto.git"
+11 -2
View File
@@ -88,10 +88,14 @@ pub const CIPHER_DES_CFB: &'static str = "des-cfb";
pub const CIPHER_IDEA_CFB: &'static str = "idea-cfb";
#[cfg(feature="cipher-rc2-cfb")]
pub const CIPHER_RC2_CFB: &'static str = "rc2-cfb";
#[cfg(feature="cipher-rc4")]
pub const CIPHER_RC4: &'static str = "rc4";
#[cfg(feature="cipher-rc4-md5")]
pub const CIPHER_RC4_MD5: &'static str = "rc4-md5";
#[cfg(feature="cipher-seed-cfb")]
pub const CIPHER_SEED_CFB: &'static str = "seed-cfb";
#[deriving(Clone)]
#[deriving(Clone, Show)]
pub enum CipherType {
CipherTypeUnknown,
@@ -128,7 +132,8 @@ pub enum CipherType {
#[cfg(feature="cipher-des-cfb")] CipherTypeDesCfb,
#[cfg(feature="cipher-idea-cfb")] CipherTypeIdeaCfb,
#[cfg(feature="cipher-rc2-cfb")] CipherTypeRc2Cfb,
#[cfg(feature="cipher-rc4-hmac-md5")] CipherTypeRc4HmacMd5,
#[cfg(feature="cipher-rc4")] CipherTypeRc4,
#[cfg(feature="cipher-rc4-md5")] CipherTypeRc4Md5,
#[cfg(feature="cipher-seed-cfb")] CipherTypeSeedCfb,
}
@@ -234,6 +239,10 @@ pub fn with_name(method: &str, key: &[u8]) -> Option<CipherVariant> {
CIPHER_IDEA_CFB => Some(OpenSSLCrypto(openssl::OpenSSLCipher::new(CipherTypeIdeaCfb, key))),
#[cfg(feature="cipher-rc2-cfb")]
CIPHER_RC2_CFB => Some(OpenSSLCrypto(openssl::OpenSSLCipher::new(CipherTypeRc2Cfb, key))),
#[cfg(feature="cipher-rc4")]
CIPHER_RC4 => Some(OpenSSLCrypto(openssl::OpenSSLCipher::new(CipherTypeRc4, key))),
#[cfg(feature="cipher-rc4-md5")]
CIPHER_RC4_MD5 => Some(OpenSSLCrypto(openssl::OpenSSLCipher::new(CipherTypeRc4Md5, key))),
#[cfg(feature="cipher-seed-cfb")]
CIPHER_SEED_CFB => Some(OpenSSLCrypto(openssl::OpenSSLCipher::new(CipherTypeSeedCfb, key))),
+35
View File
@@ -0,0 +1,35 @@
// The MIT License (MIT)
// Copyright (c) 2014 Y. T. CHUNG
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
pub trait Digest {
fn update(&mut self, data: &[u8]);
fn digest(&mut self) -> Vec<u8>;
}
#[deriving(Clone)]
pub enum DigestType {
Md5,
Sha1,
Sha,
UnknownDigest,
}
+1 -2
View File
@@ -23,8 +23,7 @@
extern crate libc;
extern crate test;
extern crate "rust-crypto" as rust_crypto;
pub mod cipher;
pub mod openssl;
pub mod rust;
pub mod digest;
+151 -4
View File
@@ -28,6 +28,9 @@ extern crate test;
use crypto::cipher::Cipher;
use crypto::cipher;
use crypto::digest::Digest;
use crypto::digest;
use std::ptr;
use std::clone::Clone;
use std::mem::swap;
@@ -37,6 +40,8 @@ type EVP_CIPHER_CTX = *const libc::c_void;
#[allow(non_camel_case_types)]
type EVP_CIPHER = *const libc::c_void;
#[allow(non_camel_case_types)]
type EVP_MD_CTX = *mut libc::c_void;
#[allow(non_camel_case_types)]
type EVP_MD = *const libc::c_void;
#[allow(non_camel_case_types)]
type ENGINE = *const libc::c_void;
@@ -118,13 +123,125 @@ extern {
fn EVP_rc2_cfb64() -> EVP_CIPHER;
#[cfg(feature="cipher-seed-cfb")]
fn EVP_seed_cfb128() -> EVP_CIPHER;
#[cfg(any(feature="cipher-rc4", feature="cipher-rc4-md5"))]
fn EVP_rc4() -> EVP_CIPHER;
// MD
fn EVP_MD_CTX_create() -> EVP_MD_CTX;
fn EVP_MD_CTX_init(ctx: EVP_MD_CTX);
fn EVP_MD_CTX_cleanup(ctx: EVP_MD_CTX);
fn EVP_MD_CTX_destroy(ctx: EVP_MD_CTX);
fn EVP_MD_CTX_copy_ex(out: EVP_MD_CTX, ctx_in: EVP_MD_CTX) -> libc::c_int;
fn EVP_DigestInit_ex(ctx: EVP_MD_CTX, md_type: EVP_MD, engine: ENGINE) -> libc::c_int;
fn EVP_DigestUpdate(ctx: EVP_MD_CTX, d: *const libc::c_void, cnt: libc::size_t) -> libc::c_int;
fn EVP_DigestFinal_ex(ctx: EVP_MD_CTX, md: *mut libc::c_uchar, s: *mut libc::c_uint);
fn EVP_md5() -> EVP_MD;
fn EVP_sha() -> EVP_MD;
fn EVP_sha1() -> EVP_MD;
}
struct OpenSSLDigest {
md_ctx: EVP_MD_CTX,
digest_len: uint,
}
impl OpenSSLDigest {
pub fn new(t: digest::DigestType) -> OpenSSLDigest {
let ctx = unsafe {
let md_ctx = EVP_MD_CTX_create();
assert!(!md_ctx.is_null());
EVP_MD_CTX_init(md_ctx);
md_ctx
};
let dlen = unsafe {
let (md, len) = OpenSSLDigest::get_md(t);
EVP_DigestInit_ex(ctx, md, ptr::null());
len
};
OpenSSLDigest {
md_ctx: ctx,
digest_len: dlen,
}
}
pub fn get_md(t: digest::DigestType) -> (EVP_MD, uint) {
unsafe {
match t {
digest::Md5 => { (EVP_md5(), 16u) },
digest::Sha => { (EVP_sha(), 20u) },
digest::Sha1 => { (EVP_sha1(), 20u) },
digest::UnknownDigest => { (ptr::null(), 0u) },
}
}
}
}
impl Digest for OpenSSLDigest {
fn update(&mut self, data: &[u8]) {
unsafe {
if EVP_DigestUpdate(self.md_ctx, data.as_ptr() as *const libc::c_void, data.len() as libc::size_t)
!= 1 as libc::c_int {
fail!("Failed to call EVP_DigestUpdate");
}
}
}
fn digest(&mut self) -> Vec<u8> {
let mut dig = Vec::from_elem(self.digest_len, 0u8);
unsafe {
EVP_DigestFinal_ex(self.md_ctx, dig.as_mut_ptr(), ptr::null_mut());
}
dig
}
}
impl Clone for OpenSSLDigest {
fn clone(&self) -> OpenSSLDigest {
let ctx = unsafe {
let md_ctx = EVP_MD_CTX_create();
assert!(!md_ctx.is_null());
if EVP_MD_CTX_copy_ex(md_ctx, self.md_ctx) != 1 as libc::c_int {
EVP_MD_CTX_destroy(md_ctx);
fail!("Failed to call EVP_MD_CTX_copy_ex");
}
md_ctx
};
OpenSSLDigest {
md_ctx: ctx,
digest_len: self.digest_len,
}
}
fn clone_from(&mut self, source: &OpenSSLDigest) {
self.md_ctx = unsafe {
let md_ctx = EVP_MD_CTX_create();
assert!(!md_ctx.is_null());
if EVP_MD_CTX_copy_ex(md_ctx, source.md_ctx) != 1 as libc::c_int {
EVP_MD_CTX_destroy(md_ctx);
fail!("Failed to call EVP_MD_CTX_copy_ex");
}
EVP_MD_CTX_cleanup(self.md_ctx);
EVP_MD_CTX_destroy(self.md_ctx);
md_ctx
};
self.digest_len = source.digest_len;
}
}
#[unsafe_destructor]
impl Drop for OpenSSLDigest {
fn drop(&mut self) {
unsafe {
EVP_MD_CTX_cleanup(self.md_ctx);
EVP_MD_CTX_destroy(self.md_ctx);
}
}
}
/// This two modes will be converted into the last parameter of `EVP_CipherInit_ex`.
enum CryptoMode {
CryptoModeDecrypt,
@@ -159,7 +276,7 @@ impl OpenSSLCrypto {
let (ctx, _, block_size) = unsafe {
let (cipher, key_size, block_size) = OpenSSLCrypto::get_cipher(cipher_type);
assert!(iv.len() >= block_size);
// assert!(iv.len() >= block_size);
let evp_ctx = EVP_CIPHER_CTX_new();
assert!(!evp_ctx.is_null());
@@ -253,6 +370,10 @@ impl OpenSSLCrypto {
cipher::CipherTypeRc2Cfb => { (EVP_rc2_cfb64(), 16, 8) },
#[cfg(feature="cipher-seed-cfb")]
cipher::CipherTypeSeedCfb => { (EVP_seed_cfb128(), 16, 16) },
#[cfg(feature="cipher-rc4")]
cipher::CipherTypeRc4 => { (EVP_rc4(), 16, 16) },
#[cfg(feature="cipher-rc4-md5")]
cipher::CipherTypeRc4Md5 => { (EVP_rc4(), 16, 16) },
cipher::CipherTypeUnknown => { (ptr::null(), 0, 0) },
}
@@ -366,11 +487,25 @@ impl Cipher for OpenSSLCipher {
match self.encryptor {
Some(ref encryptor) => { encryptor.update(data) },
None => {
let (key, mut iv) = OpenSSLCrypto::bytes_to_key(
let (key, mut iv) = {
let (key, iv) = OpenSSLCrypto::bytes_to_key(
self.cipher_type,
self.key.as_slice()
);
match self.cipher_type {
cipher::CipherTypeRc4Md5 => {
let mut md5_digest = OpenSSLDigest::new(digest::Md5);
md5_digest.update(key.as_slice());
md5_digest.update(iv.as_slice());
(md5_digest.digest(), iv)
},
_ => {
(key, iv)
}
}
};
let encryptor = OpenSSLCrypto::new(self.cipher_type, key.as_slice(), iv.as_slice(), CryptoModeEncrypt);
self.encryptor = Some(encryptor);
@@ -387,15 +522,27 @@ impl Cipher for OpenSSLCipher {
match self.decryptor {
Some(ref decryptor) => { decryptor.update(data) },
None => {
let (key, iv) = OpenSSLCrypto::bytes_to_key(
let (_, _, expected_iv_len) = OpenSSLCrypto::get_cipher(self.cipher_type);
let (pad_key, _) = OpenSSLCrypto::bytes_to_key(
self.cipher_type,
self.key.as_slice()
);
// Get the begining IV from the data
let expected_iv_len = iv.len();
let (real_iv, data) = data.split_at(expected_iv_len);
let key = match self.cipher_type {
cipher::CipherTypeRc4Md5 => {
let mut md5_digest = OpenSSLDigest::new(digest::Md5);
md5_digest.update(pad_key.as_slice());
md5_digest.update(real_iv.as_slice());
md5_digest.digest()
},
_ => {
pad_key
}
};
let decryptor = OpenSSLCrypto::new(self.cipher_type, key.as_slice(), real_iv, CryptoModeDecrypt);
self.decryptor = Some(decryptor);
-2
View File
@@ -29,8 +29,6 @@ extern crate serialize;
#[phase(plugin, link)]
extern crate log;
extern crate native;
pub const VERSION: &'static str = "0.9.0";
pub mod config;