From fb1e133ca1755fc83d522f72209d21dfab445a03 Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Sun, 17 Jan 2021 17:31:28 -0600 Subject: [PATCH] :recycle: refactor: Extract Instant struct --- bare_minimum_crypto/cpp/bmc_test.cpp | 44 +++++++++---------- bare_minimum_crypto/cpp/time_helpers.cpp | 56 ++++++++++++++++++++---- bare_minimum_crypto/cpp/time_helpers.h | 18 +++++++- 3 files changed, 85 insertions(+), 33 deletions(-) diff --git a/bare_minimum_crypto/cpp/bmc_test.cpp b/bare_minimum_crypto/cpp/bmc_test.cpp index 3754e84..94212db 100644 --- a/bare_minimum_crypto/cpp/bmc_test.cpp +++ b/bare_minimum_crypto/cpp/bmc_test.cpp @@ -48,7 +48,7 @@ bool is_pubkey_length (const vector & v) { optional > try_verify_signed_data ( const ExpiringSignature & sig, const vector & pubkey, - int64_t now + Instant now ) { try_sodium_init (); @@ -67,13 +67,12 @@ optional > try_verify_signed_data ( const json j = json::parse (sig.cert_s); - const int64_t not_before = j ["not_before"]; - const int64_t not_after = j ["not_after"]; + const TimeRange tr { + j ["not_before"], + j ["not_after"] + }; - if (now < not_before) { - return nullopt; - } - if (now > not_after) { + if (! tr.contains (now)) { return nullopt; } @@ -86,7 +85,7 @@ optional > try_verify_signed_data ( optional > verify_signed_data ( const ExpiringSignature & sig, const vector & pubkey, - int64_t now + Instant now ) { try { return try_verify_signed_data (sig, pubkey, now); @@ -100,7 +99,7 @@ optional > verify_cert_and_data ( const ExpiringSignature & signed_cert, const ExpiringSignature & signed_data, const vector & root_pubkey, - int64_t now + Instant now ) { auto subkey_opt = verify_signed_data (signed_cert, root_pubkey, now); if (! subkey_opt) { @@ -116,14 +115,14 @@ optional > verify_cert_and_data ( const ExpiringSignature & signed_data, const vector & root_pubkey ) { - return verify_cert_and_data (signed_cert, signed_data, root_pubkey, get_seconds_since_epoch ()); + return verify_cert_and_data (signed_cert, signed_data, root_pubkey, Instant::now ()); } optional > verify_signed_data ( const ExpiringSignature & sig, const vector & pubkey ) { - return verify_signed_data (sig, pubkey, get_seconds_since_epoch ()); + return verify_signed_data (sig, pubkey, Instant::now ()); } class SigningKey { @@ -150,20 +149,17 @@ public: optional sign_base64 ( const string & payload_b64, - int64_t duration, - int64_t now + TimeRange tr ) const { try_sodium_init (); - if (duration > about_1_year) { + if (tr.duration () > about_1_year) { return nullopt; } - const auto not_after = now + duration; - const json j { - {"not_before", now}, - {"not_after", not_after}, + {"not_before", tr.not_before}, + {"not_after", tr.not_after}, {"payload_b64", payload_b64}, }; @@ -180,14 +176,14 @@ public: }; } - optional sign_key (const SigningKey & k, int64_t now) const + optional sign_key (const SigningKey & k, Instant now) const { - return sign_base64 (k.pub_to_base64 (), about_3_months, now); + return sign_base64 (k.pub_to_base64 (), TimeRange::from_start_and_dur (now, about_3_months)); } - optional sign_data (const vector & v, int64_t now) const + optional sign_data (const vector & v, Instant now) const { - return sign_base64 (base64_encode (v), about_1_week, now); + return sign_base64 (base64_encode (v), TimeRange::from_start_and_dur (now, about_1_week)); } }; @@ -207,7 +203,7 @@ int happy_path () { SigningKey signing_key; cerr << "Signing key " << signing_key.pub_to_base64 () << endl; - const auto now = get_seconds_since_epoch (); + const auto now = Instant::now (); // That signing key signs some important data const auto important_data = copy_to_bytes ("Nikolai, Anna, Ivan, Mikhail, Ivan, Nikolai, Anna. 7 4 1 4 3 5 7 4"); @@ -219,7 +215,7 @@ int happy_path () { { // Check that a different time results in a different cert const auto cert_2 = std::move (*root_key.sign_key (signing_key, now)); - const auto cert_3 = std::move (*root_key.sign_key (signing_key, now + 1)); + const auto cert_3 = std::move (*root_key.sign_key (signing_key, Instant {now.x + 1})); if (cert != cert_2) { cerr << "Certs should have been identical" << endl; diff --git a/bare_minimum_crypto/cpp/time_helpers.cpp b/bare_minimum_crypto/cpp/time_helpers.cpp index 8035df3..28f6c4d 100644 --- a/bare_minimum_crypto/cpp/time_helpers.cpp +++ b/bare_minimum_crypto/cpp/time_helpers.cpp @@ -7,26 +7,66 @@ namespace BareMinimumCrypto { using namespace std; using namespace chrono; - int64_t get_seconds_since_epoch () { + Instant::Instant (int64_t x): x (x) {} + + Instant Instant::now () { const auto utc_now = system_clock::now (); - return duration_cast (utc_now.time_since_epoch ()).count (); + return Instant {duration_cast (utc_now.time_since_epoch ()).count ()}; + } + + bool TimeRange::contains (Instant x) const { + if (not_after < not_before) { + return false; + } + + if (x.x < not_before) { + return false; + } + + if (x.x > not_after) { + return false; + } + + return true; + } + + int64_t TimeRange::duration () const { + return not_after - not_before; + } + + TimeRange TimeRange::from_start_and_dur (Instant start, int64_t dur) { + return TimeRange { + start.x, + start.x + dur + }; } // Most tests will use a virtual clock. But just as a smoke test, // make sure real time is realistic. int test_time () { - const auto seconds_since_epoch = get_seconds_since_epoch (); + const auto now = Instant::now (); const auto time_of_writing = 1610844872; - if (seconds_since_epoch < time_of_writing) { - cerr << "Error: Real time is in the past." << endl; + const int64_t about_100_years = (int64_t)100 * 365 * 86400; + + const TimeRange tr { + time_of_writing, + time_of_writing + about_100_years + }; + + if (! tr.contains (now)) { + cerr << "System clock is acting weird" << endl; return 1; } - const int64_t about_100_years = (int64_t)100 * 365 * 86400; - if (seconds_since_epoch > time_of_writing + about_100_years) { - cerr << "Error: Real time is in the far future." << endl; + const TimeRange bad_tr { + time_of_writing + about_100_years, + time_of_writing + }; + + if (bad_tr.contains (now)) { + cerr << "Invalid TimeRange should not contain any Instants" << endl; return 1; } diff --git a/bare_minimum_crypto/cpp/time_helpers.h b/bare_minimum_crypto/cpp/time_helpers.h index 5f22580..2cae6eb 100644 --- a/bare_minimum_crypto/cpp/time_helpers.h +++ b/bare_minimum_crypto/cpp/time_helpers.h @@ -7,7 +7,23 @@ namespace BareMinimumCrypto { const int64_t about_3_months = (int64_t)105 * 86400; const int64_t about_1_year = (int64_t)365 * 86400; - int64_t get_seconds_since_epoch (); + struct Instant { + // Seconds since Unix epoch + int64_t x; + + Instant (int64_t x); + static Instant now (); + }; + + struct TimeRange { + int64_t not_before; + int64_t not_after; + + bool contains (Instant x) const; + int64_t duration () const; + + static TimeRange from_start_and_dur (Instant start, int64_t dur); + }; int test_time (); }