md5mix 0.1.2

A fun number to string by md5
Documentation
//! # md5 混淆加解密数字
//!
//! md5 混淆加解密数字到字符串,解析字符串到数字,抄袭php的一个加密算法,加密算法名字不明
//! 
/// 
/// 
/// # Examples
///
/// ```
///let sign_str = "xxxxxxxx";
///let md5mix_obj = md5mix::Md5mix::new(sign_str);
///let result = md5mix_obj.encode(1000898);
///let str = result.unwrap();
///println!("str:{}", &str);

///let result = md5mix_obj.decode(&str);
///let id = result.unwrap();
///println!("id:{}", id);
/// ```
/// 
// --snip--


use crypto::md5::Md5;
use crypto::digest::Digest;


use std::time::SystemTime;


pub struct Md5mix<'a>{
    sign_str: &'a str,
}

impl<'a> Md5mix<'a> {
    pub fn new(s: &'a str) -> Md5mix {
        Self { sign_str: s }
    }

    pub fn decode(&self, s: &str) -> Result<i32, String> {

        let string = s.replace("-", "+").replace("_", "/").replace(".", "=");

        let ckey_length = 4;

        let ( keya, _keyb) = self.create_key();

        let keyc = &string[..ckey_length];

        let mut hasher = Md5::new();
        
        let keyacstr = format!("{}{}", keya, keyc);
        hasher.input_str(&keyacstr);
        let keyac = hasher.result_str();


        let cryptkey = format!("{}{}", &keya, &keyac);


        let string = match base64::decode(&string[ckey_length..]){
            Ok(s) => s,
            Err(e) => {
                return Err(format!("base64.decode err:{:?}", e))
            }
        };


        let buf = Self::mix(&cryptkey, &string);


        let result = match std::str::from_utf8(&buf){
            Ok(s) => s,
            Err(e) => {
                return Err(format!("from_utf8 err:{:?}", e))
            }
        };

        let number = &result[26..];

        match number.parse(){
            Ok(s) => Ok(s),
            Err(e) => Err(format!("number parse err:{:?}", e)),
        }

    }


    fn mix(cryptkey: &str, string: &[u8]) -> Vec<u8>{


        let key_length = cryptkey.len();

        let mut randkey: Vec<i32> = Vec::new();
        for i in 0..256 {
            let index = i % key_length;
            let chars = &cryptkey[index..index+1];

            let ascii = chars.as_bytes();
            let ascii = ascii.to_ascii_lowercase();

            randkey.push(ascii[0] as i32);

        }



        let mut box_vec: Vec<i32> = Vec::new();
        for i in 0..256 {
            box_vec.push(i);
        }

        let mut j: i32 = 0;
        for i in 0..256 {
            j = (j + box_vec[i] + randkey[i]) % 256;
            let tmp = box_vec[i];
            box_vec[i] = box_vec[j as usize];
            box_vec[j as usize] = tmp;
        }



        let mut a = 0;
        let mut j = 0;
        

        let mut buf: Vec<u8> = vec![];

        for &item in string.into_iter(){
            a = (a + 1) % 256;
            
            j = (j + box_vec[a]) %256;

            let tmp = box_vec[a];

            box_vec[a] = box_vec[j as usize];
            box_vec[j as usize] = tmp;
        
            let stringord = item as i32;

            let b = (box_vec[a] + box_vec[j as usize]) % 256;

            let chr_num =  stringord ^ box_vec[b as usize];

            buf.push(chr_num as u8);

        };

        buf

    }


    fn create_key(&self) -> (String, String) {
        let mut hasher = Md5::new();
        hasher.input_str(self.sign_str);
        let key = hasher.result_str();



        let mut hasher = Md5::new();
        hasher.input_str(&key[..16]);
        let keya = hasher.result_str();

        let mut hasher = Md5::new();
        hasher.input_str(&key[16..]);
        let keyb = hasher.result_str();

        (keya, keyb)
    }

    pub fn encode(&self, id: i32) -> Result<String, String> {


        let ckey_length = 4;

    
        let (keya, keyb) = self.create_key();



        let mut hasher = Md5::new();
        let now = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH){
            Ok(s) => s,
            Err(e) => {
                let err = format!("SystemTime::now() err {:?}", e);
                return Err(err);
            }
        };
        hasher.input_str(&now.as_secs().to_string());
        let keyc = hasher.result_str();
        let keyc = &keyc[..];
        let keycstart = keyc.len() - ckey_length;
        let keyc = &keyc[keycstart..];


        let mut hasher = Md5::new();
        let keyacstr = format!("{}{}", keya, keyc);
        hasher.input_str(&keyacstr);
        let keyac = hasher.result_str();

        let cryptkey = format!("{}{}", &keya, &keyac);


        let mut hasher = Md5::new();
        let string = format!("{}{}", id, keyb);
        hasher.input_str(&string);
        let string = hasher.result_str();

        let string: &str = &string[..];
        let string = format!("0000000000{}{}", &string[0..16], id);


        let buf = Self::mix(&cryptkey, &string.as_bytes());

        let bs = &base64::encode(buf);
        let rs = bs.replace("=", "");
        let rs = format!("{}{}", keyc, rs);
        let rs = rs.replace("+", "-").replace("/", "_").replace("=", ".");


        Ok(rs)

    }

}