update: working on sender role
parent
dd6ddbcd80
commit
02b7cca354
|
@ -5,10 +5,10 @@ CXX_FLAGS=$(FLAGS) -c
|
||||||
L_FLAGS=$(FLAGS)
|
L_FLAGS=$(FLAGS)
|
||||||
LIBS=-lsodium
|
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)
|
$(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) $<
|
$(CXX) -o $@ $(CXX_FLAGS) $<
|
||||||
|
|
||||||
base64.o: cpp-base64/base64.cpp cpp-base64/base64.h
|
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
|
receiver.o: receiver.cpp receiver.h expiring_signature.h sodium_helpers.h string_helpers.h time_helpers.h
|
||||||
$(CXX) -o $@ $(CXX_FLAGS) $<
|
$(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
|
sodium_helpers.o: sodium_helpers.cpp sodium_helpers.h
|
||||||
$(CXX) -o $@ $(CXX_FLAGS) $<
|
$(CXX) -o $@ $(CXX_FLAGS) $<
|
||||||
|
|
||||||
|
@ -30,5 +36,5 @@ time_helpers.o: time_helpers.cpp time_helpers.h
|
||||||
$(CXX) -o $@ $(CXX_FLAGS) $<
|
$(CXX) -o $@ $(CXX_FLAGS) $<
|
||||||
|
|
||||||
clean:
|
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
|
||||||
|
|
||||||
|
|
|
@ -5,89 +5,20 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
// #include "cpp-base64/base64.h"
|
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
|
|
||||||
#include "expiring_signature.h"
|
#include "expiring_signature.h"
|
||||||
#include "receiver.h"
|
#include "receiver.h"
|
||||||
|
#include "sender.h"
|
||||||
|
#include "signing_key.h"
|
||||||
#include "sodium_helpers.h"
|
#include "sodium_helpers.h"
|
||||||
#include "string_helpers.h"
|
#include "string_helpers.h"
|
||||||
#include "time_helpers.h"
|
#include "time_helpers.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
|
|
||||||
using namespace BareMinimumCrypto;
|
using namespace BareMinimumCrypto;
|
||||||
|
|
||||||
class SigningKey {
|
|
||||||
vector <uint8_t> pk;
|
|
||||||
vector <uint8_t> sk;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SigningKey () {
|
|
||||||
try_sodium_init ();
|
|
||||||
|
|
||||||
pk.resize (crypto_sign_PUBLICKEYBYTES);
|
|
||||||
sk.resize (crypto_sign_SECRETKEYBYTES);
|
|
||||||
|
|
||||||
crypto_sign_keypair (pk.data (), sk.data ());
|
|
||||||
}
|
|
||||||
|
|
||||||
vector <uint8_t> pubkey () const {
|
|
||||||
return pk;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector <uint8_t> pub_to_msgpack () const {
|
|
||||||
const json j = {
|
|
||||||
{"key", json::binary (pk)},
|
|
||||||
};
|
|
||||||
return json::to_msgpack (j);
|
|
||||||
}
|
|
||||||
|
|
||||||
optional <ExpiringSignature> sign (
|
|
||||||
const vector <uint8_t> & 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 <uint8_t> sig;
|
|
||||||
sig.resize (crypto_sign_BYTES);
|
|
||||||
|
|
||||||
crypto_sign_detached (sig.data (), nullptr, cert.data (), cert.size (), sk.data ());
|
|
||||||
|
|
||||||
return ExpiringSignature {
|
|
||||||
cert,
|
|
||||||
sig,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
optional <ExpiringSignature> sign_key (const SigningKey & k, Instant now) const
|
|
||||||
{
|
|
||||||
return sign (k.pub_to_msgpack (), TimeRange::from_start_and_dur (now, about_3_months));
|
|
||||||
}
|
|
||||||
|
|
||||||
optional <ExpiringSignature> sign_data (const vector <uint8_t> & v, Instant now) const
|
|
||||||
{
|
|
||||||
return sign (v, TimeRange::from_start_and_dur (now, about_1_week));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int happy_path () {
|
int happy_path () {
|
||||||
// We generate a root key and keep it somewhere safe
|
// We generate a root key and keep it somewhere safe
|
||||||
// (offline, hopefully)
|
// (offline, hopefully)
|
||||||
|
@ -98,57 +29,25 @@ int happy_path () {
|
||||||
return 1;
|
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 ();
|
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 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));
|
const auto signed_data = std::move (*sender.sign (important_data));
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The receiver verifies the data by the root public key,
|
// 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 ();
|
auto verified_opt = Receiver::verify_cert_and_data (root_key.pubkey (), signed_data);
|
||||||
|
|
||||||
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));
|
|
||||||
if (! verified_opt) {
|
if (! verified_opt) {
|
||||||
cerr << "Receiver couldn't verify cert and data" << endl;
|
cerr << "Receiver couldn't verify cert and data" << endl;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -1,7 +1,50 @@
|
||||||
#include "sender.h"
|
#include "sender.h"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "json.hpp"
|
||||||
|
|
||||||
|
#include "expiring_signature.h"
|
||||||
|
|
||||||
namespace BareMinimumCrypto {
|
namespace BareMinimumCrypto {
|
||||||
using namespace std;
|
using nlohmann::json;
|
||||||
|
|
||||||
|
optional <Sender> Sender::create (SigningKey k, ExpiringSignature c)
|
||||||
|
{
|
||||||
|
Sender s;
|
||||||
|
s.sender_key = k;
|
||||||
|
s.cert = c;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector <uint8_t> Sender::try_sign (const vector <uint8_t> & 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 <vector <uint8_t>> Sender::sign (const vector <uint8_t> & data, Instant now) const {
|
||||||
|
try {
|
||||||
|
return try_sign (data, now);
|
||||||
|
}
|
||||||
|
catch (exception &) {
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
optional <vector <uint8_t>> Sender::sign (const vector <uint8_t> & data) const {
|
||||||
|
return sign (data, Instant::now ());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,27 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "expiring_signature.h"
|
||||||
|
#include "signing_key.h"
|
||||||
|
#include "time_helpers.h"
|
||||||
|
|
||||||
namespace BareMinimumCrypto {
|
namespace BareMinimumCrypto {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
struct Sender {
|
||||||
|
static optional <Sender> create (SigningKey k, ExpiringSignature c);
|
||||||
|
|
||||||
|
// Signs data and attaches our cert from the CA
|
||||||
|
optional <vector <uint8_t>> sign (const vector <uint8_t> & data) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SigningKey sender_key;
|
||||||
|
ExpiringSignature cert;
|
||||||
|
|
||||||
|
vector <uint8_t> try_sign (const vector <uint8_t> & data, Instant now) const;
|
||||||
|
optional <vector <uint8_t>> sign (const vector <uint8_t> & data, Instant now) const;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 <uint8_t> SigningKey::pubkey () const {
|
||||||
|
return pk;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector <uint8_t> SigningKey::pub_to_msgpack () const {
|
||||||
|
const json j = {
|
||||||
|
{"key", json::binary (pk)},
|
||||||
|
};
|
||||||
|
return json::to_msgpack (j);
|
||||||
|
}
|
||||||
|
|
||||||
|
optional <ExpiringSignature> SigningKey::sign (
|
||||||
|
const vector <uint8_t> & 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 <uint8_t> sig;
|
||||||
|
sig.resize (crypto_sign_BYTES);
|
||||||
|
|
||||||
|
crypto_sign_detached (sig.data (), nullptr, cert.data (), cert.size (), sk.data ());
|
||||||
|
|
||||||
|
return ExpiringSignature {
|
||||||
|
cert,
|
||||||
|
sig,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
optional <ExpiringSignature> 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 <ExpiringSignature> SigningKey::sign_data (const vector <uint8_t> & v, Instant now) const
|
||||||
|
{
|
||||||
|
return sign (v, TimeRange::from_start_and_dur (now, about_1_week));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "expiring_signature.h"
|
||||||
|
#include "time_helpers.h"
|
||||||
|
|
||||||
|
namespace BareMinimumCrypto {
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class SigningKey {
|
||||||
|
vector <uint8_t> pk;
|
||||||
|
vector <uint8_t> sk;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SigningKey ();
|
||||||
|
|
||||||
|
vector <uint8_t> pubkey () const;
|
||||||
|
vector <uint8_t> pub_to_msgpack () const;
|
||||||
|
|
||||||
|
optional <ExpiringSignature> sign (
|
||||||
|
const vector <uint8_t> & payload,
|
||||||
|
TimeRange tr
|
||||||
|
) const;
|
||||||
|
|
||||||
|
optional <ExpiringSignature> sign_key (const SigningKey & k, Instant now) const;
|
||||||
|
optional <ExpiringSignature> sign_data (const vector <uint8_t> & v, Instant now) const;
|
||||||
|
};
|
||||||
|
}
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
namespace BareMinimumCrypto {
|
namespace BareMinimumCrypto {
|
||||||
void try_sodium_init () {
|
void try_sodium_init () {
|
||||||
if (sodium_init () < 0) {
|
if (sodium_init () < 0) {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <sodium.h>
|
||||||
|
|
||||||
namespace BareMinimumCrypto {
|
namespace BareMinimumCrypto {
|
||||||
void try_sodium_init ();
|
void try_sodium_init ();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue