From a709acca8ba41f21e0222debdbe39186c5106beb Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Mon, 22 Oct 2018 14:57:02 +0200 Subject: trial: Encrypt and decrypt timestamp Add functions to encrypt and decrypt a timestamp. We'll be using those functions to write the encrypted timestamp of the first trial launch date to a file. Decided to go for some light encryption instead of just storing a plain or base64-encoded value. Still need to come up with a key, but that will be stored as a plain string in the binary. Need a way to capture the results so we don't end up panicking. Trouble is, 'magic-crypt' doesn't implement the required `Error` traits, so I can't just slot it into 'error-chain'. Still trying to work out how to deal with that. Also add a function to get the days remaining from now. --- src/lib.rs | 1 + src/trial.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 8e23367..27fc7a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ extern crate libc; #[macro_use] extern crate log; +extern crate magic_crypt; #[macro_use] extern crate objc; diff --git a/src/trial.rs b/src/trial.rs index 9604f62..e716559 100644 --- a/src/trial.rs +++ b/src/trial.rs @@ -1,18 +1,22 @@ -use chrono::{DateTime, Local, TimeZone}; +use std::result; -use errors::DurationError; +use chrono::{DateTime, FixedOffset, Local, TimeZone}; +use magic_crypt::{self, MagicCrypt}; + +use errors::*; // Start timestamp on October 1 at 23h // Trial should be valid until November 1 00h const DAYS_REMAINING: u8 = 30; +const KEY: &'static str = "TODO SECRET"; fn days_remaining( start: DateTime, now: DateTime, days_available: u8, -) -> Result { +) -> result::Result { let duration = (now.date() - start.date()).num_days() as u8; if duration > days_available { @@ -24,6 +28,47 @@ fn days_remaining( } } +fn days_remaining_from_now( + start: DateTime +) -> result::Result { + days_remaining(start, Local::now(), DAYS_REMAINING) +} + +fn encode_datetime(d: DateTime) -> String { + let iv = initialization_vector(); + + let mut mc = MagicCrypt::new(KEY, magic_crypt::SecureBit::Bit64, Some(&iv)); + + let timestamp = mc.encrypt_str_to_base64(&d.to_rfc3339()); + + format!("{}//{}", timestamp, iv) +} + +fn decode_datetime(s: &str) -> DateTime { + let encrypted: Vec<_> = s.rsplitn(2, "//").collect(); + let timestamp = encrypted[0]; + let iv = encrypted[1]; + + let mut mc = MagicCrypt::new(KEY, magic_crypt::SecureBit::Bit64, Some(&iv)); + + let timestamp = mc.decrypt_base64_to_string(×tamp) + .expect("unable to read trial key"); + + DateTime::parse_from_rfc3339(×tamp) + .expect("unable to parse timestamp") +} + +fn initialization_vector() -> String { + // Multiplied by 2 for no good reason other than to make the value + // different from the actual timestamp. + (Local::now().timestamp_millis() * 2).to_string() +} + +// initialize_trial_start +// encode_datetime +// check_days_remaining +// days_remaining_from_now + #[cfg(test)] mod tests { -- cgit v1.2.3