Skip to content

Commit

Permalink
encryption add bind phrase feature
Browse files Browse the repository at this point in the history
  • Loading branch information
Consti10 committed Aug 11, 2023
1 parent 5d4aaef commit 2616f7c
Show file tree
Hide file tree
Showing 17 changed files with 82 additions and 102 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ wfb_tx
unit_test
benchmark
gs.key
drone.key
key_1.key
wfb_keygen
udp_generator_validator
socket_helper_test
Expand Down
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions example_key/txrx.key
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
����O���8x�-����%�>Kqy?�*a�oM� �0�����h|�p� ��U8B��=������ά�|�����X3̦';,U�;��P�x�:����@����;�oaP6�>��H؟�L�-���E
2 changes: 0 additions & 2 deletions example_keys/drone.key

This file was deleted.

1 change: 0 additions & 1 deletion example_keys/gs.key

This file was deleted.

3 changes: 1 addition & 2 deletions executables/example_hello.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ int main(int argc, char *const *argv) {
WBTxRx::WifiCard tmp_card{card,1};
cards.push_back(tmp_card);
WBTxRx::Options options_txrx{};
options_txrx.rtl8812au_rssi_fixup= true;
options_txrx.set_direction= true;
options_txrx.pcap_rx_set_direction = true;
options_txrx.use_gnd_identifier=!is_air;
if(advanced_debugging){
options_txrx.log_all_received_validated_packets= true;
Expand Down
2 changes: 1 addition & 1 deletion executables/example_pollute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ int main(int argc, char *const *argv) {
cards.push_back(tmp_card);
WBTxRx::Options options_txrx{};
options_txrx.rtl8812au_rssi_fixup= true;
options_txrx.set_direction= true;
options_txrx.pcap_rx_set_direction = true;
options_txrx.enable_non_openhd_mode= true;

std::shared_ptr<WBTxRx> txrx=std::make_shared<WBTxRx>(cards,options_txrx);
Expand Down
4 changes: 2 additions & 2 deletions executables/example_udp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ int main(int argc, char *const *argv) {
cards.push_back(tmp_card);
WBTxRx::Options options_txrx{};
options_txrx.rtl8812au_rssi_fixup= true;
//options_txrx.set_direction= false;
options_txrx.set_direction= pcap_setdirection;
//options_txrx.pcap_rx_set_direction= false;
options_txrx.pcap_rx_set_direction = pcap_setdirection;
options_txrx.log_all_received_validated_packets= false;

std::shared_ptr<WBTxRx> txrx=std::make_shared<WBTxRx>(cards,options_txrx);
Expand Down
2 changes: 1 addition & 1 deletion executables/injection_rate_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ int main(int argc, char *const *argv) {
cards.push_back(tmp_card);
WBTxRx::Options options_txrx{};
options_txrx.rtl8812au_rssi_fixup= true;
//options_txrx.set_direction= false;
//options_txrx.pcap_rx_set_direction= false;
options_txrx.log_all_received_validated_packets= false;

std::shared_ptr<WBTxRx> txrx=std::make_shared<WBTxRx>(cards,options_txrx);
Expand Down
4 changes: 2 additions & 2 deletions executables/test_txrx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ int main(int argc, char *const *argv) {
cards.push_back(tmp_card);
WBTxRx::Options options_txrx{};
options_txrx.rtl8812au_rssi_fixup= true;
//options_txrx.set_direction= false;
options_txrx.set_direction= pcap_setdirection;
//options_txrx.pcap_rx_set_direction= false;
options_txrx.pcap_rx_set_direction = pcap_setdirection;
options_txrx.log_all_received_validated_packets= true;

std::shared_ptr<WBTxRx> txrx=std::make_shared<WBTxRx>(cards,options_txrx);
Expand Down
21 changes: 6 additions & 15 deletions executables/unit_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,33 +110,24 @@ static void test_fec_stream_random_bs_fs_overhead_dropped(){
// Test encryption+packet validation and packet validation only
static void test_encrypt_decrypt_validate(const bool use_key_from_file,bool message_signing_only) {
std::cout << "Using generated keypair (default seed otherwise):" << (use_key_from_file ? "y" : "n") << "\n";
//const std::string filename_gs="gs.key";
//const std::string filename_drone="drone.key";
const std::string filename_gs="../example_keys/gs.key";
const std::string filename_drone="../example_keys/drone.key";
wb::KeyPair encKey{};
wb::KeyPair decKey{};
const std::string KEY_FILENAME="../example_key/txrx.key";
wb::KeyPairTxRx keyPairTxRx{};
if(use_key_from_file){
encKey=wb::read_keypair_from_file(filename_gs);
decKey=wb::read_keypair_from_file(filename_gs);
keyPairTxRx=wb::read_keypair_from_file(KEY_FILENAME);
}else{
/*encKey=wb::generate_keypair_deterministic(false);
decKey=wb::generate_keypair_deterministic(false);*/
const auto before=std::chrono::steady_clock::now();
auto tmp=wb::generate_keypair_from_bind_phrase("openhd");
keyPairTxRx=wb::generate_keypair_from_bind_phrase("openhd");
std::cout<<"Generating keypair from bind phrase took:"<<MyTimeHelper::R(std::chrono::steady_clock::now()-before)<<std::endl;
encKey=tmp.drone;
decKey=tmp.drone;
}
if(message_signing_only){
std::cout<<"Testing message signing\n";
}else{
std::cout<<"Testing encryption & signing\n";
}

wb::Encryptor encryptor{encKey};
wb::Encryptor encryptor{keyPairTxRx.get_tx_key(true)};// We send from air unit
encryptor.set_encryption_enabled(!message_signing_only);
wb::Decryptor decryptor{decKey};
wb::Decryptor decryptor{keyPairTxRx.get_rx_key(false)}; // To the ground unit
decryptor.set_encryption_enabled(!message_signing_only);
struct SessionStuff{
std::array<uint8_t, crypto_box_NONCEBYTES> sessionKeyNonce{}; // random data
Expand Down
4 changes: 2 additions & 2 deletions executables/wfb_keygen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* Generates a new keypair and saves it to file for later use.
*/
int main(void) {
auto keypair=wb::generate_keypair();
auto keypair= wb::generate_keypair_random();
//auto keypair=wb::generate_keypair_from_bind_phrase("openhd");
return wb::write_to_file(keypair);
return wb::write_keypair_to_file(keypair,"txrx.key");
}
2 changes: 1 addition & 1 deletion latencyTesting/SimpleTestProgram/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ env/
_trial_temp/
test
gs.key
drone.key
key_1.key
wfb_keygen
telemetry/conf/site.cfg
telemetry/conf/local.cfg
Expand Down
109 changes: 51 additions & 58 deletions src/Encryption.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,47 +26,52 @@ static constexpr auto ENCRYPTION_ADDITIONAL_VALIDATION_DATA=crypto_aead_chacha20

namespace wb{

// A wb key consists of a public and private key
struct KeyPair {
// A wb key consists of a public and secret key
struct Key {
std::array<uint8_t,crypto_box_PUBLICKEYBYTES> public_key;
std::array<uint8_t,crypto_box_SECRETKEYBYTES> secret_key;
};

// A wb keypair are 2 keys, one for transmitting, one for receiving
// (Since both ground and air unit talk bidirectional)
// We use a different key for the down-link / uplink, respective
struct KeyPairTxRx {
// NOTE: The key itself for drone exists of drone.secret and ground.public
KeyPair drone;
KeyPair ground;
// NOTE the air key consists of key1.sec and key2.pub and vice versa
KeyPair get_keypair_air(){
return KeyPair{drone.secret_key,ground.public_key};
Key key_1;
Key key_2;
Key get_tx_key(bool is_air){
return is_air ? key_1 : key_2;
}
KeyPair get_keypair_ground(){
return KeyPair{ground.secret_key,drone.public_key};
Key get_rx_key(bool is_air){
return is_air ? key_2 : key_1;
}
};

// Generates a new keypair. Non-deterministic, 100% secure.
static KeyPairTxRx generate_keypair(){
static KeyPairTxRx generate_keypair_random(){
KeyPairTxRx ret{};
crypto_box_keypair(ret.drone.public_key.data(), ret.drone.secret_key.data());
crypto_box_keypair(ret.ground.public_key.data(), ret.ground.secret_key.data());
crypto_box_keypair(ret.key_1.public_key.data(), ret.key_1.secret_key.data());
crypto_box_keypair(ret.key_2.public_key.data(), ret.key_2.secret_key.data());
return ret;
}
static KeyPair generate_keypair_deterministic(bool is_air){
KeyPair ret{};

// Obsolete
static Key generate_keypair_deterministic(bool is_air){
Key ret{};
std::array<uint8_t , crypto_box_SEEDBYTES> seed1{0};
std::array<uint8_t , crypto_box_SEEDBYTES> seed2{1};
crypto_box_seed_keypair(ret.public_key.data(), ret.secret_key.data(),is_air ? seed1.data(): seed2.data());
return ret;
}

// Salts generated once using https://www.random.org/cgi-bin/randbyte?nbytes=16&format=d
// We want deterministic seed from a pw, and are only interested in making it impossible to reverse the process (even though the salt is plain text)
static constexpr std::array<uint8_t,crypto_pwhash_SALTBYTES> OHD_SALT_AIR{192,189,216,102,56,153,154,92,228,26,49,209,157,7,128,207};
static constexpr std::array<uint8_t,crypto_pwhash_SALTBYTES> OHD_SALT_GND{179,30,150,20,17,200,225,82,48,64,18,130,89,62,83,234};
static constexpr auto OHD_DEFAULT_TX_RX_KEY_FILENAME="txrx.key";

// See https://libsodium.gitbook.io/doc/password_hashing
static std::array<uint8_t , crypto_box_SEEDBYTES> create_seed_from_password(const std::string& pw,bool use_salt_air){
// Salts generated once using https://www.random.org/cgi-bin/randbyte?nbytes=16&format=d
// We want deterministic seed from a pw, and are only interested in making it impossible to reverse the process (even though the seed is known)
std::array<uint8_t,crypto_pwhash_SALTBYTES> salt_air{192,189,216,102,56,153,154,92,228,26,49,209,157,7,128,207};
std::array<uint8_t,crypto_pwhash_SALTBYTES> salt_gnd{179,30,150,20,17,200,225,82,48,64,18,130,89,62,83,234};
const auto salt = use_salt_air ? salt_air : salt_gnd;
const auto salt = use_salt_air ? OHD_SALT_AIR : OHD_SALT_GND;
std::array<uint8_t , crypto_box_SEEDBYTES> key{};
if (crypto_pwhash(key.data(), key.size(), pw.c_str(), pw.length(), salt.data(),
crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE,
Expand All @@ -78,59 +83,47 @@ static std::array<uint8_t , crypto_box_SEEDBYTES> create_seed_from_password(con
return key;
}

static KeyPairTxRx generate_keypair_from_bind_phrase(const std::string& bind_phrase=""){
// We always use the same bind phrase by default
static constexpr auto DEFAULT_BIND_PHRASE="openhd";
static KeyPairTxRx generate_keypair_from_bind_phrase(const std::string& bind_phrase=DEFAULT_BIND_PHRASE){
const auto seed_air= create_seed_from_password(bind_phrase, true);
const auto seed_gnd= create_seed_from_password(bind_phrase, false);
KeyPairTxRx ret{};
crypto_box_seed_keypair(ret.drone.public_key.data(), ret.drone.secret_key.data(),seed_air.data());
crypto_box_seed_keypair(ret.ground.public_key.data(), ret.ground.secret_key.data(),seed_gnd.data());
crypto_box_seed_keypair(ret.key_1.public_key.data(), ret.key_1.secret_key.data(),seed_air.data());
crypto_box_seed_keypair(ret.key_2.public_key.data(), ret.key_2.secret_key.data(),seed_gnd.data());
return ret;
}

static int write_keypair_to_file(const KeyPair& keypair,const std::string& filename){
static int write_keypair_to_file(const KeyPairTxRx& keypair_txrx,const std::string& filename){
FILE *fp;
if ((fp = fopen(filename.c_str(), "w")) == nullptr) {
std::cerr<<"Unable to save "<<filename<<std::endl;
assert(false);
return 1;
}
fwrite(keypair.secret_key.data(), crypto_box_SECRETKEYBYTES, 1, fp);
fwrite(keypair.public_key.data(), crypto_box_PUBLICKEYBYTES, 1, fp);
assert(fwrite(keypair_txrx.key_1.secret_key.data(), crypto_box_SECRETKEYBYTES, 1, fp)==1);
assert(fwrite(keypair_txrx.key_1.public_key.data(), crypto_box_PUBLICKEYBYTES, 1, fp)==1);
assert(fwrite(keypair_txrx.key_2.secret_key.data(), crypto_box_SECRETKEYBYTES, 1, fp)==1);
assert(fwrite(keypair_txrx.key_2.public_key.data(), crypto_box_PUBLICKEYBYTES, 1, fp)==1);
fclose(fp);
return 0;
}

static KeyPair read_keypair_from_file(const std::string& filename){
KeyPair ret{};
static KeyPairTxRx read_keypair_from_file(const std::string& filename){
KeyPairTxRx ret{};
FILE *fp;
if ((fp = fopen(filename.c_str(), "r")) == nullptr) {
throw std::runtime_error(fmt::format("Unable to open {}: {}", filename.c_str(), strerror(errno)));
}
if (fread(ret.secret_key.data(), crypto_box_SECRETKEYBYTES, 1, fp) != 1) {
fclose(fp);
throw std::runtime_error(fmt::format("Unable to read secret key: {}", strerror(errno)));
}
if (fread(ret.public_key.data(), crypto_box_PUBLICKEYBYTES, 1, fp) != 1) {
fclose(fp);
throw std::runtime_error(fmt::format("Unable to read public key: {}", strerror(errno)));
std::cerr<<fmt::format("Unable to open {}: {}", filename.c_str(), strerror(errno))<<std::endl;
assert(false);
}
assert(fread(ret.key_1.secret_key.data(), crypto_box_SECRETKEYBYTES, 1, fp)==1);
assert(fread(ret.key_1.public_key.data(), crypto_box_PUBLICKEYBYTES, 1, fp)==1);
assert(fread(ret.key_2.secret_key.data(), crypto_box_SECRETKEYBYTES, 1, fp)==1);
assert(fread(ret.key_2.public_key.data(), crypto_box_PUBLICKEYBYTES, 1, fp)==1);
fclose(fp);
return ret;
}

static int write_to_file(const KeyPairTxRx& data){
if(!write_keypair_to_file(
KeyPair{data.drone.secret_key,data.ground.public_key},"drone.key")){
return 1;
}
fprintf(stderr, "Drone keypair (drone sec + gs pub) saved to drone.key\n");
if(!write_keypair_to_file(
KeyPair{data.ground.secret_key,data.drone.public_key},"gs.key")){
return 1;
}
fprintf(stderr, "GS keypair (gs sec + drone pub) saved to gs.key\n");
return 0;
}


// https://libsodium.gitbook.io/doc/key_derivation
// Helper since we both support encryption and one time validation to save cpu performance
Expand All @@ -148,12 +141,12 @@ class Encryptor {
public:
/**
*
* @param keypair encryption key, otherwise enable a default deterministic encryption key by using std::nullopt
* @param key1 encryption key, otherwise enable a default deterministic encryption key by using std::nullopt
* @param DISABLE_ENCRYPTION_FOR_PERFORMANCE only validate, do not encrypt (less CPU usage)
*/
explicit Encryptor(wb::KeyPair keypair)
: tx_secretkey(keypair.secret_key),
rx_publickey(keypair.public_key){
explicit Encryptor(wb::Key key1)
: tx_secretkey(key1.secret_key),
rx_publickey(key1.public_key){
}
/**
* Creates a new session key, simply put, the data we can send publicly
Expand Down Expand Up @@ -223,8 +216,8 @@ class Decryptor {
public:
// enable a default deterministic encryption key by using std::nullopt
// else, pass path to file with encryption keys
explicit Decryptor(wb::KeyPair keypair)
:rx_secretkey(keypair.secret_key),tx_publickey(keypair.public_key){
explicit Decryptor(wb::Key key1)
:rx_secretkey(key1.secret_key),tx_publickey(key1.public_key){
memset(session_key.data(), 0, sizeof(session_key));
}
static constexpr auto SESSION_VALID_NEW=0;
Expand All @@ -248,11 +241,11 @@ class Decryptor {
return SESSION_NOT_VALID;
}
if (memcmp(session_key.data(), new_session_key.data(), sizeof(session_key)) != 0) {
// this is NOT an error, the same session key is sent multiple times !
wifibroadcast::log::get_default()->info("Decryptor-New session detected");
session_key = new_session_key;
return SESSION_VALID_NEW;
}
// this is NOT an error, the same session key is sent multiple times !
return SESSION_VALID_NOT_NEW;
}
/**
Expand Down
18 changes: 9 additions & 9 deletions src/WBTxRx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ WBTxRx::WBTxRx(std::vector<WifiCard> wifi_cards1,Options options1)
pcapTxRx.rx=wifibroadcast::pcap_helper::open_pcap_rx(wifi_card.name);
//pcapTxRx.tx=pcapTxRx.rx;
pcapTxRx.tx=wifibroadcast::pcap_helper::open_pcap_tx(wifi_card.name);
if(m_options.set_direction){
if(m_options.pcap_rx_set_direction){
const auto ret=pcap_setdirection(pcapTxRx.rx, PCAP_D_IN);
m_console->debug("pcap_setdirection() returned {}",ret);
}
Expand All @@ -54,14 +54,14 @@ WBTxRx::WBTxRx(std::vector<WifiCard> wifi_cards1,Options options1)
m_receive_pollfds[i].fd = fd;
m_receive_pollfds[i].events = POLLIN;
}
wb::KeyPair keypair{};
if(m_options.encryption_key.has_value()){
keypair= wb::read_keypair_from_file(m_options.encryption_key.value());
wb::KeyPairTxRx keypair{};
if(m_options.secure_keypair.has_value()){
keypair= m_options.secure_keypair.value();
}else{
keypair=wb::generate_keypair_deterministic(true);
keypair=wb::generate_keypair_from_bind_phrase();
}
m_encryptor=std::make_unique<wb::Encryptor>(keypair);
m_decryptor=std::make_unique<wb::Decryptor>(keypair);
m_encryptor=std::make_unique<wb::Encryptor>(keypair.get_tx_key(!m_options.use_gnd_identifier));
m_decryptor=std::make_unique<wb::Decryptor>(keypair.get_rx_key(!m_options.use_gnd_identifier));
m_encryptor->makeNewSessionKey(m_tx_sess_key_packet.sessionKeyNonce,m_tx_sess_key_packet.sessionKeyData);
// next session key in delta ms if packets are being fed
m_session_key_next_announce_ts = std::chrono::steady_clock::now();
Expand Down Expand Up @@ -750,6 +750,6 @@ void WBTxRx::recalculate_pollution_perc() {
}

std::string WBTxRx::options_to_string(const std::vector<std::string>& wifi_cards,const WBTxRx::Options& options) {
return fmt::format("Id:{} Cards:{} KeyPair:{} ",options.use_gnd_identifier ? "Ground":"Air",StringHelper::string_vec_as_string(wifi_cards),
options.encryption_key.value_or("DEFAULT_SEED"));
return fmt::format("Id:{} Cards:{} Key:{} ",options.use_gnd_identifier ? "Ground":"Air",StringHelper::string_vec_as_string(wifi_cards),
options.secure_keypair.has_value() ? "Custom" : "Default(openhd)");
}
9 changes: 4 additions & 5 deletions src/WBTxRx.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,10 @@
class WBTxRx {
public:
struct Options{
// file for encryptor
// make optional for ease of use - with no keypair given the default "seed" is used
std::optional<std::string> encryption_key = std::nullopt;
// on the rx pcap fd, set direction PCAP_D_IN (aka only packets received by the card) - doesn't work on AR9271
bool set_direction= true;
// Bidirectional, so we need 2 keys
std::optional<wb::KeyPairTxRx> secure_keypair=std::nullopt;
// on the rx pcap rx fd, set direction PCAP_D_IN (aka only packets received by the card) - doesn't work on AR9271
bool pcap_rx_set_direction = true;
// thy spam the console, but usefully for debugging
// log all received packets (regardless where they are from)
bool log_all_received_packets= false;
Expand Down

0 comments on commit 2616f7c

Please sign in to comment.