diff --git a/bare_minimum_crypto/cpp/bmc_test.cpp b/bare_minimum_crypto/cpp/bmc_test.cpp index de1cf8e..3754e84 100644 --- a/bare_minimum_crypto/cpp/bmc_test.cpp +++ b/bare_minimum_crypto/cpp/bmc_test.cpp @@ -7,6 +7,7 @@ #include +#include "cpp-base64/base64.h" #include "json.hpp" #include "string_helpers.h" @@ -40,19 +41,18 @@ void try_sodium_init () { } } -struct VerifiedData { - vector payload; - string purpose; -}; +bool is_pubkey_length (const vector & v) { + return v.size () == crypto_sign_PUBLICKEYBYTES; +} -optional try_verify_signed_data ( +optional > try_verify_signed_data ( const ExpiringSignature & sig, - int64_t now, - const vector & pubkey + const vector & pubkey, + int64_t now ) { try_sodium_init (); - if (pubkey.size () != crypto_sign_PUBLICKEYBYTES) { + if (! is_pubkey_length (pubkey)) { return nullopt; } @@ -77,29 +77,55 @@ optional try_verify_signed_data ( return nullopt; } - const string purpose = j ["purpose"]; const string payload_b64 = j ["payload_b64"]; - const auto payload = std::move (*base64_decode (payload_b64)); + const auto payload = std::move (*BareMinimumCrypto::base64_decode (payload_b64)); - return VerifiedData { - payload, - purpose - }; + return payload; } -optional verify_signed_data ( +optional > verify_signed_data ( const ExpiringSignature & sig, - int64_t now, - const vector & pubkey + const vector & pubkey, + int64_t now ) { try { - return try_verify_signed_data (sig, now, pubkey); + return try_verify_signed_data (sig, pubkey, now); } catch (json::exception &) { return nullopt; } } +optional > verify_cert_and_data ( + const ExpiringSignature & signed_cert, + const ExpiringSignature & signed_data, + const vector & root_pubkey, + int64_t now +) { + auto subkey_opt = verify_signed_data (signed_cert, root_pubkey, now); + if (! subkey_opt) { + return nullopt; + } + const auto subkey = std::move (*subkey_opt); + + return verify_signed_data (signed_data, subkey, now); +} + +optional > verify_cert_and_data ( + const ExpiringSignature & signed_cert, + const ExpiringSignature & signed_data, + const vector & root_pubkey +) { + return verify_cert_and_data (signed_cert, signed_data, root_pubkey, get_seconds_since_epoch ()); +} + +optional > verify_signed_data ( + const ExpiringSignature & sig, + const vector & pubkey +) { + return verify_signed_data (sig, pubkey, get_seconds_since_epoch ()); +} + class SigningKey { vector pk; vector sk; @@ -123,10 +149,9 @@ public: } optional sign_base64 ( - const string & payload_b64, - string purpose, - int64_t now, - int64_t duration + const string & payload_b64, + int64_t duration, + int64_t now ) const { try_sodium_init (); @@ -139,7 +164,6 @@ public: const json j { {"not_before", now}, {"not_after", not_after}, - {"purpose", purpose}, {"payload_b64", payload_b64}, }; @@ -158,15 +182,17 @@ public: optional sign_key (const SigningKey & k, int64_t now) const { - return sign_base64 (k.pub_to_base64 (), "4QHAB7O5 trusted public key", now, about_3_months); + return sign_base64 (k.pub_to_base64 (), about_3_months, now); } optional sign_data (const vector & v, int64_t now) const { - return sign_base64 (base64_encode (v), "MS7WL26L signed data", now, about_1_week); + return sign_base64 (base64_encode (v), about_1_week, now); } }; + + int happy_path () { // We generate a root key and keep it somewhere safe // (offline, hopefully) @@ -217,43 +243,20 @@ int happy_path () { cerr << base64_encode (cert.sig) << endl; } - // The client knows our root public key + // The receiver verifies the data by the root public key, + // even though the receiver has never seen the sub-key. + const auto root_pubkey = root_key.pubkey (); - - { - auto verified_opt = verify_signed_data (cert, now, root_pubkey); - if (! verified_opt) { - cerr << "Couldn't verify cert" << endl; - return 1; - } - const auto verified = std::move (*verified_opt); - - if (verified.purpose != "4QHAB7O5 trusted public key") { - cerr << "Purpose did not match" << endl; - return 1; - } - if (verified.payload != signing_key.pubkey ()) { - cerr << "Pubkey payload did not match" << endl; - return 1; - } + auto verified_opt = verify_cert_and_data (cert, signed_data, root_pubkey); + if (! verified_opt) { + cerr << "Receiver couldn't verify cert and data" << endl; + return 1; } + const auto verified = std::move (*verified_opt); - { - auto verified_opt = verify_signed_data (signed_data, now, signing_key.pubkey ()); - if (! verified_opt) { - cerr << "Couldn't verify cert" << endl; - return 1; - } - const auto verified = std::move (*verified_opt); - - if (verified.purpose != "MS7WL26L signed data") { - cerr << "Purpose did not match" << endl; - return 1; - } - if (verified.payload != important_data) { - cerr << "Pubkey payload did not match" << endl; - return 1; - } + if (verified != important_data) { + cerr << "Verified payload did not match expected payload" << endl; + return 1; } return 0;