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
use byteorder::WriteBytesExt;
use crypto::{
    buffer::{ReadBuffer, WriteBuffer},
    digest::Digest,
};

pub trait Encrypt {
    fn ekey(&self) -> crate::EResult<String>;
}

fn encode_id_util(
    id: u64,
    sub_key: &str,
    secret_key: &str,
    secret_key_bytes: &[u8],
) -> crate::EResult<String> {
    let version: u32 = 1;
    let crc: u32 = crc::crc32::checksum_ieee(id.to_string().as_bytes());

    let mut msg: Vec<u8> = vec![];
    msg.write_u32::<byteorder::LittleEndian>(crc)?;
    msg.write_u64::<byteorder::LittleEndian>(id)?;
    msg.write_u32::<byteorder::LittleEndian>(version)?;

    let mut sha_value = crypto::sha2::Sha256::new();
    sha_value.input_str(&format!("{}{}", secret_key, sub_key));
    let mut iv: Vec<u8> = vec![0; 32];
    sha_value.result(&mut iv);
    let iv = &iv[..16];
    let mut encryptor = crypto::aes::cbc_encryptor(
        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(msg.as_ref());
    let mut buffer = [0; 16];
    let mut write_buffer = crypto::buffer::RefWriteBuffer::new(&mut buffer);

    loop {
        let result =
            encryptor.encrypt(&mut read_buffer, &mut write_buffer, true);

        let result = match result {
            Ok(v) => v,
            Err(e) => return Err(crate::EError::Encrypt(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 => {}
        }
    }
    Ok(base64::encode_config(&final_result, base64::URL_SAFE).replace("=", ""))
}

#[deprecated(since = "0.1.5", note = "Please use .encrypt() instead")]
pub fn encode(
    id: u64,
    sub_key: &str,
) -> crate::EResult<String> {
    encrypt(id, sub_key)
}

pub fn encrypt(
    id: u64,
    sub_key: &str,
) -> crate::EResult<String> {
    let config = crate::CONFIG.read().unwrap();
    if config.secret_key.is_none() {
        return Err(crate::EError::SecretKeyNotFound.into());
    }
    encode_id_util(
        id,
        sub_key,
        config.secret_key.as_ref().unwrap(),
        config.secret_key_bytes.as_ref(),
    )
}

#[deprecated(
    since = "0.1.5",
    note = "Please use .encrypt_with_secret() instead"
)]
pub fn encode_with_secret(
    id: u64,
    sub_key: &str,
    secret: &str,
) -> crate::EResult<String> {
    encrypt_with_secret(id, sub_key, secret)
}

pub fn encrypt_with_secret(
    id: u64,
    sub_key: &str,
    secret: &str,
) -> crate::EResult<String> {
    encode_id_util(id, sub_key, secret, secret.as_bytes().as_ref())
}