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

AES-256 File Encryption Tool (cpp, written by Claude Code)

envgap__claude-code__cpp-t1-11

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
3b4bf3af634bd9cb2a774abc59f06f4cc2aeba30
Manifest
CMakeLists.txt
Reproduce
cmake --build build -j4
Run under trace
rc=0; out=$(timeout 60 ./build/encryptor < /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 #11 · 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: AES-256 File Encryption Tool

Write a program that encrypts and decrypts files using AES-256 encryption in CBC mode with proper key derivation, initialization vectors, and authenticated encryption to prevent tampering.

FUNCTIONAL REQUIREMENTS:
- Accept a file path, a password, and a mode (encrypt or decrypt) as command-line arguments
- Derive the encryption key from the password using PBKDF2 with SHA-256, a random 16-byte salt, and at least 100,000 iterations
- Encrypt using AES-256-CBC with a random 16-byte initialization vector (IV) for each encryption
- Prepend the salt and IV to the encrypted output file so they are available for decryption
- Add HMAC-SHA256 authentication tag to the encrypted file to detect tampering during decryption
- During decryption, verify the HMAC before attempting to decrypt and report a clear error if the file has been modified
- Support encrypting entire directories recursively via --recursive flag, preserving directory structure in the output
- Support a --output flag to specify the output file or directory (default: append .enc for encryption, strip .enc for decryption)
- Display progress information for large files: file size, percentage complete, and throughput
- If no input file is given, generate a sample text file with random content, encrypt it, then decrypt it back and verify the output matches the original
- Handle errors gracefully: wrong password (HMAC mismatch), corrupted file, file not found, permission denied

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 M1T1P11L4). 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(FileEncryptor VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Find OpenSSL
find_package(OpenSSL 3.0.0 REQUIRED)

add_executable(encryptor encryptor.cpp)
target_link_libraries(encryptor PRIVATE OpenSSL::Crypto)

# Install target
install(TARGETS encryptor DESTINATION bin)
encryptor.cpp
/**
 * AES-256 File Encryption Tool - Trial 1 (C++)
 * Uses OpenSSL (libcrypto) for AES-256-CBC encryption with PBKDF2 key derivation.
 */

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

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstring>
#include <cstdint>
#include <iomanip>
#include <sstream>
#include <algorithm>

// Constants
static const char MAGIC_HEADER[] = "ENC1";
static const int SALT_SIZE = 32;
static const int IV_SIZE = 16;
static const int KEY_SIZE = 32;  // AES-256
static const int PBKDF2_ITERATIONS = 600000;
static const int HMAC_SIZE = 32;

/**
 * Read entire file into a byte vector.
 */
std::vector<uint8_t> readFile(const std::string& path) {
    std::ifstream file(path, std::ios::binary | std::ios::ate);
    if (!file.is_open()) {
        throw std::runtime_error("Cannot open file: " + path);
    }
    auto size = file.tellg();
    file.seekg(0, std::ios::beg);
    std::vector<uint8_t> data(size);
    if (!file.read(reinterpret_cast<char*>(data.data()), size)) {
        throw std::runtime_error("Failed to read file: " + path);
    }
    return data;
}

/**
 * Write byte vector to file.
 */
void writeFile(const std::string& path, const std::vector<uint8_t>& data) {
    std::ofstream file(path, std::ios::binary);
    if (!file.is_open()) {
        throw std::runtime_error("Cannot open file for writing: " + path);
    }
    file.write(reinterpret_cast<const char*>(data.data()), data.size());
}

/**
 * Derive key using PBKDF2-HMAC-SHA256.
 */
std::vector<uint8_t> deriveKey(const std::string& password, const std::vector<uint8_t>& salt) {
    std::vector<uint8_t> key(KEY_SIZE);
    if (PKCS5_PBKDF2_HMAC(password.c_str(), static_cast<int>(password.size()),
                           salt.data(), static_cast<int>(salt.size()),
                           PBKDF2_ITERATIONS, EVP_sha256(),
                           KEY_SIZE, key.data()) != 1) {
        throw std::runtime_error("PBKDF2 key derivation failed");
    }
    return key;
}

/**
 * Compute HMAC-SHA256.
 */
std::vector<uint8_t> computeHmac(const std::vector<uint8_t>& key, const std::vector<uint8_t>& data) {
    unsigned int hmacLen = 0;
    std::vector<uint8_t> hmac(EVP_MAX_MD_SIZE);
    uint8_t* result = HMAC(EVP_sha256(), key.data(), static_cast<int>(key.size()),
                           data.data(), data.size(), hmac.data(), &hmacLen);
    if (!result) {
        throw std::runtime_error("HMAC computation failed");
    }
    hmac.resize(hmacLen);
    return hmac;
}

/**
 * Convert bytes to hex string.
 */
std::string toHex(const std::vector<uint8_t>& data, size_t maxLen = 0) {
    std::ostringstream ss;
    size_t len = maxLen > 0 ? std::min(maxLen, data.size()) : data.size();
    for (size_t i = 0; i < len; ++i) {
        ss << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(data[i]);
    }
    return ss.str();
}

/**
 * Write a 64-bit big-endian value.
 */
void writeBE64(std::vector<uint8_t>& out, uint64_t value) {
    for (int i = 7; i >= 0; --i) {
        out.push_back(static_cast<uint8_t>((value >> (i * 8)) & 0xFF));
    }
}

/**
 * Read a 64-bit big-endian value.
 */
uint64_t readBE64(const uint8_t* data) {
    uint64_t value = 0;
    for (int i = 0; i < 8; ++i) {
        value = (value << 8) | data[i];
    }
    return value;
}

/**
 * Constant-time comparison.
 */
bool secureCompare(const std::vector<uint8_t>& a, const std::vector<uint8_t>& b) {
    if (a.size() != b.size()) return false;
    return CRYPTO_memcmp(a.data(), b.data(), a.size()) == 0;
}

/**
 * Encrypt a file using AES-256-CBC.
 */
void encryptFile(const std::string& inputPath, const std::string& outputPath, const std::string& password) {
    // Read input
    auto plaintext = readFile(inputPath);

    // Generate random salt and IV
    std::vector<uint8_t> salt(SALT_SIZE);
    std::vector<uint8_t> iv(IV_SIZE);
    if (RAND_bytes(salt.data(), SALT_SIZE) != 1 || RAND_bytes(iv.data(), IV_SIZE) != 1) {
        throw std::runtime_error("Failed to generate random bytes");
    }

    // Derive key
    auto key = deriveKey(password, salt);

    // Encrypt with AES-256-CBC (EVP handles PKCS7 padding)
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    if (!ctx) throw std::runtime_error("Failed to create cipher context");

    if (EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, key.data(), iv.data()) != 1) {
        EVP_CIPHER_CTX_free(ctx);
        throw std::runtime_error("Encryption init failed");
    }

    std::vector<uint8_t> ciphertext(plaintext.size() + EVP_CIPHER_block_size(EVP_aes_256_cbc()));
    int outLen = 0, totalLen = 0;

    if (EVP_EncryptUpdate(ctx, ciphertext.data(), &outLen, plaintext.data(), static_cast<int>(plaintext.size())) != 1) {
        EVP_CIPHER_CTX_free(ctx);
        throw std::runtime_error("Encryption update failed");
    }
    totalLen = outLen;

    if (EVP_EncryptFinal_ex(ctx, ciphertext.data() + totalLen, &outLen) != 1) {
        EVP_CIPHER_CTX_free(ctx);
        throw std::runtime_error("Encryption finalize failed");
    }
    totalLen += outLen;
    ciphertext.resize(totalLen);
    EVP_CIPHER_CTX_free(ctx);

    // Compute HMAC over salt + iv + ciphertext
    std::vector<uint8_t> hmacData;
    hmacData.insert(hmacData.end(), salt.begin(), salt.end());
    hmacData.insert(hmacData.end(), iv.begin(), iv.end());
    hmacData.insert(hmacData.end(), ciphertext.begin(), ciphertext.end());
    auto hmac = computeHmac(key, hmacData);

    // Build output: MAGIC(4) + SALT(32) + IV(16) + CT_LEN(8) + CT(N) + HMAC(32)
    std::vector<uint8_t> output;
    output.insert(output.end(), MAGIC_HEADER, MAGIC_HEADER + 4);
    output.insert(output.end(), salt.begin(), salt.end());
    output.insert(output.end(), iv.begin(), iv.end());
    writeBE64(output, static_cast<uint64_t>(ciphertext.size()));
    output.insert(output.end(), ciphertext.begin(), ciphertext.end());
    output.insert(output.end(), hmac.begin(), hmac.end());

    writeFile(outputPath, output);

    std::cout << "Encrypted: " << inputPath << " -> " << outputPath << std::endl;
    std::cout << "  Salt: " << toHex(salt, 8) << "..." << std::endl;
    std::cout << "  IV:   " << toHex(iv, 8) << "..." << std::endl;
    std::cout << "  Size: " << plaintext.size() << " bytes -> " << ciphertext.size() << " bytes" << std::endl;
}

/**
 * Decrypt a file.
 */
bool decryptFile(const std::string& inputPath, const std::string& outputPath, const std::string& password) {
    auto data = readFile(inputPath);

    // Verify magic header
    if (data.size() < 4 || std::memcmp(data.data(), MAGIC_HEADER, 4) != 0) {
        std::cerr << "Error: Not a valid encrypted file (bad magic header)." << std::endl;
        return false;
    }

    size_t offset = 4;
    std::vector<uint8_t> salt(data.begin() + offset, data.begin() + offset + SALT_SIZE);
    offset += SALT_SIZE;
    std::vector<uint8_t> iv(data.begin() + offset, data.begin() + offset + IV_SIZE);
    offset += IV_SIZE;
    uint64_t ctLen = readBE64(data.data() + offset);
    offset += 8;
    std::vector<uint8_t> ciphertext(data.begin() + offset, data.begin() + offset + ctLen);
    offset += ctLen;
    std::vector<uint8_t> storedHmac(data.begin() + offset, data.begin() + offset + HMAC_SIZE);

    // Derive key
    auto key = deriveKey(password, salt);

    // Verify HMAC
    std::vector<uint8_t> hmacData;
    hmacData.insert(hmacData.end(), salt.begin(), salt.end());
    hmacData.insert(hmacData.end(), iv.begin(), iv.end());
    hmacData.insert(hmacData.end(), ciphertext.begin(), ciphertext.end());
    auto computedHmac = computeHmac(key, hmacData);

    if (!secureCompare(storedHmac, computedHmac)) {
        std::cerr << "Error: Integrity check failed. Wrong password or corrupted file." << std::endl;
        return false;
    }

    // Decrypt with AES-256-CBC
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    if (!ctx) throw std::runtime_error("Failed to create cipher context");

    if (EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, key.data(), iv.data()) != 1) {
        EVP_CIPHER_CTX_free(ctx);
        std::cerr << "Error: Decryption init failed." << std::endl;
        return false;
    }

    std::vector<uint8_t> plaintext(ciphertext.size() + EVP_CIPHER_block_size(EVP_aes_256_cbc()));
    int outLen = 0, totalLen = 0;

    if (EVP_DecryptUpdate(ctx, plaintext.data(), &outLen, ciphertext.data(), static_cast<int>(ciphertext.size())) != 1) {
        EVP_CIPHER_CTX_free(ctx);
        std::cerr << "Error: Decryption failed. Wrong password or corrupted file." << std::endl;
        return false;
    }
    totalLen = outLen;

    if (EVP_DecryptFinal_ex(ctx, plaintext.data() + totalLen, &outLen) != 1) {
        EVP_CIPHER_CTX_free(ctx);
        std::cerr << "Error: Decryption failed. Wrong password or corrupted file." << std::endl;
        return false;
    }
    totalLen += outLen;
    plaintext.resize(totalLen);
    EVP_CIPHER_CTX_free(ctx);

    writeFile(outputPath, plaintext);

    std::cout << "Decrypted: " << inputPath << " -> " << outputPath << std::endl;
    std::cout << "  Size: " << ciphertext.size() << " bytes -> " << plaintext.size() << " bytes" << std::endl;
    return true;
}

/**
 * Run demo with sample file.
 */
void runDemo() {
    const std::string sampleFile = "sample_input.txt";
    const std::string encryptedFile = "sample_encrypted.enc";
    const std::string decryptedFile = "sample_decrypted.txt";
    const std::string demoPassword = "demo_password_123";

    // Create sample file
    std::string sampleContent =
        "This is a sample file for AES-256-CBC encryption demo.\n"
        "It contains multiple lines of text.\n"
        "Line 3: The quick brown fox jumps over the lazy dog.\n"
        "Line 4: 0123456789 ABCDEF !@#$%^&*()\n";

    {
        std::ofstream f(sampleFile);
        f << sampleContent;
    }
    std::cout << "Created sample file: " << sampleFile << " (" << sampleContent.size() << " bytes)" << std::endl;

    // Encrypt
    std::cout << "\n--- Encrypting ---" << std::endl;
    encryptFile(sampleFile, encryptedFile, demoPassword);

    // Decrypt
    std::cout << "\n--- Decrypting ---" << std::endl;
    decryptFile(encryptedFile, decryptedFile, demoPassword);

    // Verify
    auto original = readFile(sampleFile);
    auto restored = readFile(decryptedFile);
    if (original == restored) {
        std::cout << "\nVerification: SUCCESS - Decrypted file matches original." << std::endl;
    } else {
        std::cout << "\nVerification: FAILED - Files do not match!" << std::endl;
    }

    // Test wrong password
    std::cout << "\n--- Testing wrong password ---" << std::endl;
    bool result = decryptFile(encryptedFile, "should_not_exist.txt", "wrong_password");
    if (!result) {
        std::cout << "(Wrong password correctly rejected)" << std::endl;
    }

    // Cleanup
    std::remove(sampleFile.c_str());
    std::remove(encryptedFile.c_str());
    std::remove(decryptedFile.c_str());
    std::remove("should_not_exist.txt");
    std::cout << "\nDemo complete. Temporary files cleaned up." << std::endl;
}

void printUsage() {
    std::cout << "Usage:" << std::endl;
    std::cout << "  encryptor encrypt <input> [-o output] [-p password]" << std::endl;
    std::cout << "  encryptor decrypt <input> [-o output] [-p password]" << std::endl;
    std::cout << "  encryptor demo" << std::endl;
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        std::cout << "No command specified. Running demo mode..." << std::endl;
        runDemo();
        return 0;
    }

    std::string command = argv[1];

    if (command == "demo") {
        runDemo();
        return 0;
    }

    if (command != "encrypt" && command != "decrypt") {
        printUsage();
        return 1;
    }

    if (argc < 3) {
        std::cerr << "Error: Input file required." << std::endl;
        printUsage();
        return 1;
    }

    std::string inputPath = argv[2];
    std::string outputPath;
    std::string password;

    // Parse flags
    for (int i = 3; i < argc; ++i) {
        std::string arg = argv[i];
        if (arg == "-o" && i + 1 < argc) {
            outputPath = argv[++i];
        } else if (arg == "-p" && i + 1 < argc) {
            password = argv[++i];
        }
    }

    if (password.empty()) {
        std::cout << "Enter password: ";
        std::getline(std::cin, password);
        if (command == "encrypt") {
            std::string confirm;
            std::cout << "Confirm password: ";
            std::getline(std::cin, confirm);
            if (password != confirm) {
                std::cerr << "Error: Passwords do not match." << std::endl;
                return 1;
            }
        }
    }

    try {
        if (command == "encrypt") {
            if (outputPath.empty()) outputPath = inputPath + ".enc";
            encryptFile(inputPath, outputPath, password);
        } else {
            if (outputPath.empty()) {
                if (inputPath.size() > 4 && inputPath.substr(inputPath.size() - 4) == ".enc") {
                    outputPath = inputPath.substr(0, inputPath.size() - 4);
                } else {
                    outputPath = inputPath + ".dec";
                }
            }
            if (!decryptFile(inputPath, outputPath, password)) {
                return 1;
            }
        }
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}
README.md
# AES-256 File Encryption Tool - C++ Trial 1

## Dependencies
- **OpenSSL** (>= 3.0.0): Provides AES-256-CBC via EVP interface, PBKDF2-HMAC-SHA256, and HMAC.
- **CMake** (>= 3.16) for build system.
- **C++17** compiler.

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

## Usage

### Encrypt a file
```bash
./encryptor encrypt <input_file> -o <output_file> -p <password>
```

### Decrypt a file
```bash
./encryptor decrypt <input_file> -o <output_file> -p <password>
```

### Demo mode
```bash
./encryptor demo
# or simply:
./encryptor
```

## Design
- **Algorithm**: AES-256-CBC with PKCS7 padding (via OpenSSL EVP)
- **Key Derivation**: PBKDF2-HMAC-SHA256 with 600,000 iterations
- **Integrity**: HMAC-SHA256 over salt + IV + ciphertext
- **File Format**: MAGIC(4) + SALT(32) + IV(16) + CT_LEN(8) + CT(N) + HMAC(32)