#include "receiver.h" #include #include "json.hpp" #include "expiring_signature.h" #include "sodium_helpers.h" #include "string_helpers.h" #include "time_helpers.h" namespace BareMinimumCrypto::Receiver { using nlohmann::json; bool is_pubkey_length (const vector & v) { return v.size () == crypto_sign_PUBLICKEYBYTES; } optional > try_verify_signed_data ( const vector & pubkey, const ExpiringSignature & sig, Instant now ) { try_sodium_init (); if (! is_pubkey_length (pubkey)) { return nullopt; } if (crypto_sign_verify_detached ( sig.sig.data (), (const uint8_t *)sig.cert_s.data (), sig.cert_s.size (), pubkey.data () ) != 0) { return nullopt; } const json j = json::parse (sig.cert_s); const TimeRange tr { j ["not_before"], j ["not_after"] }; if (! tr.contains (now)) { return nullopt; } const string payload_b64 = j ["payload_b64"]; const auto payload = std::move (*BareMinimumCrypto::base64_decode (payload_b64)); return payload; } optional > verify_signed_data ( const vector & pubkey, const ExpiringSignature & sig, Instant now ) { try { return try_verify_signed_data (pubkey, sig, now); } catch (json::exception &) { return nullopt; } } optional > verify_cert_and_data ( const vector & root_pubkey, const ExpiringSignature & signed_cert, const ExpiringSignature & signed_data, Instant now ) { auto subkey_opt = verify_signed_data (root_pubkey, signed_cert, now); if (! subkey_opt) { return nullopt; } const auto subkey = std::move (*subkey_opt); return verify_signed_data (subkey, signed_data, now); } optional > verify_cert_and_data ( const vector & root_pubkey, const ExpiringSignature & signed_cert, const ExpiringSignature & signed_data ) { return verify_cert_and_data (root_pubkey, signed_cert, signed_data, Instant::now ()); } optional > try_verify_cert_and_data ( const vector & root_pubkey, const string & json_string, Instant now ) { const json j = json::parse (json_string); ExpiringSignature cert; cert.sig = *base64_decode (j ["cert"]["sig_b64"]); cert.cert_s = j ["cert"]["payload_s"]; auto subkey_opt = verify_signed_data (root_pubkey, cert, now); const auto subkey = std::move (*subkey_opt); ExpiringSignature data; data.sig = *base64_decode (j ["data"]["sig_b64"]); data.cert_s = j ["data"]["payload_s"]; return verify_signed_data (subkey, data, now); } optional > verify_cert_and_data ( const vector & root_pubkey, const string & json_string ) { try { return try_verify_cert_and_data (root_pubkey, json_string, Instant::now ()); } catch (json::exception &) { return nullopt; } } }