#include #include #include #include #include #include class SecretManagement; class TextData { friend class SecretManagement; static constexpr char* GREET = "Greetings from Secret Management Corp!\n" "If you were not cleared to use this software by your superior officer, abort this " "session immediatly!\n\n" "1) provide authorization value (Hitchhiker series infamous number) inside the " "variable of exactly half the size of you CPU's register\n" "To procede use SecretManagement.auth(T arg) method where T is requested type. This method " "will return a " "pointer(unsigned char*) " "to the first byte of a 4-byte passcode\n\n"; static constexpr char* AUTH_SUCCESS = "2) First stage auth passed successfully, agent!\n" "Now you have obtained the pointer to the first byte of a 4-byte passcode\n" "To prove you attempt is legit provide pointer to five mantissa digits of the pi number\n" "They should be written one after another in memory and be of type unsigned char.\n" "Call SecretManagement.checkPiDigits(unsigned char *ptr). It will return pointer (unsigned " "char*) to the second byte of a 4-byte passcode\n\n"; static constexpr char* PI_SUCCESS = "3) OK, now this program will read a binary file that contains you personal secret code" "call checkFileCode(std::vector &secret_code, std::string &path_to_file) to check the " "file\n" "the above method returns the pointer to the first of the last TWO bytes of a 4-byte " "passcode\n\n"; static constexpr char* PERSONAL_CODE_SUCCESS = "4) Now you have all pointers to all bytes of a 4 byte passcode. You can get this number " "as unsigned int " "with\n" "method SecretManagement.get4byteNumber(unsigned char a, unsigned char b, unsigned char c, " "unsigned char d) which returns unsigned int.\n" "Double this 4-byte number and check it with method " "SecretManagement.checkFinalNumber(unsigned int " "final_number)\n" "If successful, this method will provide you with the 4-byte passcode for the nuclear " "triad control panel.\n\n"; static constexpr char* MISSION_COMPLETE = "Good job, 47! Mission accomplished!\n\n"; static constexpr char FINAL_SECRET[] = {0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x75, 0x72, 0x6c, 0x2e, 0x61, 0x74, 0x2f, 0x57, 0x67, 0x58, 0x38, 0x63, 0x00}; }; class SecretManagement { public: static constexpr size_t TOTAL_PASSCODE_NUMBER = 4; SecretManagement() { printf("%s\n", TextData::GREET); // random passcode generation std::random_device seed; std::mt19937 gen{seed()}; std::uniform_int_distribution<> distrib{1, 254}; data_.resize(TOTAL_PASSCODE_NUMBER); for (size_t i = 0; i < TOTAL_PASSCODE_NUMBER; ++i) { data_[i] = static_cast(distrib(gen)); } data_.back() += 1 - data_.back() % 2; } ~SecretManagement() { for (uint8_t* ptr : returned_data_) { delete ptr; } } template uint8_t* auth(const T number) { const int register_size = sizeof(void*); printf("Auth attempt on %d-bit system\n", register_size * 8); if (sizeof(number) != register_size / 2) { printf("wrong size!\n"); panicCorruptData(); return nullptr; } if (number + 2 != ((0x3C & 0x2E) | (0x01 << 5) ^ 0x08)) { printf("wrong auth number!\n"); panicCorruptData(); return nullptr; } returned_data_.push_back(new uint8_t{data_[0]}); printf("%s\n", TextData::AUTH_SUCCESS); return returned_data_.back(); } uint8_t* checkPiDigits(unsigned char* ptr) { int number = 0; for (size_t i = 0; i < 5; ++i) { number = number * 10 + static_cast(*(ptr + i)); } if (number + (1 << 11) + 503 != (((0x700 ^ 0x187) | (0x20 << 4)) & ~(0x10)) * 10) { printf("wrong pi digits!\n"); panicCorruptData(); return nullptr; } returned_data_.push_back(new uint8_t{data_[1]}); printf("%s\n", TextData::PI_SUCCESS); return returned_data_.back(); } uint8_t* checkFileCode(const std::vector& secret_code, const std::string& path_to_file) { if (secret_code.empty()) { printf("empty code\n"); panicCorruptData(); return nullptr; } std::ifstream input_file(path_to_file, std::ios::in | std::ios::binary); for (size_t i = 0; i < secret_code.size(); i++) { int read_num = 0; input_file.read((char*)&read_num, sizeof(read_num)); if (read_num != secret_code[i]) { input_file.close(); printf("wrong file content\n"); panicCorruptData(); return nullptr; } } input_file.close(); // not an optimal allocation, because of determined delete operator (instead of delete[]) in // destructor // subject to fix uint8_t* numbers_to_return = new uint8_t[2]; numbers_to_return[0] = data_[2]; numbers_to_return[1] = data_[3]; returned_data_.push_back(numbers_to_return); printf("%s\n", TextData::PERSONAL_CODE_SUCCESS); return returned_data_.back(); } static uint32_t get4byteNumber( const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d) { uint32_t res = ((uint32_t)a << 24) + ((uint32_t)b << 16) + ((uint32_t)c << 8) + (uint32_t)d; return res; } void checkFinalNumber(const uint32_t final_number) { bool valid_order_verdict = (*returned_data_[0] == data_[0] && *returned_data_[1] == data_[1] && *returned_data_[2] == data_[2] && *(returned_data_[2] + 1) == data_[3]); if (!valid_order_verdict) { printf("wrong task order\n"); panicCorruptData(); return; } if (final_number % 2 != 0) { printf("did you double the number?)\n"); panicCorruptData(); return; } uint32_t half_number = final_number / 2; uint8_t a = (uint8_t)(final_number & 0x000000FF); uint8_t b = (uint8_t)((final_number & 0x0000FF00) >> 8); uint8_t c = (uint8_t)((final_number & 0x00FF0000) >> 16); uint8_t d = (uint8_t)(final_number >> 24); bool number_verdict = (a == data_[0] && b == data_[1] && c == data_[2] && d == data_[3]); if (!valid_order_verdict) { printf("wrong final number bytes\n"); panicCorruptData(); return; } printf("%s\n", TextData::MISSION_COMPLETE); printf("%s\n", TextData::FINAL_SECRET); } private: void panicCorruptData() { printf( "Security breach, special forces have been dispatched to the location, standby\n" "Initializing data corruption. Protocol 'Enemy's Lair' is active\n"); data_.clear(); for (uint8_t* ptr : returned_data_) { delete ptr; } } std::vector data_; std::vector returned_data_; }; // compile with cmd: g++ -Wno-write-strings secret_management.cpp -o secret_management && ./secret_management int main() { SecretManagement manager; /* ( , , ) uint8_t* auth(const T number) uint8_t* checkPiDigits(unsigned char* ptr) uint8_t* checkFileCode(const std::vector& secret_code, const std::string& path_to_file) uint32_t get4byteNumber(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d) void checkFinalNumber(const uint32_t final_number) */ // example: // uint8_t *a = manager.auth(???); }