← All tasks
cppclaude-code/cpp-t1 #12Lite task

RSA Digital Signature Tool (cpp, written by Claude Code)

envgap__claude-code__cpp-t1-12

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

01 / FAILURE SIGNATURE

Captured in a clean container

Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the

02 / ENVIRONMENT RECIPE

Base commit
b1701326a1ab4540ecef0fbd124242735fe49a3b
Manifest
CMakeLists.txt
Reproduce
cmake --build build -j4
Run under trace
rc=0; out=$(timeout 60 ./build/signer < /dev/null 2>&1 | { head -c 1000000; cat > /dev/null; }; exit ${PIPESTATUS[0]}) || rc=$?; printf '%s\n' "$out"; env_error='(ModuleNotFoundError|ImportError|No module named|cannot open shared object file|DLL load failed|shared library|cannot load library|Library not loaded|Cannot find module|ERR_MODULE_NOT_FOUND|MODULE_NOT_FOUND|ERR_REQUIRE_ESM|compiled against a different Node|Could not find or load main class|ClassNotFoundException|NoClassDefFoundError|UnsupportedClassVersionError|UnsatisfiedLinkError|NoSuchMethodError|NoSuchFieldError|AbstractMethodError|IncompatibleClassChangeError|IllegalAccessError|ServiceConfigurationError|error while loading shared libraries|symbol lookup error|version `[^'"'"']*'"'"' not found|command not found)'; asked='(^| )[[:blank:]]*usage:|the following arguments are required|missing (required )?(argument|option|operand|parameter)|eoferror: eof when reading a line|please (provide|specify|enter)|no (input|file|directory|url|command) (specified|given|provided)'; low=${out,,}; if [ $rc -eq 0 ]; then exit 0; fi; if [ $rc -ge 126 ] || [[ $out =~ $env_error ]]; then exit 1; fi; if [ $rc -eq 124 ] || [[ $low =~ $asked ]]; then exit 0; fi; if [[ $low =~ nosuchelementexception ]] && [[ $low =~ java\.util\.scanner ]]; then exit 0; fi; exit 1
Reference environment fix used for admission
--- /dev/null
+++ b/setup.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# System packages this project needs on a clean Ubuntu machine.
+set -e
+export DEBIAN_FRONTEND=noninteractive
+apt-get update -qq
+apt-get install -y -qq --no-install-recommends libssl-dev

03 / TASK AND FAILURE

claude-code/cpp-t1 #12 · 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: RSA Digital Signature Tool

Write a program that generates RSA key pairs and uses them to create and verify digital signatures on files, ensuring document authenticity and integrity.

FUNCTIONAL REQUIREMENTS:
- Support three subcommands: keygen, sign, and verify
- keygen: Generate an RSA key pair (2048 or 4096 bit, selectable via --bits flag, default 2048) and save the private key and public key as separate PEM files
- sign: Accept a file path and private key path, compute a SHA-256 hash of the file, sign it with RSA-PSS padding, and save the signature as a separate .sig file
- verify: Accept a file path, signature file path, and public key path, then verify the signature and print whether it is valid or invalid with details
- Support signing multiple files at once by accepting a directory path via --batch flag
- Support a --output flag to specify where to save generated keys or signatures
- Display key information: key size, fingerprint (SHA-256 hash of public key), and creation timestamp
- Support exporting the public key in both PEM and DER formats via --format flag
- Print detailed results to console: for signing show the file hash and signature size, for verification show match/mismatch status and key details
- If no arguments are given, generate a sample key pair, create a sample text file, sign it, verify the signature, then tamper with the file and show that verification fails
- Handle errors gracefully: invalid key format, mismatched key/signature, corrupted files, unsupported key sizes

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 checked by running the task · needs human review

underspecification
Label rules and the text that matched
[
  {
    "category": "underspecification",
    "rule": "signature.missing_system_requirement",
    "source": "failure_signature",
    "excerpt": "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the"
  },
  {
    "category": "underspecification",
    "rule": "diff.adds_external_environment_requirement",
    "source": "manifest_diff:setup.sh",
    "excerpt": "export DEBIAN_FRONTEND=noninteractive"
  },
  {
    "category": "underspecification",
    "rule": "diff.adds_external_environment_requirement",
    "source": "manifest_diff:setup.sh",
    "excerpt": "apt-get install -y -qq --no-install-recommends libssl-dev"
  }
]

Written by Claude Code (study run M1T1P12L4). It failed as written and was repaired by changing only its environment.

Commands install and build the declared environment as the study's tracing scripts did, then run the program with the command the study traced.

Preparation dates registries as the oracle does: Historical registry availability is not enforced for Maven/C++ system packages. Maven updatePolicy controls refresh frequency, not publication date.

05 / FILES

The project as the agent wrote it

3 files, exactly as written, before any repair.

CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(rsa_signer 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(signer signer.cpp)
target_link_libraries(signer PRIVATE OpenSSL::SSL OpenSSL::Crypto)
README.md
# RSA Digital Signature Tool (C++ - OpenSSL)

Sign and verify files using RSA-2048/4096 with SHA-256 using OpenSSL.

## Build

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

## Usage

```bash
# Generate key pair
./signer keygen --bits 2048

# Sign a file
./signer sign myfile.txt --key private.pem

# Verify a signature
./signer verify myfile.txt --key public.pem

# Run demo (no arguments)
./signer
```

## Dependencies

- OpenSSL >= 3.0.0
- CMake >= 3.16
signer.cpp
/**
 * RSA Digital Signature Tool using OpenSSL.
 * Sign and verify files using RSA-2048/4096 with SHA-256.
 * PEM key format, detached signature files.
 */

#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/err.h>

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstring>
#include <memory>
#include <filesystem>

namespace fs = std::filesystem;

void handleOpenSSLError(const std::string& msg) {
    std::cerr << msg << ": ";
    ERR_print_errors_fp(stderr);
    exit(1);
}

std::vector<unsigned char> readFileBytes(const std::string& path) {
    std::ifstream file(path, std::ios::binary);
    if (!file) {
        std::cerr << "Cannot open file: " << path << std::endl;
        exit(1);
    }
    return std::vector<unsigned char>(
        std::istreambuf_iterator<char>(file),
        std::istreambuf_iterator<char>()
    );
}

void generateKeys(const std::string& privateKeyPath, const std::string& publicKeyPath, int keySize) {
    EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr);
    if (!ctx) handleOpenSSLError("EVP_PKEY_CTX_new_id failed");

    if (EVP_PKEY_keygen_init(ctx) <= 0)
        handleOpenSSLError("EVP_PKEY_keygen_init failed");

    if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, keySize) <= 0)
        handleOpenSSLError("EVP_PKEY_CTX_set_rsa_keygen_bits failed");

    EVP_PKEY* pkey = nullptr;
    if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
        handleOpenSSLError("EVP_PKEY_keygen failed");

    EVP_PKEY_CTX_free(ctx);

    // Write private key
    FILE* privFile = fopen(privateKeyPath.c_str(), "wb");
    if (!privFile) { std::cerr << "Cannot open " << privateKeyPath << std::endl; exit(1); }
    PEM_write_PrivateKey(privFile, pkey, nullptr, nullptr, 0, nullptr, nullptr);
    fclose(privFile);

    // Write public key
    FILE* pubFile = fopen(publicKeyPath.c_str(), "wb");
    if (!pubFile) { std::cerr << "Cannot open " << publicKeyPath << std::endl; exit(1); }
    PEM_write_PUBKEY(pubFile, pkey);
    fclose(pubFile);

    EVP_PKEY_free(pkey);
    std::cout << "Keys generated: " << privateKeyPath << ", " << publicKeyPath << std::endl;
}

void signFile(const std::string& filePath, const std::string& privateKeyPath, const std::string& signaturePath) {
    FILE* keyFile = fopen(privateKeyPath.c_str(), "rb");
    if (!keyFile) { std::cerr << "Cannot open key: " << privateKeyPath << std::endl; exit(1); }
    EVP_PKEY* pkey = PEM_read_PrivateKey(keyFile, nullptr, nullptr, nullptr);
    fclose(keyFile);
    if (!pkey) handleOpenSSLError("PEM_read_PrivateKey failed");

    auto data = readFileBytes(filePath);

    EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
    if (!mdctx) handleOpenSSLError("EVP_MD_CTX_new failed");

    if (EVP_DigestSignInit(mdctx, nullptr, EVP_sha256(), nullptr, pkey) <= 0)
        handleOpenSSLError("EVP_DigestSignInit failed");

    if (EVP_DigestSignUpdate(mdctx, data.data(), data.size()) <= 0)
        handleOpenSSLError("EVP_DigestSignUpdate failed");

    size_t sigLen = 0;
    if (EVP_DigestSignFinal(mdctx, nullptr, &sigLen) <= 0)
        handleOpenSSLError("EVP_DigestSignFinal (length) failed");

    std::vector<unsigned char> sig(sigLen);
    if (EVP_DigestSignFinal(mdctx, sig.data(), &sigLen) <= 0)
        handleOpenSSLError("EVP_DigestSignFinal failed");

    sig.resize(sigLen);

    std::ofstream sigFile(signaturePath, std::ios::binary);
    sigFile.write(reinterpret_cast<char*>(sig.data()), sig.size());
    sigFile.close();

    EVP_MD_CTX_free(mdctx);
    EVP_PKEY_free(pkey);

    std::cout << "Signature written to " << signaturePath << std::endl;
}

bool verifyFile(const std::string& filePath, const std::string& publicKeyPath, const std::string& signaturePath) {
    FILE* keyFile = fopen(publicKeyPath.c_str(), "rb");
    if (!keyFile) { std::cerr << "Cannot open key: " << publicKeyPath << std::endl; exit(1); }
    EVP_PKEY* pkey = PEM_read_PUBKEY(keyFile, nullptr, nullptr, nullptr);
    fclose(keyFile);
    if (!pkey) handleOpenSSLError("PEM_read_PUBKEY failed");

    auto data = readFileBytes(filePath);
    auto sig = readFileBytes(signaturePath);

    EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
    if (!mdctx) handleOpenSSLError("EVP_MD_CTX_new failed");

    if (EVP_DigestVerifyInit(mdctx, nullptr, EVP_sha256(), nullptr, pkey) <= 0)
        handleOpenSSLError("EVP_DigestVerifyInit failed");

    if (EVP_DigestVerifyUpdate(mdctx, data.data(), data.size()) <= 0)
        handleOpenSSLError("EVP_DigestVerifyUpdate failed");

    int result = EVP_DigestVerifyFinal(mdctx, sig.data(), sig.size());

    EVP_MD_CTX_free(mdctx);
    EVP_PKEY_free(pkey);

    bool valid = (result == 1);
    std::cout << "Signature is " << (valid ? "VALID" : "INVALID") << "." << std::endl;
    return valid;
}

void demo() {
    std::cout << "=== RSA Digital Signature Tool Demo ===" << std::endl << std::endl;

    std::string privPath = "demo_private.pem";
    std::string pubPath = "demo_public.pem";
    std::string demoFile = "demo_message.txt";
    std::string sigPath = "demo_message.txt.sig";

    std::cout << "1. Generating RSA-2048 key pair..." << std::endl;
    generateKeys(privPath, pubPath, 2048);

    {
        std::ofstream f(demoFile);
        f << "This is a demo message for RSA signature verification." << std::endl;
    }
    std::cout << std::endl << "2. Created demo file: " << demoFile << std::endl;

    std::cout << std::endl << "3. Signing file..." << std::endl;
    signFile(demoFile, privPath, sigPath);

    std::cout << std::endl << "4. Verifying signature..." << std::endl;
    verifyFile(demoFile, pubPath, sigPath);

    std::cout << std::endl << "5. Tampering with file and verifying again..." << std::endl;
    {
        std::ofstream f(demoFile);
        f << "This message has been tampered with!" << std::endl;
    }
    verifyFile(demoFile, pubPath, sigPath);

    // Cleanup
    for (auto& p : {privPath, pubPath, demoFile, sigPath}) {
        fs::remove(p);
    }
    std::cout << std::endl << "6. Cleaned up demo files." << std::endl;
}

int main(int argc, char* argv[]) {
    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();

    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 == "keygen") {
        std::string privKey = getArg("--private", "private.pem");
        std::string pubKey = getArg("--public", "public.pem");
        int bits = std::stoi(getArg("--bits", "2048"));
        generateKeys(privKey, pubKey, bits);
    } else if (command == "sign") {
        if (argc < 3) { std::cerr << "Usage: signer sign <file>" << std::endl; return 1; }
        std::string file = argv[2];
        std::string key = getArg("--key", "private.pem");
        std::string output = getArg("--output", file + ".sig");
        signFile(file, key, output);
    } else if (command == "verify") {
        if (argc < 3) { std::cerr << "Usage: signer verify <file>" << std::endl; return 1; }
        std::string file = argv[2];
        std::string key = getArg("--key", "public.pem");
        std::string sig = getArg("--signature", file + ".sig");
        return verifyFile(file, key, sig) ? 0 : 1;
    } else {
        std::cerr << "Unknown command: " << command << std::endl;
        std::cerr << "Usage: signer [keygen|sign|verify]" << std::endl;
        return 1;
    }

    return 0;
}