Untitled

 avatar
unknown
plain_text
23 days ago
8.1 kB
4
Indexable
#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