diff --git a/inc/integretychecker.h b/inc/integretychecker.h index 080cd74..1a5b1ca 100644 --- a/inc/integretychecker.h +++ b/inc/integretychecker.h @@ -18,16 +18,21 @@ public: std::string generateHashList(const std::string &app); std::string generateFileHash(const std::string &filepath); + bool checkHashList(const std::string &hashList, const std::string &appPath); + bool verifyFileHash(const std::string &filePath, const std::string &hash); void signHashList(std::string &hashList); - bool verifyHashList(const std::string &signedHashList); + bool verifyHashList(const std::string &signedHashList, std::string &hashList); static const int KEY_SIZE; static const std::string HASH_FILE; static const std::string KEY_FILE; static const std::string SIGNATURE_MARKER; + static const std::string HASH_FILE_DIVIDER; private: CryptoPP::RSA::PublicKey m_publicKey; CryptoPP::RSA::PrivateKey m_privateKey; + bool extractHashAndFile(const std::string &line, std::string &hash, + std::string &filename); }; diff --git a/src/integretychecker.cpp b/src/integretychecker.cpp index f95e2ac..d008bd5 100644 --- a/src/integretychecker.cpp +++ b/src/integretychecker.cpp @@ -14,6 +14,7 @@ const int IntegretyCheck::KEY_SIZE = 2048; const std::string IntegretyCheck::HASH_FILE = "hashlist.sha256"; const std::string IntegretyCheck::KEY_FILE = "appKey.pub"; const std::string IntegretyCheck::SIGNATURE_MARKER = "### signature ###\n"; +const std::string IntegretyCheck::HASH_FILE_DIVIDER = " *"; std::string string_to_hex(const std::string &input) { static const char *const lut = "0123456789ABCDEF"; @@ -81,8 +82,8 @@ std::string IntegretyCheck::generateHashList(const std::string &app) { std::string filepath = f.path().string(); filepath.erase(0, p.size()); // write hash line to file - hashlist << generateFileHash(f.path().string()) << " *" << filepath - << std::endl; + hashlist << generateFileHash(f.path().string()) << HASH_FILE_DIVIDER + << filepath << std::endl; } } return hashlist.str(); @@ -102,6 +103,45 @@ std::string IntegretyCheck::generateFileHash(const std::string &filepath) { std::string((char *)abDigest, CryptoPP::SHA256::DIGESTSIZE)); } +bool IntegretyCheck::extractHashAndFile(const std::string &line, + std::string &hash, + std::string &filename) { + size_t divider = line.find(HASH_FILE_DIVIDER); + bool result = false; + if (divider != std::string::npos) { + hash = line.substr(0, divider); + filename = line.substr(divider + HASH_FILE_DIVIDER.size()); + result = true; + } else { + std::cerr << "ERROR: malformated hash line '" << line << "'" << std::endl; + } + return result; +} + +bool IntegretyCheck::checkHashList(const std::string &hashList, + const std::string &appPath) { + std::stringstream ss(hashList); + std::string line, hash, filename; + bool result = true; + fs::path p(appPath); + while (std::getline(ss, line, '\n')) { + if (extractHashAndFile(line, hash, filename)) { + bool check = verifyFileHash((p / filename).string(), hash); + result &= check; + if (!check) { + std::cerr << "ERROR: Checksum does not match on '" << filename << "'!" + << std::endl; + } + } + } + return result; +} + +bool IntegretyCheck::verifyFileHash(const std::string &filePath, + const std::string &hash) { + return (generateFileHash(filePath) == hash); +} + void IntegretyCheck::signHashList(std::string &hashList) { CryptoPP::AutoSeededRandomPool rng; @@ -125,14 +165,16 @@ void IntegretyCheck::signHashList(std::string &hashList) { hashList.append(strHexSignature); } -bool IntegretyCheck::verifyHashList(const std::string &signedHashList) { +bool IntegretyCheck::verifyHashList(const std::string &signedHashList, + std::string &hashList) { size_t startSig = signedHashList.find(SIGNATURE_MARKER); if (startSig == std::string::npos) { + std::cerr << "ERROR: no signature marker found!" << std::endl; return false; } // extract hash list - std::string hashList = signedHashList.substr(0, startSig); + hashList = signedHashList.substr(0, startSig); // extract base64 encoded signature std::string base64Signature =