1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
use byteorder::ReadBytesExt; use crypto::{ buffer::{ReadBuffer, WriteBuffer}, digest::Digest, }; pub trait Decrypt { fn id( &self, ekey: &str, ) -> crate::EResult<u64>; } fn decode_util( ekey: &str, sub_key: &str, secret_key: &str, secret_key_bytes: &[u8], ) -> crate::EResult<u64> { if ekey.is_empty() { return Err(crate::EError::InvalidInput.into()); } let ekey = ekey.to_string(); let padding: String = vec!['='; 3 - ekey.len() % 3].into_iter().collect(); let ekey = ekey + &padding; let emsg = match base64::decode_config(&ekey, base64::URL_SAFE) { Ok(m) => m, Err(_) => return Err(crate::EError::InvalidInput.into()), }; let mut sha = crypto::sha2::Sha256::new(); sha.input_str(&format!("{}{}", secret_key, sub_key)); let mut iv: Vec<u8> = vec![0; 32]; sha.result(&mut iv); let iv = &iv[..16]; let mut decryptor = crypto::aes::cbc_decryptor( crypto::aes::KeySize::KeySize256, &secret_key_bytes[..32], iv, crypto::blockmodes::NoPadding, ); let mut final_result = Vec::<u8>::new(); let mut read_buffer = crypto::buffer::RefReadBuffer::new(&emsg); let mut buffer = [0; 16]; let mut write_buffer = crypto::buffer::RefWriteBuffer::new(&mut buffer); loop { let result = decryptor.decrypt(&mut read_buffer, &mut write_buffer, true); let result = match result { Ok(v) => v, Err(e) => return Err(crate::EError::Decrypt(e).into()), }; final_result.extend( write_buffer .take_read_buffer() .take_remaining() .iter() .copied(), ); match result { crypto::buffer::BufferResult::BufferUnderflow => break, crypto::buffer::BufferResult::BufferOverflow => {} } } let mut rdr = std::io::Cursor::new(final_result); let crc = rdr.read_u32::<byteorder::LittleEndian>()?; let id = rdr.read_u64::<byteorder::LittleEndian>()?; let version = rdr.read_u32::<byteorder::LittleEndian>()?; let expected_crc: u32 = if version == 0 { crc::crc32::checksum_ieee(&vec![0; id as usize]) } else { let id: String = id.to_string(); let id_bytes = id.as_bytes(); crc::crc32::checksum_ieee(id_bytes) }; if crc != expected_crc { return Err(crate::EError::CRCMismatch.into()); } Ok(id) } #[deprecated(since = "0.1.5", note = "Please use .decrypt() instead")] pub fn decode( ekey: &str, sub_key: &str, ) -> crate::EResult<u64> { decrypt(ekey, sub_key) } pub fn decrypt( ekey: &str, sub_key: &str, ) -> crate::EResult<u64> { let config = crate::CONFIG.read().unwrap(); if config.secret_key.is_none() { return Err(crate::EError::SecretKeyNotFound.into()); } decode_util( ekey, sub_key, config.secret_key.as_ref().unwrap(), config.secret_key_bytes.as_ref(), ) } #[deprecated( since = "0.1.5", note = "Please use .decrypt_with_secret() instead" )] pub fn decode_with_secret( ekey: &str, sub_key: &str, secret: &str, ) -> crate::EResult<u64> { decrypt_with_secret(ekey, sub_key, secret) } pub fn decrypt_with_secret( ekey: &str, sub_key: &str, secret: &str, ) -> crate::EResult<u64> { decode_util(ekey, sub_key, secret, secret.as_bytes().as_ref()) }