From 02b7cca3549f6ce6020c20078b313e5d95d65b78 Mon Sep 17 00:00:00 2001 From: _ <> Date: Mon, 18 Jan 2021 22:57:33 +0000 Subject: [PATCH] update: working on sender role --- bare_minimum_crypto/cpp/Makefile | 12 +- bare_minimum_crypto/cpp/bmc_test.cpp | 131 +++------------------ bare_minimum_crypto/cpp/sender.cpp | 45 ++++++- bare_minimum_crypto/cpp/sender.h | 22 ++++ bare_minimum_crypto/cpp/signing_key.cpp | 68 +++++++++++ bare_minimum_crypto/cpp/signing_key.h | 31 +++++ bare_minimum_crypto/cpp/sodium_helpers.cpp | 2 - bare_minimum_crypto/cpp/sodium_helpers.h | 2 + 8 files changed, 191 insertions(+), 122 deletions(-) create mode 100644 bare_minimum_crypto/cpp/signing_key.cpp create mode 100644 bare_minimum_crypto/cpp/signing_key.h diff --git a/bare_minimum_crypto/cpp/Makefile b/bare_minimum_crypto/cpp/Makefile index 46755ce..5dc01a6 100644 --- a/bare_minimum_crypto/cpp/Makefile +++ b/bare_minimum_crypto/cpp/Makefile @@ -5,10 +5,10 @@ CXX_FLAGS=$(FLAGS) -c L_FLAGS=$(FLAGS) LIBS=-lsodium -bmc_test: bmc_test.o base64.o expiring_signature.o receiver.o sodium_helpers.o string_helpers.o time_helpers.o +bmc_test: bmc_test.o base64.o expiring_signature.o receiver.o sender.o signing_key.o sodium_helpers.o string_helpers.o time_helpers.o $(CXX) -o $@ $^ $(L_FLAGS) $(LIBS) -bmc_test.o: bmc_test.cpp expiring_signature.h receiver.h sodium_helpers.h string_helpers.h time_helpers.h +bmc_test.o: bmc_test.cpp expiring_signature.h receiver.h sender.h signing_key.h sodium_helpers.h string_helpers.h time_helpers.h $(CXX) -o $@ $(CXX_FLAGS) $< base64.o: cpp-base64/base64.cpp cpp-base64/base64.h @@ -20,6 +20,12 @@ expiring_signature.o: expiring_signature.cpp expiring_signature.h receiver.o: receiver.cpp receiver.h expiring_signature.h sodium_helpers.h string_helpers.h time_helpers.h $(CXX) -o $@ $(CXX_FLAGS) $< +sender.o: sender.cpp sender.h expiring_signature.h signing_key.h sodium_helpers.h time_helpers.h + $(CXX) -o $@ $(CXX_FLAGS) $< + +signing_key.o: signing_key.cpp signing_key.h expiring_signature.h sodium_helpers.h time_helpers.h + $(CXX) -o $@ $(CXX_FLAGS) $< + sodium_helpers.o: sodium_helpers.cpp sodium_helpers.h $(CXX) -o $@ $(CXX_FLAGS) $< @@ -30,5 +36,5 @@ time_helpers.o: time_helpers.cpp time_helpers.h $(CXX) -o $@ $(CXX_FLAGS) $< clean: - rm -f bmc_test bmc_test.o base64.o expiring_signature.o receiver.o sodium_helpers.o string_helpers.o time_helpers.o + rm -f bmc_test bmc_test.o base64.o expiring_signature.o receiver.o sender.o signing_key.o sodium_helpers.o string_helpers.o time_helpers.o diff --git a/bare_minimum_crypto/cpp/bmc_test.cpp b/bare_minimum_crypto/cpp/bmc_test.cpp index 15cdeaf..2f2d199 100644 --- a/bare_minimum_crypto/cpp/bmc_test.cpp +++ b/bare_minimum_crypto/cpp/bmc_test.cpp @@ -5,89 +5,20 @@ #include #include -#include - -// #include "cpp-base64/base64.h" #include "json.hpp" #include "expiring_signature.h" #include "receiver.h" +#include "sender.h" +#include "signing_key.h" #include "sodium_helpers.h" #include "string_helpers.h" #include "time_helpers.h" using namespace std; using nlohmann::json; - using namespace BareMinimumCrypto; -class SigningKey { - vector pk; - vector sk; - -public: - SigningKey () { - try_sodium_init (); - - pk.resize (crypto_sign_PUBLICKEYBYTES); - sk.resize (crypto_sign_SECRETKEYBYTES); - - crypto_sign_keypair (pk.data (), sk.data ()); - } - - vector pubkey () const { - return pk; - } - - vector pub_to_msgpack () const { - const json j = { - {"key", json::binary (pk)}, - }; - return json::to_msgpack (j); - } - - optional sign ( - const vector & payload, - TimeRange tr - ) const { - try_sodium_init (); - - if (tr.duration () > about_1_year) { - return nullopt; - } - - const json j { - {"not_before", tr.not_before}, - {"not_after", tr.not_after}, - {"payload", json::binary (payload)}, - }; - - const auto cert = json::to_msgpack (j); - - vector sig; - sig.resize (crypto_sign_BYTES); - - crypto_sign_detached (sig.data (), nullptr, cert.data (), cert.size (), sk.data ()); - - return ExpiringSignature { - cert, - sig, - }; - } - - optional sign_key (const SigningKey & k, Instant now) const - { - return sign (k.pub_to_msgpack (), TimeRange::from_start_and_dur (now, about_3_months)); - } - - optional sign_data (const vector & v, Instant now) const - { - return sign (v, TimeRange::from_start_and_dur (now, about_1_week)); - } -}; - - - int happy_path () { // We generate a root key and keep it somewhere safe // (offline, hopefully) @@ -98,57 +29,25 @@ int happy_path () { return 1; } - // The server generates a signing key - SigningKey signing_key; - cerr << "Signing key " << base64_encode (signing_key.pubkey ()) << endl; - const auto now = Instant::now (); - // That signing key signs some important data + // The sender generates a key + SigningKey sender_key; + cerr << "Sender key " << base64_encode (sender_key.pubkey ()) << endl; + + // The root signs the sender key + const ExpiringSignature sender_cert = std::move (*root_key.sign_key (sender_key, now)); + + const auto sender = std::move (*Sender::create (sender_key, sender_cert)); + + // The sender 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"); - const ExpiringSignature signed_data = std::move (*signing_key.sign_data (important_data, now)); - - // The server signs our temporary signing key - const ExpiringSignature cert = std::move (*root_key.sign_key (signing_key, now)); - - { - // 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, Instant {now.x + 1})); - - if (cert != cert_2) { - cerr << "Certs should have been identical" << endl; - return 1; - } - - if (cert == cert_3) { - cerr << "Certs should have been different" << endl; - return 1; - } - - if (cert == cert_3) { - cerr << "Signatures should have been different" << endl; - return 1; - } - } + const auto signed_data = std::move (*sender.sign (important_data)); // The receiver verifies the data by the root public key, - // even though the receiver has never seen the sub-key. + // even though the receiver has never seen the sender-key. - const auto root_pubkey = root_key.pubkey (); - - const json j { - {"cert", { - {"sig", json::binary (cert.sig)}, - {"cert", json::binary (cert.cert)}, - }}, - {"data", { - {"sig", json::binary (signed_data.sig)}, - {"cert", json::binary (signed_data.cert)}, - }}, - }; - - auto verified_opt = Receiver::verify_cert_and_data (root_pubkey, json::to_msgpack (j)); + auto verified_opt = Receiver::verify_cert_and_data (root_key.pubkey (), signed_data); if (! verified_opt) { cerr << "Receiver couldn't verify cert and data" << endl; return 1; diff --git a/bare_minimum_crypto/cpp/sender.cpp b/bare_minimum_crypto/cpp/sender.cpp index c105623..ae01651 100644 --- a/bare_minimum_crypto/cpp/sender.cpp +++ b/bare_minimum_crypto/cpp/sender.cpp @@ -1,7 +1,50 @@ #include "sender.h" +#include + +#include "json.hpp" + +#include "expiring_signature.h" + namespace BareMinimumCrypto { - using namespace std; + using nlohmann::json; + optional Sender::create (SigningKey k, ExpiringSignature c) + { + Sender s; + s.sender_key = k; + s.cert = c; + + return s; + } + vector Sender::try_sign (const vector & data, Instant now) const { + const auto signed_data = std::move (*sender_key.sign_data (data, now)); + + const json j { + {"cert", { + {"sig", json::binary (cert.sig)}, + {"cert", json::binary (cert.cert)}, + }}, + {"data", { + {"sig", json::binary (signed_data.sig)}, + {"cert", json::binary (signed_data.cert)}, + }}, + }; + + return json::to_msgpack (j); + } + + optional > Sender::sign (const vector & data, Instant now) const { + try { + return try_sign (data, now); + } + catch (exception &) { + return nullopt; + } + } + + optional > Sender::sign (const vector & data) const { + return sign (data, Instant::now ()); + } } diff --git a/bare_minimum_crypto/cpp/sender.h b/bare_minimum_crypto/cpp/sender.h index ae1c52f..2b84ee8 100644 --- a/bare_minimum_crypto/cpp/sender.h +++ b/bare_minimum_crypto/cpp/sender.h @@ -1,5 +1,27 @@ #pragma once +#include +#include +#include + +#include "expiring_signature.h" +#include "signing_key.h" +#include "time_helpers.h" + namespace BareMinimumCrypto { + using namespace std; + struct Sender { + static optional create (SigningKey k, ExpiringSignature c); + + // Signs data and attaches our cert from the CA + optional > sign (const vector & data) const; + + private: + SigningKey sender_key; + ExpiringSignature cert; + + vector try_sign (const vector & data, Instant now) const; + optional > sign (const vector & data, Instant now) const; + }; } diff --git a/bare_minimum_crypto/cpp/signing_key.cpp b/bare_minimum_crypto/cpp/signing_key.cpp new file mode 100644 index 0000000..5358302 --- /dev/null +++ b/bare_minimum_crypto/cpp/signing_key.cpp @@ -0,0 +1,68 @@ +#include "signing_key.h" + +#include "json.hpp" + +#include "sodium_helpers.h" + +namespace BareMinimumCrypto { + using nlohmann::json; + + SigningKey::SigningKey () { + try_sodium_init (); + + pk.resize (crypto_sign_PUBLICKEYBYTES); + sk.resize (crypto_sign_SECRETKEYBYTES); + + crypto_sign_keypair (pk.data (), sk.data ()); + } + + vector SigningKey::pubkey () const { + return pk; + } + + vector SigningKey::pub_to_msgpack () const { + const json j = { + {"key", json::binary (pk)}, + }; + return json::to_msgpack (j); + } + + optional SigningKey::sign ( + const vector & payload, + TimeRange tr + ) const { + try_sodium_init (); + + if (tr.duration () > about_1_year) { + return nullopt; + } + + const json j { + {"not_before", tr.not_before}, + {"not_after", tr.not_after}, + {"payload", json::binary (payload)}, + }; + + const auto cert = json::to_msgpack (j); + + vector sig; + sig.resize (crypto_sign_BYTES); + + crypto_sign_detached (sig.data (), nullptr, cert.data (), cert.size (), sk.data ()); + + return ExpiringSignature { + cert, + sig, + }; + } + + optional SigningKey::sign_key (const SigningKey & k, Instant now) const + { + return sign (k.pub_to_msgpack (), TimeRange::from_start_and_dur (now, about_3_months)); + } + + optional SigningKey::sign_data (const vector & v, Instant now) const + { + return sign (v, TimeRange::from_start_and_dur (now, about_1_week)); + } +} diff --git a/bare_minimum_crypto/cpp/signing_key.h b/bare_minimum_crypto/cpp/signing_key.h new file mode 100644 index 0000000..6c85f78 --- /dev/null +++ b/bare_minimum_crypto/cpp/signing_key.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include + +#include "expiring_signature.h" +#include "time_helpers.h" + +namespace BareMinimumCrypto { + using namespace std; + + class SigningKey { + vector pk; + vector sk; + + public: + SigningKey (); + + vector pubkey () const; + vector pub_to_msgpack () const; + + optional sign ( + const vector & payload, + TimeRange tr + ) const; + + optional sign_key (const SigningKey & k, Instant now) const; + optional sign_data (const vector & v, Instant now) const; + }; +} diff --git a/bare_minimum_crypto/cpp/sodium_helpers.cpp b/bare_minimum_crypto/cpp/sodium_helpers.cpp index 6d0aa2d..d4fb219 100644 --- a/bare_minimum_crypto/cpp/sodium_helpers.cpp +++ b/bare_minimum_crypto/cpp/sodium_helpers.cpp @@ -2,8 +2,6 @@ #include -#include - namespace BareMinimumCrypto { void try_sodium_init () { if (sodium_init () < 0) { diff --git a/bare_minimum_crypto/cpp/sodium_helpers.h b/bare_minimum_crypto/cpp/sodium_helpers.h index 58d619a..237ad9b 100644 --- a/bare_minimum_crypto/cpp/sodium_helpers.h +++ b/bare_minimum_crypto/cpp/sodium_helpers.h @@ -1,5 +1,7 @@ #pragma once +#include + namespace BareMinimumCrypto { void try_sodium_init (); }