← All tasks
cppclaude-code/cpp-t1 #13Not a task: not reproduced

HMAC File Integrity Checker (cpp, written by Claude Code)

envgap__claude-code__cpp-t1-13

Written by a coding agent; not on GitHubWritten 2026-02-27

01 / FAILURE SIGNATURE

As the study recorded it

Could NOT find OpenSSL - libssl-dev not in Docker image
Not a benchmark task.
  • In a clean container the reported failure did not reproduce, or the known fix did not make the project run.

02 / ENVIRONMENT RECIPE

Base commit
Not freshly verified
Manifest
CMakeLists.txt
Reproduce
Awaiting issue-specific recipe
Run under trace
Awaiting a meaningful runtime command

03 / TASK AND FAILURE

claude-code/cpp-t1 #13 · read the task the agent was given
Claude Code wrote this cpp project from the task below. It does not run on a clean Ubuntu 22.04 machine as written.

Task given to the agent:

TASK: HMAC File Integrity Checker

Write a program that computes and verifies HMAC-based integrity checksums for files and directories, creating a manifest of checksums that can later be used to detect unauthorized modifications.

FUNCTIONAL REQUIREMENTS:
- Accept a file or directory path, a secret key, and a mode (generate or verify) as command-line arguments
- Support multiple hash algorithms selectable via --algorithm flag: SHA-256 (default), SHA-384, SHA-512, SHA3-256
- generate mode: Compute HMAC for each file and save a manifest file containing file paths, HMAC values, file sizes, and timestamps
- verify mode: Read the manifest, recompute HMACs, and report which files are unchanged, modified, added (present but not in manifest), or missing (in manifest but deleted)
- For directories, recursively process all files and support --exclude flag with glob patterns to skip files (e.g., --exclude "*.log,*.tmp")
- Support a --output flag for the manifest file path (default: integrity_manifest.json)
- Print a colored summary to console showing verification results: passed files in green, modified in red, missing in yellow, new files in blue
- Compute a master HMAC over the entire manifest to detect tampering of the manifest file itself
- Support incremental updates: when generating with an existing manifest, only recompute HMACs for files whose modification time has changed via --incremental flag
- If no arguments are given, generate sample files in a temporary directory, create an integrity manifest, modify one file, delete another, add a new file, then run verification to demonstrate all detection capabilities
- Handle binary and text files correctly, permission errors gracefully

Create a complete C++ project for a clean Ubuntu 22.04 machine with only G++ 12+ and CMake 3.22+ installed. Include:
- Source code
- CMakeLists.txt with all dependencies (direct and transitive) pinned to exact versions
- README.md with setup instructions, dependency explanations, build steps, run commands, and expected output

04 / LABELS

Labels from the report text only; not yet run

No supported category has been assigned.

Label rules and the text that matched
[]

05 / FILES

The project as the agent wrote it

3 files, exactly as written, before any repair.

checker.cpp
/**
 * HMAC File Integrity Checker using OpenSSL HMAC.
 * Compute and verify HMAC-SHA256 checksums for files/directories.
 */

#include <openssl/hmac.h>
#include <openssl/evp.h>

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <filesystem>
#include <iomanip>
#include <cstring>

namespace fs = std::filesystem;

std::string computeHmac(const std::string& filePath, const std::string& key) {
    std::ifstream file(filePath, std::ios::binary);
    if (!file) {
        std::cerr << "Cannot open file: " << filePath << std::endl;
        exit(1);
    }

    unsigned char result[EVP_MAX_MD_SIZE];
    unsigned int resultLen = 0;

    HMAC_CTX* ctx = HMAC_CTX_new();
    HMAC_Init_ex(ctx, key.c_str(), key.size(), EVP_sha256(), nullptr);

    char buffer[8192];
    while (file.read(buffer, sizeof(buffer)) || file.gcount() > 0) {
        HMAC_Update(ctx, reinterpret_cast<unsigned char*>(buffer), file.gcount());
    }

    HMAC_Final(ctx, result, &resultLen);
    HMAC_CTX_free(ctx);

    std::ostringstream oss;
    for (unsigned int i = 0; i < resultLen; i++) {
        oss << std::hex << std::setw(2) << std::setfill('0') << (int)result[i];
    }
    return oss.str();
}

std::vector<std::string> scanFiles(const std::string& target) {
    std::vector<std::string> files;
    if (fs::is_regular_file(target)) {
        files.push_back(target);
    } else if (fs::is_directory(target)) {
        for (const auto& entry : fs::recursive_directory_iterator(target)) {
            if (entry.is_regular_file()) {
                std::string p = entry.path().string();
                std::replace(p.begin(), p.end(), '\\', '/');
                files.push_back(p);
            }
        }
        std::sort(files.begin(), files.end());
    } else {
        std::cerr << "Error: " << target << " is not a file or directory." << std::endl;
        exit(1);
    }
    return files;
}

void computeManifest(const std::string& target, const std::string& key, const std::string& manifestPath) {
    auto files = scanFiles(target);
    std::ofstream manifest(manifestPath);

    int count = 0;
    for (const auto& filePath : files) {
        std::string relPath = fs::relative(filePath).string();
        std::replace(relPath.begin(), relPath.end(), '\\', '/');
        std::string hmacVal = computeHmac(filePath, key);
        manifest << hmacVal << "  " << relPath << "\n";
        std::cout << "  " << hmacVal << "  " << relPath << std::endl;
        count++;
    }

    manifest.close();
    std::cout << "\nManifest written to " << manifestPath << " (" << count << " files)" << std::endl;
}

bool verifyManifest(const std::string& manifestPath, const std::string& key) {
    std::ifstream manifest(manifestPath);
    if (!manifest) {
        std::cerr << "Cannot open manifest: " << manifestPath << std::endl;
        exit(1);
    }

    int passed = 0, failed = 0, missing = 0;
    std::string line;

    while (std::getline(manifest, line)) {
        if (line.empty()) continue;
        size_t sep = line.find("  ");
        if (sep == std::string::npos) continue;

        std::string expectedHmac = line.substr(0, sep);
        std::string filePath = line.substr(sep + 2);

        if (!fs::exists(filePath)) {
            std::cout << "  MISSING  " << filePath << std::endl;
            missing++;
            continue;
        }

        std::string actualHmac = computeHmac(filePath, key);
        if (actualHmac == expectedHmac) {
            std::cout << "  OK       " << filePath << std::endl;
            passed++;
        } else {
            std::cout << "  FAILED   " << filePath << std::endl;
            failed++;
        }
    }

    std::cout << "\nResults: " << passed << " OK, " << failed << " FAILED, " << missing << " MISSING" << std::endl;
    return failed == 0 && missing == 0;
}

void demo() {
    std::cout << "=== HMAC File Integrity Checker Demo ===" << std::endl << std::endl;

    std::string demoDir = "demo_files";
    std::string manifestPath = "demo_manifest.txt";
    std::string secretKey = "my-secret-key-for-demo";

    fs::create_directories(demoDir);
    for (int i = 1; i <= 3; i++) {
        std::ofstream f(demoDir + "/file" + std::to_string(i) + ".txt");
        f << "This is sample file " << i << " for HMAC integrity checking." << std::endl;
    }
    std::cout << "1. Created sample files in " << demoDir << "/" << std::endl << std::endl;

    std::cout << "2. Computing HMAC-SHA256 manifest..." << std::endl;
    computeManifest(demoDir, secretKey, manifestPath);

    std::cout << std::endl << "3. Verifying manifest..." << std::endl;
    verifyManifest(manifestPath, secretKey);

    std::cout << std::endl << "4. Tampering with a file..." << std::endl;
    {
        std::ofstream f(demoDir + "/file2.txt");
        f << "This file has been tampered with!" << std::endl;
    }
    verifyManifest(manifestPath, secretKey);

    fs::remove_all(demoDir);
    fs::remove(manifestPath);
    std::cout << std::endl << "5. Cleaned up demo files." << std::endl;
}

int main(int argc, char* argv[]) {
    if (argc < 2) { demo(); return 0; }

    std::string command = argv[1];
    auto getArg = [&](const std::string& flag, const std::string& def) -> std::string {
        for (int i = 2; i < argc - 1; i++) {
            if (std::string(argv[i]) == flag) return argv[i + 1];
        }
        return def;
    };

    if (command == "compute") {
        if (argc < 3) { std::cerr << "Usage: checker compute <target> --key <key>" << std::endl; return 1; }
        std::string target = argv[2];
        std::string key = getArg("--key", "");
        if (key.empty()) { std::cerr << "--key is required" << std::endl; return 1; }
        computeManifest(target, key, getArg("--manifest", "manifest.txt"));
    } else if (command == "verify") {
        std::string key = getArg("--key", "");
        if (key.empty()) { std::cerr << "--key is required" << std::endl; return 1; }
        return verifyManifest(getArg("--manifest", "manifest.txt"), key) ? 0 : 1;
    } else {
        std::cerr << "Unknown command: " << command << std::endl;
        return 1;
    }
    return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(hmac_checker VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(OpenSSL 3.0.0 REQUIRED)

add_executable(checker checker.cpp)
target_link_libraries(checker PRIVATE OpenSSL::SSL OpenSSL::Crypto)
README.md
# HMAC File Integrity Checker (C++ - OpenSSL)

Compute and verify HMAC-SHA256 checksums using OpenSSL.

## Build

```bash
mkdir build && cd build
cmake ..
cmake --build .
```

## Usage

```bash
./checker compute ./mydir --key mysecret
./checker verify --manifest manifest.txt --key mysecret
./checker   # Run demo
```

## Dependencies

- OpenSSL >= 3.0.0
- CMake >= 3.16