# include # include # include # include # include # include # include # include # include # include # include namespace hpcstat::ssh { std::optional fingerprint() { if (auto datadir = env::env("HPCSTAT_DATADIR", true); !datadir) return std::nullopt; else if ( auto output = exec(std::filesystem::path(*datadir) / "ssh-add", { "-l" }); !output ) { std::cerr << "Failed to get ssh fingerprints\n"; return std::nullopt; } else { std::regex pattern(R"r(\b(?:sha|SHA)256:([0-9A-Za-z+/=]{43})\b)r"); std::smatch match; for ( auto i = std::sregex_iterator(output->begin(), output->end(), pattern); i != std::sregex_iterator(); ++i ) if (Keys.contains(i->str(1))) return i->str(1); std::cerr << fmt::format("No valid fingerprint found in:\n{}\n", *output); return std::nullopt; } } std::optional sign(std::string message, std::string fingerprint) { if (auto datadir = env::env("HPCSTAT_DATADIR", true); !datadir) return std::nullopt; else if ( auto output = exec ( std::filesystem::path(*datadir) / "ssh-keygen", { "-Y", "sign", "-q", "-f", fmt::format("{}/keys/{}", *datadir, Keys[fingerprint].PubkeyFilename), "-n", "hpcstat@chn.moe", "-" }, message ); !output ) { std::cerr << fmt::format("Failed to sign message: {}\n", message); return std::nullopt; } else return *output; } bool verify(std::string message, std::string signature, std::string fingerprint) { if (auto datadir = env::env("HPCSTAT_DATADIR", true); !datadir) return false; else { namespace bf = boost::filesystem; auto tempdir = bf::temp_directory_path() / bf::unique_path(); bf::create_directories(tempdir); auto signaturefile = tempdir / "signature"; std::ofstream(signaturefile) << signature; return exec ( std::filesystem::path(*datadir) / "ssh-keygen", { "-Y", "verify", "-f", fmt::format("{}/keys/{}", *datadir, Keys[fingerprint].PubkeyFilename), "-n", "hpcstat@chn.moe", "-s", signaturefile.string() }, message ).has_value(); } } }