#include <iostream>
#include <string>
#include <bitset>
using namespace std;
typedef bitset<4> word;
typedef bitset<1> byte;
typedef bitset<5> word5;
const int nr = 31;
static word S[16] = { 0x0c,0x05,0x06,0x0b,0x09,0x00,0x0a,
0x0d,0x03,0x0e,0x0f,0x08,0x04,0x07,0x01,0x02 };
static int P[64] = {
0,16,32,48,1,
17,33,49,2,18,
34,50,3,19,35,
51,4,20,36,
52,5,21,37,53
,6,22,38,54,
7,23,39,55,
8,24,40,56,
9,25,41,57,10,
26,42,58,11,27,43,59,
12,28,44,60,
13,29,45,61,
14,30,46,62,
15,31,47,63
};
void sBoxLayer(word state[4 * 4])
{
for (int i = 0; i < 16; i++)
{
int x = state[i][3] * 8 + state[i][2] * 4 + state[i][1] * 2 + state[i][0];
state[i] = S[x];
}
};
void PLayer(word in_state[16])
{
byte temp_1[64];
byte temp_2[64];
word temp;
for (int z = 0, h = 4; z < 16; z++)
{
for (int k = 0; k < 4; k++)
{
temp_1[z*h + k] = byte(in_state[z][3- k]);
}
in_state[z] = { 0 };
}
for (int i = 0; i < 64; i++)
{
temp_2[P[i]] = temp_1[i];
}
for (int s = 0, j = 4; s < 16; s++)
{
temp = temp_2[j*s ].to_ulong();
temp <<= 3;
in_state[s] |= temp;
temp = temp_2[j*s + 1].to_ulong();
temp<<= 2;
in_state[s] |= temp;
temp = temp_2[j*s + 2].to_ulong();
temp<<= 1;
in_state[s] |= temp;
temp=temp_2[j*s+3].to_ulong();
in_state[s] |= temp;
}
};
void generateroundkey(word key[20], word out_key[16], word5 round_counter)
{
for (int i = 0; i < 16; i++)
{
out_key[i] = key[i];
}
byte temp[80];
byte temp_3[80];
for (int i = 0, h = 4; i < 20; i++)
{
for (int j = 0; j < 4; j++)
{
temp_3[i*h + j] = byte(key[i][3 - j]);
}
key[i] = { 0 };
}
for (int s = 0; s < 19; s++)
temp[s] = temp_3[s + 61];
for (int s = 19; s < 80; s++)
temp[s] = temp_3[s - 19];
word temp_1;
word5 temp_2;
word skey = { 0 };
temp_1 = temp[0].to_ulong();
temp_1 <<= 3;
skey |= temp_1;
temp_1 = temp[1].to_ulong();
temp_1 <<= 2;
skey |= temp_1;
temp_1 = temp[2].to_ulong();
temp_1 <<= 1;
skey |= temp_1;
temp_1 = temp[3].to_ulong();
skey |= temp_1;
int x = skey[3] * 8 + skey[2] * 4 + skey[1] * 2 + skey[0];
skey = S[x];
word5 skey2 = { 0 };
temp_2 = temp[60].to_ulong();
temp_2 <<= 4;
skey2 |= temp_2;
temp_2 = temp[61].to_ulong();
temp_2 <<= 3;
skey2 |= temp_2;
temp_2 = temp[62].to_ulong();
temp_2 <<= 2;
skey2 |= temp_2;
temp_2 = temp[63].to_ulong();
temp_2 <<= 1;
skey2 |= temp_2;
temp_2 = temp[64].to_ulong();
skey2 |= temp_2;
skey2 = skey2 ^ round_counter;
for (int s = 0; s < 5; s++)
{
temp[60 + s] = byte(skey2[4 - s]);
}
key[0] = skey;
for (int i = 1, h = 4; i < 20; i++)
{
temp_1 = temp[i*h].to_ulong();
temp_1 <<= 3;
key[i] |= temp_1;
temp_1 = temp[i*h + 1].to_ulong();
temp_1 <<= 2;
key[i] |= temp_1;
temp_1 = temp[i*h + 2].to_ulong();
temp_1 <<= 1;
key[i] |= temp_1;
temp_1 = temp[i*h + 3].to_ulong();
key[i] |= temp_1;
}
};
void keyschedule(word key[16], word state[16])
{
for (int i = 0; i < 16; i++)
state[i] = state[i] ^ key[i];
}
int main()
{
word state1[16] =
{
0x0f,0x0f ,0x0f ,0x0f ,
0x0f,0x0f ,0x0f ,0x0f ,
0x0f,0x0f ,0x0f ,0x0f ,
0x0f,0x0f ,0x0f ,0x0f
};
word in_key[20] =
{
0x0f,0x0f ,0x0f ,0x0f ,
0x0f,0x0f ,0x0f ,0x0f ,
0x0f,0x0f ,0x0f ,0x0f ,
0x0f,0x0f ,0x0f ,0x0f ,
0x0f,0x0f ,0x0f ,0x0f
};
cout << "明文是:\n";
for (int i = 0; i < 16; i++)
{
cout << hex << state1[i].to_ulong() << " ";
}
cout << "\n初始密钥是:\n";
for (int j = 0; j < 20; j++)
{
cout << hex << in_key[j].to_ulong() << " ";
}
word out_key[32][16];
word key32[16];
word5 r_counter;
for (int k = 1; k <= nr; k++)
{
r_counter = word5(k);
generateroundkey(in_key, out_key[k], r_counter);
}
cout << "\n加密进行!\n\n";
for (int j = 1; j <= nr; j++)
{
keyschedule(out_key[j], state1);
sBoxLayer(state1);
PLayer(state1);
}
for (int i = 0; i < 16; i++)
{
key32[i] = in_key[i];
}
keyschedule(key32, state1);
cout << "加密后的密文:" << endl;
for (int i = 0; i < 16; ++i)
{
cout << hex << state1[i].to_ulong() << " ";
if ((i + 1) % 4 == 0)
cout << endl;
}
return 0;
}