Untitled
unknown
plain_text
9 months ago
8.1 kB
6
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;
}
Editor is loading...
Leave a Comment