Obtains Gateway's encryption keys. If the key file exists, it's contents will be Base64 decoded and validated. Otherwise they will be generated. @param keysFilePath path to the keys file. @return std::tuple with a flag (true if keys were read, false if generated) and all the keys.
| 13 | /// @param keysFilePath path to the keys file. |
| 14 | /// @return std::tuple with a flag (true if keys were read, false if generated) and all the keys. |
| 15 | std::tuple<bool, FSecure::Crypto::SignatureKeys, FSecure::Crypto::SymmetricKey> ReadFromFileOrGenerateGatewayKeys(std::filesystem::path const& keysFilePath) |
| 16 | { |
| 17 | // Check if file exists. |
| 18 | if (std::filesystem::exists(keysFilePath)) |
| 19 | try |
| 20 | { |
| 21 | // Parse keys. |
| 22 | auto keys = json::parse(std::ifstream{ keysFilePath, std::ios::in }); |
| 23 | |
| 24 | // Helper lambda to read patch entries. TODO: rewrite as a template lambda when C++20 is out. |
| 25 | auto ParseEntry = [&keys](auto* typePtr, auto const& entryName) -> std::remove_pointer_t<decltype(typePtr)> |
| 26 | { |
| 27 | try |
| 28 | { |
| 29 | return cppcodec::base64_rfc4648::decode<FSecure::ByteVector>(keys[entryName].template get<std::string>()); |
| 30 | } |
| 31 | catch (std::exception& exception) |
| 32 | { |
| 33 | throw std::runtime_error{ OBF("Couldn't parse ") + std::string(entryName) + OBF(" element from patch. ") + exception.what() }; |
| 34 | } |
| 35 | catch (...) |
| 36 | { |
| 37 | throw std::runtime_error{ OBF("Caught an unknown exception while parsing ") + std::string(entryName) + OBF(" element from patch.") }; |
| 38 | } |
| 39 | }; |
| 40 | |
| 41 | // Parse and return keys. |
| 42 | return std::make_tuple(true, FSecure::Crypto::SignatureKeys{ ParseEntry((FSecure::Crypto::PrivateSignature*)nullptr, OBF("Private signature")), |
| 43 | ParseEntry((FSecure::Crypto::PublicSignature*)nullptr, OBF("Public signature")) }, ParseEntry((FSecure::Crypto::SymmetricKey*)nullptr, OBF("Broadcast key"))); |
| 44 | } |
| 45 | catch (const std::exception & exception) |
| 46 | { |
| 47 | throw std::runtime_error{ OBF_STR("Incorrect key file. ") + exception.what() }; |
| 48 | } |
| 49 | |
| 50 | // File doesn't exist. Generate all the keys. |
| 51 | auto singatures = FSecure::Crypto::GenerateSignatureKeys(); |
| 52 | auto broadcastKey = FSecure::Crypto::GenerateSymmetricKey(); |
| 53 | |
| 54 | // Create json tree. |
| 55 | auto keys = json{}; |
| 56 | keys[OBF("Private signature")] = cppcodec::base64_rfc4648::encode(singatures.first.ToByteVector().data(), FSecure::Crypto::PrivateSignature::Size); |
| 57 | keys[OBF("Public signature")] = cppcodec::base64_rfc4648::encode(singatures.second.ToByteVector().data(), FSecure::Crypto::PublicSignature::Size); |
| 58 | keys[OBF("Broadcast key")] = cppcodec::base64_rfc4648::encode(broadcastKey.ToByteVector().data(), FSecure::Crypto::SymmetricKey::Size); |
| 59 | |
| 60 | // Store them in provided file and return. |
| 61 | std::ofstream{ keysFilePath, std::ios::out | std::ios::trunc } << keys.dump(4); // dump(4) adds 4 space indentation to file. |
| 62 | |
| 63 | return std::make_tuple(false, singatures, broadcastKey); |
| 64 | } |
| 65 | |
| 66 | /// Obtains Gateway's configuration. |
| 67 | /// @param configurationFilePath path to the configuration file. |