encrypted_id 0.1.5

Encryption and Decryption
Documentation
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())
}