update: working on sender role
parent
dd6ddbcd80
commit
02b7cca354
|
@ -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
|
||||
|
||||
|
|
|
@ -5,89 +5,20 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
// #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 <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 () {
|
||||
// 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;
|
||||
|
|
|
@ -1,7 +1,50 @@
|
|||
#include "sender.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
#include "expiring_signature.h"
|
||||
|
||||
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
|
||||
|
||||
namespace BareMinimumCrypto {
|
||||
#include <optional>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "expiring_signature.h"
|
||||
#include "signing_key.h"
|
||||
#include "time_helpers.h"
|
||||
|
||||
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 <sodium.h>
|
||||
|
||||
namespace BareMinimumCrypto {
|
||||
void try_sodium_init () {
|
||||
if (sodium_init () < 0) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
namespace BareMinimumCrypto {
|
||||
void try_sodium_init ();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue