mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
Changed base64 to hex encoding.
This commit is contained in:
@@ -41,7 +41,7 @@ function main() {
|
||||
{
|
||||
hotpocket: 0.1,
|
||||
type: 'public_challenge',
|
||||
challenge: '<base64 string>'
|
||||
challenge: '<hex string>'
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -68,15 +68,16 @@ function main() {
|
||||
console.log("Received challenge message")
|
||||
console.log(m)
|
||||
|
||||
console.log('My public key is: ' + Buffer.from(keys.publicKey).toString('base64'));
|
||||
let pkhex = 'ed' + Buffer.from(keys.publicKey).toString('hex');
|
||||
console.log('My public key is: ' + pkhex);
|
||||
|
||||
// sign the challenge and send back the response
|
||||
var sigbytes = sodium.crypto_sign_detached(m.challenge, keys.privateKey);
|
||||
var response = {
|
||||
type: 'challenge_response',
|
||||
challenge: m.challenge,
|
||||
sig: Buffer.from(sigbytes).toString('base64'),
|
||||
pubkey: Buffer.from(keys.publicKey).toString('base64')
|
||||
sig: Buffer.from(sigbytes).toString('hex'),
|
||||
pubkey: pkhex
|
||||
}
|
||||
|
||||
console.log('Sending challenge response...');
|
||||
|
||||
65
src/conf.cpp
65
src/conf.cpp
@@ -49,7 +49,7 @@ int rekey()
|
||||
return -1;
|
||||
|
||||
crypto::generate_signing_keys(cfg.pubkey, cfg.seckey, cfg.keytype);
|
||||
if (binpair_to_b64() != 0)
|
||||
if (binpair_to_hex() != 0)
|
||||
return -1;
|
||||
|
||||
if (save_config() != 0)
|
||||
@@ -82,7 +82,7 @@ int create_contract()
|
||||
//We populate the in-memory struct with default settings and then save it to the file.
|
||||
|
||||
crypto::generate_signing_keys(cfg.pubkey, cfg.seckey, cfg.keytype);
|
||||
if (binpair_to_b64() != 0)
|
||||
if (binpair_to_hex() != 0)
|
||||
return -1;
|
||||
|
||||
cfg.listenip = "0.0.0.0";
|
||||
@@ -167,8 +167,8 @@ int load_config()
|
||||
|
||||
// Load up the values into the struct.
|
||||
|
||||
cfg.pubkeyb64 = d["pubkeyb64"].GetString();
|
||||
cfg.seckeyb64 = d["seckeyb64"].GetString();
|
||||
cfg.pubkeyhex = d["pubkeyhex"].GetString();
|
||||
cfg.seckeyhex = d["seckeyhex"].GetString();
|
||||
cfg.keytype = d["keytype"].GetString();
|
||||
cfg.binary = d["binary"].GetString();
|
||||
cfg.binargs = d["binargs"].GetString();
|
||||
@@ -188,8 +188,8 @@ int load_config()
|
||||
cfg.pubmaxsize = d["pubmaxsize"].GetInt();
|
||||
cfg.pubmaxcpm = d["pubmaxcpm"].GetInt();
|
||||
|
||||
// Convert the b64 keys to binary and keep for later use.
|
||||
if (b64pair_to_bin() != 0)
|
||||
// Convert the hex keys to binary and keep for later use.
|
||||
if (hexpair_to_bin() != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@@ -208,8 +208,8 @@ int save_config()
|
||||
d.SetObject();
|
||||
rapidjson::Document::AllocatorType &allocator = d.GetAllocator();
|
||||
d.AddMember("version", rapidjson::StringRef(util::HP_VERSION), allocator);
|
||||
d.AddMember("pubkeyb64", rapidjson::StringRef(cfg.pubkeyb64.data()), allocator);
|
||||
d.AddMember("seckeyb64", rapidjson::StringRef(cfg.seckeyb64.data()), allocator);
|
||||
d.AddMember("pubkeyhex", rapidjson::StringRef(cfg.pubkeyhex.data()), allocator);
|
||||
d.AddMember("seckeyhex", rapidjson::StringRef(cfg.seckeyhex.data()), allocator);
|
||||
d.AddMember("keytype", rapidjson::StringRef(cfg.keytype.data()), allocator);
|
||||
d.AddMember("binary", rapidjson::StringRef(cfg.binary.data()), allocator);
|
||||
d.AddMember("binargs", rapidjson::StringRef(cfg.binargs.data()), allocator);
|
||||
@@ -256,25 +256,25 @@ int save_config()
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode current binary keys in 'cfg' and populate the it with base64 keys.
|
||||
* Decode current binary keys in 'cfg' and populate the it with hex keys.
|
||||
*
|
||||
* @return 0 for successful conversion. -1 for failure.
|
||||
*/
|
||||
int binpair_to_b64()
|
||||
int binpair_to_hex()
|
||||
{
|
||||
if (util::base64_encode(
|
||||
cfg.pubkeyb64,
|
||||
if (util::bin2hex(
|
||||
cfg.pubkeyhex,
|
||||
reinterpret_cast<const unsigned char *>(cfg.pubkey.data()),
|
||||
crypto_sign_PUBLICKEYBYTES) != 0)
|
||||
cfg.pubkey.length()) != 0)
|
||||
{
|
||||
std::cerr << "Error encoding public key bytes.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (util::base64_encode(
|
||||
cfg.seckeyb64,
|
||||
if (util::bin2hex(
|
||||
cfg.seckeyhex,
|
||||
reinterpret_cast<const unsigned char *>(cfg.seckey.data()),
|
||||
crypto_sign_SECRETKEYBYTES) != 0)
|
||||
cfg.seckey.length()) != 0)
|
||||
{
|
||||
std::cerr << "Error encoding secret key bytes.\n";
|
||||
return -1;
|
||||
@@ -284,28 +284,29 @@ int binpair_to_b64()
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode current base64 keys in 'cfg' and populate the it with binary keys.
|
||||
* Decode current hex keys in 'cfg' and populate the it with binary keys.
|
||||
*
|
||||
* @return 0 for successful conversion. -1 for failure.
|
||||
*/
|
||||
int b64pair_to_bin()
|
||||
int hexpair_to_bin()
|
||||
{
|
||||
cfg.pubkey.resize(crypto_sign_PUBLICKEYBYTES);
|
||||
if (util::base64_decode(
|
||||
cfg.pubkey.resize(crypto::PFXD_PUBKEY_BYTES);
|
||||
if (util::hex2bin(
|
||||
reinterpret_cast<unsigned char *>(cfg.pubkey.data()),
|
||||
cfg.pubkey.length(), cfg.pubkeyb64) != 0)
|
||||
cfg.pubkey.length(),
|
||||
cfg.pubkeyhex) != 0)
|
||||
{
|
||||
std::cerr << "Error decoding base64 public key.\n";
|
||||
std::cerr << "Error decoding hex public key.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
cfg.seckey.resize(crypto_sign_SECRETKEYBYTES);
|
||||
if (util::base64_decode(
|
||||
cfg.seckey.resize(crypto::PFXD_SECKEY_BYTES);
|
||||
if (util::hex2bin(
|
||||
reinterpret_cast<unsigned char *>(cfg.seckey.data()),
|
||||
cfg.seckey.length(),
|
||||
cfg.seckeyb64) != 0)
|
||||
cfg.seckeyhex) != 0)
|
||||
{
|
||||
std::cerr << "Error decoding base64 secret key.\n";
|
||||
std::cerr << "Error decoding hex secret key.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -321,7 +322,7 @@ int validate_config()
|
||||
{
|
||||
// Check for non-empty signing keys.
|
||||
// We also check for key pair validity as well in the below code.
|
||||
if (cfg.pubkeyb64.empty() || cfg.seckeyb64.empty())
|
||||
if (cfg.pubkeyhex.empty() || cfg.seckeyhex.empty())
|
||||
{
|
||||
std::cerr << "Signing keys missing. Run with 'rekey' to generate new keys.\n";
|
||||
return -1;
|
||||
@@ -344,8 +345,8 @@ int validate_config()
|
||||
|
||||
//Sign and verify a sample message to ensure we have a matching signing key pair.
|
||||
std::string msg = "hotpocket";
|
||||
std::string sigb64 = crypto::sign_b64(msg, cfg.seckeyb64);
|
||||
if (crypto::verify_b64(msg, sigb64, cfg.pubkeyb64) != 0)
|
||||
std::string sighex = crypto::sign_hex(msg, cfg.seckeyhex);
|
||||
if (crypto::verify_hex(msg, sighex, cfg.pubkeyhex) != 0)
|
||||
{
|
||||
std::cerr << "Invalid signing keys. Run with 'rekey' to generate new keys.\n";
|
||||
return -1;
|
||||
@@ -385,12 +386,12 @@ int is_schema_valid(rapidjson::Document &d)
|
||||
const char *cfg_schema =
|
||||
"{"
|
||||
"\"type\": \"object\","
|
||||
"\"required\": [ \"version\", \"pubkeyb64\", \"seckeyb64\", \"keytype\", \"binary\", \"binargs\", \"listenip\""
|
||||
"\"required\": [ \"version\", \"pubkeyhex\", \"seckeyhex\", \"keytype\", \"binary\", \"binargs\", \"listenip\""
|
||||
", \"peers\", \"unl\", \"peerport\", \"roundtime\", \"pubport\", \"pubmaxsize\", \"pubmaxcpm\" ],"
|
||||
"\"properties\": {"
|
||||
"\"version\": { \"type\": \"string\" },"
|
||||
"\"pubkeyb64\": { \"type\": \"string\" },"
|
||||
"\"seckeyb64\": { \"type\": \"string\" },"
|
||||
"\"pubkeyhex\": { \"type\": \"string\" },"
|
||||
"\"seckeyhex\": { \"type\": \"string\" },"
|
||||
"\"keytype\": { \"type\": \"string\" },"
|
||||
"\"binary\": { \"type\": \"string\" },"
|
||||
"\"binargs\": { \"type\": \"string\" },"
|
||||
|
||||
10
src/conf.hpp
10
src/conf.hpp
@@ -33,14 +33,14 @@ struct contract_config
|
||||
|
||||
// Config elements which are loaded from the config file.
|
||||
|
||||
std::string pubkeyb64; // Contract base64 public key
|
||||
std::string seckeyb64; // Contract base64 secret key
|
||||
std::string pubkeyhex; // Contract hex public key
|
||||
std::string seckeyhex; // Contract hex secret key
|
||||
std::string keytype; // Key generation algorithm used by libsodium
|
||||
std::string binary; // Full path to the contract binary
|
||||
std::string binargs; // CLI arguments to pass to the contract binary
|
||||
std::string listenip; // The IPs to listen on for incoming connections
|
||||
std::vector<std::string> peers; // List of peers in the format "<ip address>:<port>"
|
||||
std::vector<std::string> unl; // Unique node list (list of base64 public keys)
|
||||
std::vector<std::string> unl; // Unique node list (list of hex public keys)
|
||||
unsigned short peerport; // Listening port for peer connections
|
||||
int roundtime; // Consensus round time in ms
|
||||
unsigned short pubport; // Listening port for public user connections
|
||||
@@ -76,9 +76,9 @@ int validate_contract_dir_paths();
|
||||
|
||||
int is_schema_valid(rapidjson::Document &d);
|
||||
|
||||
int binpair_to_b64();
|
||||
int binpair_to_hex();
|
||||
|
||||
int b64pair_to_bin();
|
||||
int hexpair_to_bin();
|
||||
|
||||
} // namespace conf
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <sodium.h>
|
||||
#include "crypto.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
@@ -27,13 +26,18 @@ int init()
|
||||
*/
|
||||
void generate_signing_keys(std::string &pubkey, std::string &seckey, std::string &keytype)
|
||||
{
|
||||
//Generate key pair using libsodium default algorithm. (Currently using ed25519)
|
||||
// Generate key pair using libsodium default algorithm.
|
||||
// Currently using ed25519. So append prefix byte to represent that.
|
||||
|
||||
pubkey.resize(PFXD_PUBKEY_BYTES);
|
||||
pubkey[0] = KEYPFX_ed25519;
|
||||
|
||||
seckey.resize(PFXD_SECKEY_BYTES);
|
||||
seckey[0] = KEYPFX_ed25519;
|
||||
|
||||
pubkey.resize(crypto_sign_PUBLICKEYBYTES);
|
||||
seckey.resize(crypto_sign_SECRETKEYBYTES);
|
||||
crypto_sign_keypair(
|
||||
reinterpret_cast<unsigned char *>(pubkey.data()),
|
||||
reinterpret_cast<unsigned char *>(seckey.data()));
|
||||
reinterpret_cast<unsigned char *>(pubkey.data() + 1),
|
||||
reinterpret_cast<unsigned char *>(seckey.data() + 1));
|
||||
|
||||
keytype = crypto_sign_primitive();
|
||||
}
|
||||
@@ -56,24 +60,24 @@ std::string sign(std::string_view msg, std::string_view seckey)
|
||||
NULL,
|
||||
reinterpret_cast<const unsigned char *>(msg.data()),
|
||||
msg.length(),
|
||||
reinterpret_cast<const unsigned char *>(seckey.data()));
|
||||
reinterpret_cast<const unsigned char *>(seckey.data() + 1)); // +1 to skip the prefix byte.
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base64 signature string for a message.
|
||||
* Returns the hex signature string for a message.
|
||||
*
|
||||
* @param msg Message bytes to sign.
|
||||
* @param seckeyb64 Base64 secret key string.
|
||||
* @return Base64 signature string.
|
||||
* @param seckeyhex hex secret key string.
|
||||
* @return hex signature string.
|
||||
*/
|
||||
std::string sign_b64(std::string_view msg, std::string_view seckeyb64)
|
||||
std::string sign_hex(std::string_view msg, std::string_view seckeyhex)
|
||||
{
|
||||
//Decode b64 string and generate the signature using libsodium.
|
||||
//Decode hex string and generate the signature using libsodium.
|
||||
|
||||
unsigned char seckey[crypto_sign_SECRETKEYBYTES];
|
||||
util::base64_decode(seckey, crypto_sign_SECRETKEYBYTES, seckeyb64);
|
||||
unsigned char seckey[PFXD_SECKEY_BYTES];
|
||||
util::hex2bin(seckey, PFXD_SECKEY_BYTES, seckeyhex);
|
||||
|
||||
unsigned char sig[crypto_sign_BYTES];
|
||||
crypto_sign_detached(
|
||||
@@ -81,11 +85,11 @@ std::string sign_b64(std::string_view msg, std::string_view seckeyb64)
|
||||
NULL,
|
||||
reinterpret_cast<const unsigned char *>(msg.data()),
|
||||
msg.length(),
|
||||
seckey);
|
||||
seckey + 1); // +1 to skip prefix byte.
|
||||
|
||||
std::string sigb64;
|
||||
util::base64_encode(sigb64, sig, crypto_sign_BYTES);
|
||||
return sigb64;
|
||||
std::string sighex;
|
||||
util::bin2hex(sighex, sig, crypto_sign_BYTES);
|
||||
return sighex;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,32 +106,32 @@ int verify(std::string_view msg, std::string_view sig, std::string_view pubkey)
|
||||
reinterpret_cast<const unsigned char *>(sig.data()),
|
||||
reinterpret_cast<const unsigned char *>(msg.data()),
|
||||
msg.length(),
|
||||
reinterpret_cast<const unsigned char *>(pubkey.data()));
|
||||
reinterpret_cast<const unsigned char *>(pubkey.data() + 1)); // +1 to skip prefix byte.
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the given base64 signature for the message.
|
||||
* Verifies the given hex signature for the message.
|
||||
*
|
||||
* @param msg Base64 message string.
|
||||
* @param sigb64 Base64 signature string.
|
||||
* @param pubkeyb64 Base64 secret key.
|
||||
* @param msg hex message string.
|
||||
* @param sighex hex signature string.
|
||||
* @param pubkeyhex hex secret key.
|
||||
* @return 0 for successful verification. -1 for failure.
|
||||
*/
|
||||
int verify_b64(std::string_view msg, std::string_view sigb64, std::string_view pubkeyb64)
|
||||
int verify_hex(std::string_view msg, std::string_view sighex, std::string_view pubkeyhex)
|
||||
{
|
||||
//Decode b64 string and verify the signature using libsodium.
|
||||
//Decode hex string and verify the signature using libsodium.
|
||||
|
||||
unsigned char decoded_pubkey[crypto_sign_PUBLICKEYBYTES];
|
||||
util::base64_decode(decoded_pubkey, crypto_sign_PUBLICKEYBYTES, pubkeyb64);
|
||||
unsigned char decoded_pubkey[PFXD_PUBKEY_BYTES];
|
||||
util::hex2bin(decoded_pubkey, PFXD_PUBKEY_BYTES, pubkeyhex);
|
||||
|
||||
unsigned char decoded_sig[crypto_sign_BYTES];
|
||||
util::base64_decode(decoded_sig, crypto_sign_BYTES, sigb64);
|
||||
util::hex2bin(decoded_sig, crypto_sign_BYTES, sighex);
|
||||
|
||||
return crypto_sign_verify_detached(
|
||||
decoded_sig,
|
||||
reinterpret_cast<const unsigned char *>(msg.data()),
|
||||
msg.length(),
|
||||
decoded_pubkey);
|
||||
decoded_pubkey + 1); // +1 to skip prefix byte.
|
||||
}
|
||||
|
||||
} // namespace crypto
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef _HP_CRYPTO_H_
|
||||
#define _HP_CRYPTO_H_
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
/**
|
||||
* Offers convenience functions for cryptographic operations wrapping libsodium.
|
||||
* These functions are used for contract config and user/peer message authentication.
|
||||
@@ -8,17 +10,24 @@
|
||||
namespace crypto
|
||||
{
|
||||
|
||||
// Prefix byte to append to ed25519 keys.
|
||||
static unsigned char KEYPFX_ed25519 = 0xED;
|
||||
// Prefixed public key bytes.
|
||||
static size_t PFXD_PUBKEY_BYTES = crypto_sign_PUBLICKEYBYTES + 1;
|
||||
// Prefixed secret key bytes.
|
||||
static size_t PFXD_SECKEY_BYTES = crypto_sign_SECRETKEYBYTES + 1;
|
||||
|
||||
int init();
|
||||
|
||||
void generate_signing_keys(std::string &pubkey, std::string &seckey, std::string &keytype);
|
||||
|
||||
std::string sign(std::string_view msg, std::string_view seckey);
|
||||
|
||||
std::string sign_b64(std::string_view msg, std::string_view seckeyb64);
|
||||
std::string sign_hex(std::string_view msg, std::string_view seckeyhex);
|
||||
|
||||
int verify(std::string_view msg, std::string_view sig, std::string_view pubkey);
|
||||
|
||||
int verify_b64(std::string_view msg, std::string_view sigb64, std::string_view pubkeyb64);
|
||||
int verify_hex(std::string_view msg, std::string_view sighex, std::string_view pubkeyhex);
|
||||
|
||||
} // namespace crypto
|
||||
|
||||
|
||||
24
src/proc.cpp
24
src/proc.cpp
@@ -111,7 +111,7 @@ int exec_contract(const ContractExecArgs &args)
|
||||
/**
|
||||
* Blocks the calling thread until the contract process compelted exeution (if running).
|
||||
*
|
||||
* @returns 0 if contract process exited normally, exit code of contract process if abnormally exited.
|
||||
* @return 0 if contract process exited normally, exit code of contract process if abnormally exited.
|
||||
*/
|
||||
int await_contract_execution()
|
||||
{
|
||||
@@ -130,11 +130,11 @@ int await_contract_execution()
|
||||
* Input format:
|
||||
* {
|
||||
* "version":"<hp version>",
|
||||
* "pubkey": "<this node's base64 public key>",
|
||||
* "pubkey": "<this node's hex public key>",
|
||||
* "ts": <this node's timestamp (unix milliseconds)>,
|
||||
* "usrfd":{ "<pkb64>":[fd0, fd1], ... },
|
||||
* "nplfd":{ "<pkb64>":[fd0, fd1], ... },
|
||||
* "unl":[ "pkb64", ... ]
|
||||
* "usrfd":{ "<pkhex>":[fd0, fd1], ... },
|
||||
* "nplfd":{ "<pkhex>":[fd0, fd1], ... },
|
||||
* "unl":[ "pkhex", ... ]
|
||||
* }
|
||||
*/
|
||||
int write_to_stdin(const ContractExecArgs &args)
|
||||
@@ -145,7 +145,7 @@ int write_to_stdin(const ContractExecArgs &args)
|
||||
|
||||
std::ostringstream os;
|
||||
os << "{\"version\":\"" << util::HP_VERSION
|
||||
<< "\",\"pubkey\":\"" << conf::cfg.pubkeyb64
|
||||
<< "\",\"pubkey\":\"" << conf::cfg.pubkeyhex
|
||||
<< "\",\"ts\":" << args.timestamp
|
||||
<< ",\"usrfd\":{";
|
||||
|
||||
@@ -154,16 +154,16 @@ int write_to_stdin(const ContractExecArgs &args)
|
||||
if (itr != userfds.begin())
|
||||
os << ","; // Trailing comma separator for previous element.
|
||||
|
||||
// Get the base64 pubkey of the user.
|
||||
// Get the hex pubkey of the user.
|
||||
std::string_view userpubkey = itr->first; // User pubkey in binary format.
|
||||
std::string userpubkeyb64;
|
||||
util::base64_encode(
|
||||
userpubkeyb64,
|
||||
std::string userpubkeyhex;
|
||||
util::bin2hex(
|
||||
userpubkeyhex,
|
||||
reinterpret_cast<const unsigned char *>(userpubkey.data()),
|
||||
userpubkey.length());
|
||||
|
||||
// Write user base64 pubkey and fds.
|
||||
os << "\"" << userpubkeyb64 << "\":["
|
||||
// Write user hex pubkey and fds.
|
||||
os << "\"" << userpubkeyhex << "\":["
|
||||
<< itr->second[FDTYPE::SCREAD] << ","
|
||||
<< itr->second[FDTYPE::SCWRITE] << "]";
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/websocket.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <sodium.h>
|
||||
#include "../util.hpp"
|
||||
#include "../sock/socket_session.hpp"
|
||||
#include "../proc.hpp"
|
||||
@@ -30,14 +29,14 @@ void user_session_handler::on_connect(sock::socket_session *session)
|
||||
// challenge we issued and later verifies the user's response with it.
|
||||
|
||||
std::string msg;
|
||||
std::string challengeb64;
|
||||
usr::create_user_challenge(msg, challengeb64);
|
||||
std::string challengehex;
|
||||
usr::create_user_challenge(msg, challengehex);
|
||||
|
||||
// We init the session unique id to associate with the challenge.
|
||||
session->init_uniqueid();
|
||||
|
||||
// Create an entry in pending_challenges for later tracking upon challenge response.
|
||||
usr::pending_challenges[session->uniqueid_] = challengeb64;
|
||||
usr::pending_challenges[session->uniqueid_] = challengehex;
|
||||
|
||||
session->send(std::move(msg));
|
||||
|
||||
@@ -58,20 +57,20 @@ void user_session_handler::on_message(sock::socket_session *session, std::string
|
||||
auto itr = usr::pending_challenges.find(session->uniqueid_);
|
||||
if (itr != usr::pending_challenges.end())
|
||||
{
|
||||
std::string userpubkeyb64;
|
||||
std::string userpubkeyhex;
|
||||
std::string_view original_challenge = itr->second;
|
||||
if (usr::verify_user_challenge_response(userpubkeyb64, message, original_challenge) == 0)
|
||||
if (usr::verify_user_challenge_response(userpubkeyhex, message, original_challenge) == 0)
|
||||
{
|
||||
// Challenge singature verification successful.
|
||||
|
||||
// Decode b64 pubkey and get binary pubkey. We area only going to keep
|
||||
// Decode hex pubkey and get binary pubkey. We area only going to keep
|
||||
// the binary pubkey due to reduced memory footprint.
|
||||
std::string userpubkey;
|
||||
userpubkey.resize(crypto_sign_PUBLICKEYBYTES);
|
||||
util::base64_decode(
|
||||
userpubkey.resize(userpubkeyhex.length() / 2);
|
||||
util::hex2bin(
|
||||
reinterpret_cast<unsigned char *>(userpubkey.data()),
|
||||
userpubkey.length(),
|
||||
userpubkeyb64);
|
||||
userpubkeyhex);
|
||||
|
||||
// Now check whether this user public key is duplicate.
|
||||
if (usr::sessionids.count(userpubkey) == 0)
|
||||
@@ -85,7 +84,7 @@ void user_session_handler::on_message(sock::socket_session *session, std::string
|
||||
usr::pending_challenges.erase(session->uniqueid_); // Remove the stored challenge
|
||||
|
||||
std::cout << "User connection " << session->uniqueid_ << " authenticated. Public key "
|
||||
<< userpubkeyb64 << std::endl;
|
||||
<< userpubkeyhex << std::endl;
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -61,7 +61,7 @@ static const char *CHALLENGE_MSGTYPE = "public_challenge";
|
||||
// Message type for the user challenge response.
|
||||
static const char *CHALLENGE_RESP_MSGTYPE = "challenge_response";
|
||||
// Length of user random challenge bytes.
|
||||
static const int CHALLENGE_LEN = 16;
|
||||
static const size_t CHALLENGE_LEN = 16;
|
||||
|
||||
/**
|
||||
* Initializes the usr subsystem. Must be called once during application startup.
|
||||
@@ -93,20 +93,20 @@ void deinit()
|
||||
* {
|
||||
* "version": "<HP version>",
|
||||
* "type": "public_challenge",
|
||||
* "challenge": "<base64 challenge string>"
|
||||
* "challenge": "<hex challenge string>"
|
||||
* }
|
||||
* @param challenge String reference to copy the generated base64 challenge string into.
|
||||
* @param challenge String reference to copy the generated hex challenge string into.
|
||||
*/
|
||||
void create_user_challenge(std::string &msg, std::string &challengeb64)
|
||||
void create_user_challenge(std::string &msg, std::string &challengehex)
|
||||
{
|
||||
//Use libsodium to generate the random challenge bytes.
|
||||
unsigned char challenge_bytes[CHALLENGE_LEN];
|
||||
randombytes_buf(challenge_bytes, CHALLENGE_LEN);
|
||||
|
||||
//We pass the b64 challenge string separately to the caller even though
|
||||
//We pass the hex challenge string separately to the caller even though
|
||||
//we also include it in the challenge msg as well.
|
||||
|
||||
util::base64_encode(challengeb64, challenge_bytes, CHALLENGE_LEN);
|
||||
util::bin2hex(challengehex, challenge_bytes, CHALLENGE_LEN);
|
||||
|
||||
//Construct the challenge msg json.
|
||||
// We do not use RapidJson here in favour of performance because this is a simple json message.
|
||||
@@ -118,7 +118,7 @@ void create_user_challenge(std::string &msg, std::string &challengeb64)
|
||||
msg.append("{\"version\":\"")
|
||||
.append(util::HP_VERSION)
|
||||
.append("\",\"type\":\"public_challenge\",\"challenge\":\"")
|
||||
.append(challengeb64)
|
||||
.append(challengehex)
|
||||
.append("\"}");
|
||||
}
|
||||
|
||||
@@ -126,19 +126,19 @@ void create_user_challenge(std::string &msg, std::string &challengeb64)
|
||||
* Verifies the user challenge response with the original challenge issued to the user
|
||||
* and the user public key contained in the response.
|
||||
*
|
||||
* @param extracted_pubkeyb64 The base64 public key extracted from the response.
|
||||
* @param extracted_pubkeyhex The hex public key extracted from the response.
|
||||
* @param response The response bytes to verify. This will be parsed as json.
|
||||
* Accepted response format:
|
||||
* {
|
||||
* "type": "challenge_response",
|
||||
* "challenge": "<original base64 challenge the user received>",
|
||||
* "sig": "<Base64 signature of the challenge>",
|
||||
* "pubkey": "<Base64 public key of the user>"
|
||||
* "challenge": "<original hex challenge the user received>",
|
||||
* "sig": "<hex signature of the challenge>",
|
||||
* "pubkey": "<hex public key of the user>"
|
||||
* }
|
||||
* @param original_challenge The original base64 challenge string issued to the user.
|
||||
* @param original_challenge The original hex challenge string issued to the user.
|
||||
* @return 0 if challenge response is verified. -1 if challenge not met or an error occurs.
|
||||
*/
|
||||
int verify_user_challenge_response(std::string &extracted_pubkeyb64, std::string_view response, std::string_view original_challenge)
|
||||
int verify_user_challenge_response(std::string &extracted_pubkeyhex, std::string_view response, std::string_view original_challenge)
|
||||
{
|
||||
// We load response raw bytes into json document.
|
||||
rapidjson::Document d;
|
||||
@@ -179,7 +179,7 @@ int verify_user_challenge_response(std::string &extracted_pubkeyb64, std::string
|
||||
|
||||
// Verify the challenge signature. We do this last due to signature verification cost.
|
||||
std::string_view pubkeysv = util::getsv(d[CHALLENGE_RESP_PUBKEY]);
|
||||
if (crypto::verify_b64(
|
||||
if (crypto::verify_hex(
|
||||
original_challenge,
|
||||
util::getsv(d[CHALLENGE_RESP_SIG]),
|
||||
pubkeysv) != 0)
|
||||
@@ -188,7 +188,7 @@ int verify_user_challenge_response(std::string &extracted_pubkeyb64, std::string
|
||||
return -1;
|
||||
}
|
||||
|
||||
extracted_pubkeyb64 = pubkeysv;
|
||||
extracted_pubkeyhex = pubkeysv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -60,9 +60,9 @@ int init();
|
||||
|
||||
void deinit();
|
||||
|
||||
void create_user_challenge(std::string &msg, std::string &challengeb64);
|
||||
void create_user_challenge(std::string &msg, std::string &challengehex);
|
||||
|
||||
int verify_user_challenge_response(std::string &extracted_pubkeyb64, std::string_view response, std::string_view original_challenge);
|
||||
int verify_user_challenge_response(std::string &extracted_pubkeyhex, std::string_view response, std::string_view original_challenge);
|
||||
|
||||
int add_user(sock::socket_session *session, const std::string &pubkey);
|
||||
|
||||
|
||||
43
src/util.cpp
43
src/util.cpp
@@ -7,49 +7,44 @@ namespace util
|
||||
{
|
||||
|
||||
/**
|
||||
* Encodes provided bytes to base64 string.
|
||||
* Encodes provided bytes to hex string.
|
||||
*
|
||||
* @param encoded_string String reference to assign the base64 encoded output.
|
||||
* @param encoded_string String reference to assign the hex encoded output.
|
||||
* @param bin Bytes to encode.
|
||||
* @param bin_len Bytes length.
|
||||
* @return Always returns 0.
|
||||
*/
|
||||
int base64_encode(std::string &encoded_string, const unsigned char *bin, size_t bin_len)
|
||||
int bin2hex(std::string &encoded_string, const unsigned char *bin, size_t bin_len)
|
||||
{
|
||||
// Get length of encoded result from sodium.
|
||||
const size_t base64_len = sodium_base64_encoded_len(bin_len, sodium_base64_VARIANT_ORIGINAL);
|
||||
|
||||
// "base64_len - 1" because sodium include '\0' in the calculated base64 length.
|
||||
// Therefore we need to omit it when initializing the std::string.
|
||||
encoded_string.resize(base64_len - 1);
|
||||
// Allocate the target string.
|
||||
encoded_string.resize(bin_len * 2);
|
||||
|
||||
// Get encoded string.
|
||||
const char *encoded_str_char = sodium_bin2base64(
|
||||
encoded_string.data(), base64_len,
|
||||
bin, bin_len,
|
||||
sodium_base64_VARIANT_ORIGINAL);
|
||||
|
||||
if (encoded_str_char == NULL)
|
||||
return -1;
|
||||
sodium_bin2hex(
|
||||
encoded_string.data(),
|
||||
encoded_string.length() + 1, // + 1 because sodium writes ending '\0' character as well.
|
||||
bin,
|
||||
bin_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes provided base64 string into bytes.
|
||||
* Decodes provided hex string into bytes.
|
||||
*
|
||||
* @param decodedbuf Buffer to assign decoded bytes.
|
||||
* @param decodedbuf_len Decoded buffer size.
|
||||
* @param base64_str Base64 string to decode.
|
||||
* @param hex_str hex string to decode.
|
||||
*/
|
||||
int base64_decode(unsigned char *decodedbuf, size_t decodedbuf_len, std::string_view base64_str)
|
||||
int hex2bin(unsigned char *decodedbuf, size_t decodedbuf_len, std::string_view hex_str)
|
||||
{
|
||||
const char *b64_end;
|
||||
const char *hex_end;
|
||||
size_t bin_len;
|
||||
if (sodium_base642bin(
|
||||
if (sodium_hex2bin(
|
||||
decodedbuf, decodedbuf_len,
|
||||
base64_str.data(), base64_str.size() + 1,
|
||||
"", &bin_len, &b64_end,
|
||||
sodium_base64_VARIANT_ORIGINAL))
|
||||
hex_str.data(),
|
||||
hex_str.length(),
|
||||
"", &bin_len, &hex_end))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
23
src/util.hpp
23
src/util.hpp
@@ -32,28 +32,9 @@ enum SESSION_FLAG
|
||||
USER_AUTHED = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* Holds information about a HotPocket peer connected to this node.
|
||||
*/
|
||||
struct peer_node
|
||||
{
|
||||
std::string pubkeyb64; // Base64 peer public key
|
||||
int inpipe[2]; // NPL pipe from HP to SC
|
||||
int outpipe[2]; // NPL pipe from SC to HP
|
||||
int bin2hex(std::string &encoded_string, const unsigned char *bin, size_t bin_len);
|
||||
|
||||
peer_node(std::string_view _pubkeyb64, int _inpipe[2], int _outpipe[2])
|
||||
{
|
||||
pubkeyb64 = _pubkeyb64;
|
||||
inpipe[0] = _inpipe[0];
|
||||
inpipe[1] = _inpipe[1];
|
||||
outpipe[0] = _outpipe[0];
|
||||
outpipe[1] = _outpipe[1];
|
||||
}
|
||||
};
|
||||
|
||||
int base64_encode(std::string &encoded_string, const unsigned char *bin, size_t bin_len);
|
||||
|
||||
int base64_decode(unsigned char *decoded, size_t decoded_len, std::string_view base64_str);
|
||||
int hex2bin(unsigned char *decoded, size_t decoded_len, std::string_view hex_str);
|
||||
|
||||
int version_compare(const std::string &x, const std::string &y);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user