Untitled
#include <iostream> #include <bitset> #include <vector> #include <stdexcept> #include <cstdint> // Статические таблицы, необходимые для DES static const int gInitialPermutation[64] = { 58,50,42,34,26,18,10,2, 60,52,44,36,28,20,12,4, 62,54,46,38,30,22,14,6, 64,56,48,40,32,24,16,8, 57,49,41,33,25,17,9,1, 59,51,43,35,27,19,11,3, 61,53,45,37,29,21,13,5, 63,55,47,39,31,23,15,7 }; static const int gFinalPermutation[64] = { 40,8,48,16,56,24,64,32, 39,7,47,15,55,23,63,31, 38,6,46,14,54,22,62,30, 37,5,45,13,53,21,61,29, 36,4,44,12,52,20,60,28, 35,3,43,11,51,19,59,27, 34,2,42,10,50,18,58,26, 33,1,41,9,49,17,57,25 }; static const int gPC1[56] = { 12,48,7,33,20,52,19,6, 41,2,25,15,34,9,45,31, 50,3,37,21,1,44,10,27, 11,42,54,18,30,5,46,36, 23,4,14,38,13,47,26,40, 22,39,53,29,8,24,32,55, 17,35,51,28,43,49,16,25 }; static const int gPC2[48] = { 14,17,11,24,1,5, 3,28,15,6,21,10, 23,19,12,4, 26,8,16,7,27,20, 13,2,41,52,31,37, 47,55,30,40, 51,45,33,48,44,49,39,56,34,53,46,42,50,36,29,32 }; static const int gExp[48] = { 32,1,2,3,4,5, 4,5,6,7,8,9, 8,9,10,11,12,13, 12,13,14,15,16,17, 16,17,18,19,20,21,20,21,22,23,24,25, 24,25,26,27,28,29, 28,29,30,31,32,1 }; // s-box (здесь S8 заполнена нулями, если нужно — впишите реальные значения) static const int gSBox[8][4][16] = { { // S1 {15,3,9,0,5,13,14,11,7,8,10,2,1,6,12,4}, {14,9,7,5,11,0,10,6,13,4,3,8,12,1,2,15}, {9,7,10,4,8,2,0,11,6,3,12,1,5,13,14,15}, {12,2,5,0,3,10,1,9,13,15,6,14,8,11,7,4} }, { // S2 {3,14,6,9,10,15,13,0,8,4,12,7,5,1,2,11}, {9,7,8,10,13,14,3,15,12,4,0,1,11,2,6,5}, {12,2,5,9,8,1,0,11,6,3,10,13,14,4,15,7}, {6,0,1,14,13,4,9,8,7,12,11,10,3,15,5,2} }, { // S3 {9,8,4,1,12,5,3,7,0,13,6,2,15,14,10,11}, {3,1,9,15,12,5,8,10,13,6,0,11,7,2,14,4}, {14,5,13,8,6,9,2,12,1,11,0,7,3,15,10,4}, {15,4,11,12,14,9,3,13,7,1,10,0,8,6,5,2} }, { // S4 {11,5,10,12,3,15,1,13,7,2,14,9,8,4,6,0}, {15,13,14,7,11,9,1,5,0,10,8,6,3,4,2,12}, {12,1,7,3,13,6,9,0,15,8,4,5,10,14,2,11}, {0,14,9,12,8,11,1,15,10,7,6,13,5,3,2,4} }, { // S5 {6,7,1,5,0,12,2,8,15,9,13,14,4,3,10,11}, {9,12,15,14,10,13,8,7,3,6,0,5,11,1,4,2}, {3,15,2,12,8,5,7,0,4,10,1,11,9,14,6,13}, {14,6,4,1,2,3,7,5,12,10,0,13,9,15,11,8} }, { // S6 {14,9,11,0,10,7,15,12,13,6,1,8,2,4,3,5}, {15,8,10,4,13,6,1,2,14,9,11,5,0,12,7,3}, {4,3,5,1,14,2,6,9,8,12,10,13,7,15,0,11}, {13,9,6,11,15,12,8,3,0,1,10,14,5,7,4,2} }, { // S7 {2,5,14,8,10,13,1,12,4,0,6,11,9,3,15,7}, {1,3,9,15,4,0,12,10,6,7,13,8,11,5,2,14}, {7,2,8,10,9,5,4,12,14,3,0,13,15,1,6,11}, {13,0,12,15,5,8,3,1,9,10,7,2,4,14,6,11} }, { // S8 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } }; static const int gRoundShifts[16] = { 1,1,2,2,2,2,1,1,2,2,2,2,1,1,2,2 }; // Генерация 48-битных ключей для каждого из 16 раундов std::vector<std::bitset<48>> makeSubkeys(const std::bitset<56> &mainKey) { std::vector<std::bitset<48>> subkeys(16); std::bitset<56> rearranged; for (int i = 0; i < 56; i++) { rearranged[i] = mainKey[gPC1[i] - 1]; } // Левая и правая половины (28 бит каждая) std::bitset<28> left = (rearranged.to_ullong() >> 28); std::bitset<28> right = (rearranged.to_ullong() & 0x0FFFFFFF); for (int round = 0; round < 16; round++) { auto lv = left.to_ullong(); auto rv = right.to_ullong(); lv = ((lv << gRoundShifts[round]) | (lv >> (28 - gRoundShifts[round]))); rv = ((rv << gRoundShifts[round]) | (rv >> (28 - gRoundShifts[round]))); left = std::bitset<28>(lv & 0x0FFFFFFF); right = std::bitset<28>(rv & 0x0FFFFFFF); std::bitset<56> combined = (left.to_ullong() << 28) | right.to_ullong(); for (int k = 0; k < 48; k++) { subkeys[round][k] = combined[gPC2[k] - 1]; } } return subkeys; } // Функция F (Feistel). Выполняет E-расширение, XOR с субключом, проход через s-box и P-перестановку std::bitset<32> fbox(const std::bitset<32> &rPart, const std::bitset<48> &subkey) { // Расширение E std::bitset<48> expanded; for (int i = 0; i < 48; i++) { expanded[i] = rPart[gExp[i] - 1]; } // XOR std::bitset<48> xored = expanded ^ subkey; // Применение s-box std::bitset<32> sOut(0); // Делим на блоки по 6 бит и преобразуем в 4 бита for (int i = 0; i < 8; i++) { std::bitset<6> current6 = (xored.to_ullong() >> (42 - 6*i)) & 0x3F; int row = ( (current6[5] << 1) | current6[0] ); int col = ( (current6.to_ullong() >> 1) & 0x0F ); int val = gSBox[i][row][col]; std::bitset<4> chunk4(val); // Сдвигаем в позицию (28 - i*4) auto maskPos = (28 - (i * 4)); sOut |= (std::bitset<32>(chunk4.to_ullong()) << maskPos); } // P-перестановка static const int pTab[32] = { 16,7,20,21,29,12,28,17,1,15,23,26,5,18,31,10, 2,8,24,14,32,27,3,9,19,13,30,6,22,11,4,25 }; std::bitset<32> result; for (int i = 0; i < 32; i++) { result[i] = sOut[pTab[i] - 1]; } return result; } // Основная функция DES: начальная перестановка, 16 раундов, финальная перестановка std::bitset<64> executeDES(const std::bitset<64> &inputBlock, const std::bitset<56> &theKey) { // Перестановка IP std::bitset<64> permInput(0); for (int i = 0; i < 64; i++) { permInput[i] = inputBlock[gInitialPermutation[i] - 1]; } // Разделяем на левую/правую половины по 32 бита std::bitset<32> lhs = (permInput.to_ullong() >> 32); std::bitset<32> rhs = (permInput.to_ullong() & 0xFFFFFFFF); // Получаем субключи auto subkeySet = makeSubkeys(theKey); // 16 раундов for (int round = 0; round < 16; round++) { std::bitset<32> tmp = rhs; rhs = lhs ^ fbox(rhs, subkeySet[round]); lhs = tmp; } // Склеиваем: R -> старшие 32 бита, L -> младшие 32 бита std::bitset<64> preFinal(0); for (int i = 0; i < 32; i++) { preFinal[i] = lhs[i]; preFinal[i + 32] = rhs[i]; } // Финальная перестановка (IP^-1) std::bitset<64> outputBlock(0); for (int i = 0; i < 64; i++) { outputBlock[i] = preFinal[gFinalPermutation[i] - 1]; } return outputBlock; } int main() { try { // Вместо чтения из файла — задаём данные и ключ "напрямую" // Data: 0x0123456789ABCDEF (64 bits) std::bitset<64> blockData(0x0123456789ABCDEFULL); // Key: 0x133457799BBCDF (56 bits) // При инициализации bitset<56> лишние старшие биты (если они есть) отсекаются std::bitset<56> secretKey(0x133457799BBCDFULL); std::cout << "Input block: 0x" << std::hex << blockData.to_ullong() << std::dec << "\n"; std::cout << "Key bits (56): 0x" << std::hex << secretKey.to_ullong() << std::dec << "\n"; // Выполняем DES auto encrypted = executeDES(blockData, secretKey); std::cout << "Encrypted block: 0x" << std::hex << encrypted.to_ullong() << std::dec << "\n"; } catch (const std::exception &ex) { std::cerr << "Произошла ошибка: " << ex.what() << std::endl; } return 0; }
Leave a Comment