diff --git a/README.md b/README.md index 3e37fc2e..54075d42 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,15 @@ A C++ version of hotpocket designed for production envrionments, original protot ## Steps to setup Hot Pocket +### Install Libsodium +Instructions are based on [this](https://libsodium.gitbook.io/doc/installation). + +1. Download and extract Libsodium 1.0.18 from [here](https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable.tar.gz). +2. Navigate to the extracted libsodium directory in a terminal. +3. Run `./configure` +4. Run `make && make check` +5. Run `sudo make install` + #### Install Boost Following Instructions are based on Boost [getting started](https://www.boost.org/doc/libs/1_71_0/more/getting_started/unix-variants.html#prepare-to-use-a-boost-library-binary) @@ -36,5 +45,5 @@ This will update your library cache and avoid potential issues when running your 2. Run `make` 3. Run `./build/hpcore new ~/mycontract`. This will initialize a new contract directory `mycontract` in your home directory. 4. Take a look at `~/mycontract/cfg/hp.cfg`. This is your new contract config file. You can modify it according to your contract hosting requirements. -5. Run `./build/hpcore rekey ~/mycontract` to generate new public/private key pair. +5. Optional: Run `./build/hpcore rekey ~/mycontract` to generate new public/private key pair. 6. Run `./build/hpcore run ~/mycontract` to run your smart contract (to do). \ No newline at end of file diff --git a/src/conf.cpp b/src/conf.cpp index 760f6d4e..6bb11539 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -17,6 +18,34 @@ namespace conf ContractCtx ctx; ContractConfig cfg; +const char *cfg_schema = + "{" + "\"type\": \"object\"," + "\"required\": [ \"version\", \"pubkeyb64\", \"seckeyb64\", \"binary\", \"binargs\", \"listenip\"" + ", \"peers\", \"unl\", \"peerport\", \"roundtime\", \"pubport\", \"pubmaxsize\", \"pubmaxcpm\" ]," + "\"properties\": {" + "\"version\": { \"type\": \"string\" }," + "\"pubkeyb64\": { \"type\": \"string\" }," + "\"seckeyb64\": { \"type\": \"string\" }," + "\"binary\": { \"type\": \"string\" }," + "\"binargs\": { \"type\": \"string\" }," + "\"listenip\": { \"type\": \"string\" }," + "\"peers\": {" + "\"type\": \"array\"," + "\"items\": { \"type\": \"string\" }" + "}," + "\"unl\": {" + "\"type\": \"array\"," + "\"items\": { \"type\": \"string\" }" + "}," + "\"peerport\": { \"type\": \"integer\" }," + "\"roundtime\": { \"type\": \"integer\" }," + "\"pubport\": { \"type\": \"integer\" }," + "\"pubmaxsize\": { \"type\": \"integer\" }," + "\"pubmaxcpm\": { \"type\": \"integer\" }" + "}" + "}"; + // v1 < v2 -> -1 // v1 == v2 -> 0 // v1 > v2 -> +1 @@ -49,13 +78,32 @@ int version_compare(std::string v1, std::string v2) return 0; } +bool is_schema_valid(Document &d) +{ + Document sd; + sd.Parse(cfg_schema); + SchemaDocument schema(sd); + + SchemaValidator validator(schema); + return d.Accept(validator); +} + int load_config() { ifstream ifs(ctx.configFile); IStreamWrapper isw(ifs); Document d; - d.ParseStream(isw); + if (d.ParseStream(isw).HasParseError()) + { + cerr << "Invalid config file format. Parser error at position " << d.GetErrorOffset() << endl; + return 0; + } + else if (!is_schema_valid(d)) + { + cerr << "Invalid config file format.\n"; + return 0; + } //Check contract version. string cfgVersion = d["version"].GetString(); diff --git a/src/crypto.cpp b/src/crypto.cpp index c0942a85..0ebf57f8 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -100,17 +100,34 @@ int init() return 0; } - //If any keys are missing generate a new pair and save to file. - if (conf::cfg.pubkeyb64.empty() || conf::cfg.seckeyb64.empty()) + if (conf::ctx.command == "new" || conf::ctx.command == "rekey") { cout << "Generating new keys.\n"; generate_crypto_keys(); cryptopair_to_b64(); conf::save_config(); } - else + else if (conf::ctx.command == "run") { - b64pair_to_crypto(); + if (conf::cfg.pubkeyb64.empty() || conf::cfg.seckeyb64.empty()) + { + cerr << "Signing keys missing. Run with 'rekey' to generate new keys.\n"; + return 0; + } + else + { + //Decode b64 keys into bytes and store in memory. + b64pair_to_crypto(); + + //Sign and verify a sample to ensure we have a matching key pair. + string msg = "hotpocket"; + string sigb64 = sign_b64(msg); + if (!verify_b64(msg, sigb64, conf::cfg.pubkeyb64)) + { + cerr << "Invalid signing keys. Run with 'rekey' to generate new keys.\n"; + return 0; + } + } } return 1;