#include <iostream>
#include <random>
#include <bitset>
#include <ctime>
#include <cassert>
#include <cmath>
const int maxm = 10; //最大明文组数
using std::bitset;
using std::cout;
using std::endl;
using std::mt19937_64;
// des部分
class des
{
private:
bool Init = false; //初始化
bitset<64> key; //64位密钥
bitset<48> subKey[16]; // 16 个子密钥
// 初始 IP 置换
int IP[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};
// IP 逆置换
int IP_[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};
// E - 扩展规则
int E[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};
// 8 个 S - 盒
int S[8][4][16] = {
{{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
{0, 15, 7, 4, 15, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
{4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
{15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
{{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
{3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
{0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
{13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
{{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
{13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
{13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
{1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
{{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
{12, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
{10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
{3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
{{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
{14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
{4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
{11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
{{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
{10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
{9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
{4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
{{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
{13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
{1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
{6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
{{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
{1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
{7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
{2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}};
// P - 置换
int P[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};
// PC-1 置换
int PC1[56] = {57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4};
// PC-2 压缩置换
int PC2[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};
// 子密钥生成时,每轮左移位置数
int loop[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
// 左移操作
bitset<28> LS(bitset<28> A, int shift);
// 子密钥生成
void generateSubKey();
// 轮函数
bitset<32> f(bitset<32> R, bitset<48> K);
public:
void init(bitset<64> k); //初始化(就是使用加密密钥生成轮密钥)
bitset<64> encrypt(bitset<64> m);
bitset<64> decrypt(bitset<64> c);
};
bitset<28> des::LS(bitset<28> A, int shift)
{
bitset<28> output = A;
if (shift == 1)
{
for (int i = 0; i < 27; i++)
{
if (i - shift < 0)
output[i - shift + 28] = A[i];
else
output[i] = A[i + shift];
}
}
if (shift == 2)
{
for (int i = 0; i < 26; i++)
{
if (i - shift < 0)
output[i - shift + 28] = A[i];
else
output[i] = A[i + shift];
}
}
return output;
}
void des::generateSubKey()
{
bitset<56> reducedKey;
bitset<28> Ci;
bitset<28> Di;
bitset<48> Ki;
// (1) 对 K 的 56 个非校验位实行置换 PC-1,得到 C0D0,其中 C0 和 D0 分别由 PC-1 置换后的前 28 位和后 28 位组成。
for (int i = 0; i < 56; i++)
{
reducedKey[i] = key[PC1[i] - 1];
}
// (2) 计算 Ci = LSi (Ci-1) 和 Di = LSi (Di-1),即左移
// (3) 对 56 位的 CiDi 实行 PC-2 压缩置换,得到 48 位的 Ki。
// (4) 如果已经得到 K16,密钥调度过程结束。
for (int times = 0; times < 16; times++)
{
// 上下分开
for (int i = 0; i < 28; i++)
{
Ci[i] = reducedKey[i];
}
for (int i = 28; i < 56; i++)
{
Di[i - 28] = reducedKey[i];
}
Ci = LS(Ci, loop[times]);
Di = LS(Di, loop[times]);
// 上下合并
for (int i = 0; i < 56; i++)
{
if (i < 28)
{
reducedKey[i] = Ci[i];
}
else
{
reducedKey[i] = Di[i - 28];
}
}
// PC-2 置换,得到 48 位的 subKey
for (int i = 0; i < 48; i++)
{
Ki[i] = reducedKey[PC2[i] - 1];
}
// 添加到子密钥集合中
subKey[times] = Ki;
}
}
bitset<32> des::f(bitset<32> R, bitset<48> K)
{
bitset<48> Ei;
bitset<32> result;
// (1) 将长度为 32 位的 R 作 E - 扩展,成为 48 为的串
for (int i = 0; i < 48; i++)
{
Ei[i] = R[E[i] - 1];
}
// (2) 将 Ei 和长度为 48 位的子密钥 K 作 48 位二进制串按位异或运算。
for (int i = 0; i < 48; i++)
{
Ei[i] = Ei[i] ^ K[i];
}
// (3) 将 (2) 得到的结果平均分成 8 个分组(每个分组长度为 6),各个分组分别经过 8 个不同的 S - 盒进行 6-4 转换,得到 8 个长度分别为 4 位的分组。
int j = 0; //result 的下标
for (int i = 0; i < 48; i += 6)
{
//input: b1b2b3b4b5b6
//n = (b1b6) 行号
//m = (b2b3b4b5) 列号
int n = Ei[i] * 2 + Ei[i + 5];
int m = Ei[i + 1] * 8 + Ei[i + 2] * 4 + Ei[i + 3] * 2 + Ei[i + 4];
int value = S[i / 6][n][m];
// (4) 将 (3) 得到的分组结果顺序连接得到长度为 32 位的串
bitset<4> newValue(value); //int to binary
result[j] = newValue[3];
result[j + 1] = newValue[2];
result[j + 2] = newValue[1];
result[j + 3] = newValue[0];
j += 4;
}
bitset<32> output = result;
// (5) 将 (4) 的结果经过 P - 置换,得到的结果作为论函数 f 的最终 32 位输出。
for (int i = 0; i < 32; i++)
{
output[i] = result[P[i] - 1];
}
return output;
}
void des::init(bitset<64> k)
{
key = k;
generateSubKey();
Init = true;
}
bitset<64> des::encrypt(bitset<64> m)
{
bitset<64> M0;
bitset<32> Li;
bitset<32> Ri;
bitset<32> temp;
bitset<64> c;
assert(Init); //断言是否初始化
// 初始置换 IP
for (int i = 0; i < 64; i++)
{
M0[i] = m[IP[i] - 1];
}
for (int i = 0; i < 32; i++)
{
Li[i] = M0[i];
}
for (int i = 32; i < 64; i++)
{
Ri[i - 32] = M0[i];
}
// 16 轮迭代 T
for (int times = 0; times < 16; times++)
{
temp = Ri;
Ri = Li ^ f(Ri, subKey[times]);
Li = temp;
}
// 逆置换 IP^-1
for (int i = 0; i < 32; i++)
{
c[i] = Ri[i];
}
for (int i = 32; i < 64; i++)
{
c[i] = Li[i - 32];
}
M0 = c; // 使用中间变量存储 c
for (int i = 0; i < 64; i++)
{
c[i] = M0[IP_[i] - 1];
}
return c;
}
bitset<64> des::decrypt(bitset<64> c)
{
bitset<64> M0;
bitset<32> Li;
bitset<32> Ri;
bitset<32> temp;
bitset<64> m;
assert(Init); //断言是否初始化
// 初始置换 IP
for (int i = 0; i < 64; i++)
{
M0[i] = c[IP[i] - 1];
}
for (int i = 0; i < 32; i++)
{
Li[i] = M0[i];
}
for (int i = 32; i < 64; i++)
{
Ri[i - 32] = M0[i];
}
// 16 轮迭代 T (逆序)
for (int times = 15; times >= 0; times--)
{
temp = Ri;
Ri = Li ^ f(Ri, subKey[times]);
Li = temp;
}
// 逆置换 IP^-1
for (int i = 0; i < 32; i++)
{
m[i] = Ri[i];
}
for (int i = 32; i < 64; i++)
{
m[i] = Li[i - 32];
}
M0 = m;
for (int i = 0; i < 64; i++)
{
m[i] = M0[IP_[i] - 1];
}
return m;
}
int main()
{
bitset<64> m[maxm], c[maxm], d[maxm];
uint64_t seed = time(NULL);
mt19937_64 rnd(seed); //初始化PRNG
bitset<64> key = rnd();
cout << "1)随机密钥key:" << key << endl;
cout << "2)随机生成"<<maxm<<"个明文"<<endl;
for (int i = 0; i < maxm; i++)
{
m[i] = rnd();
cout << "随机明文m" << i+1 << ":" << m[i] << endl;
}
cout << "3)开始加密(des)" << endl;
des des1;
des1.init(key);
for (int i = 0; i < maxm; i++)
{
c[i] = des1.encrypt(m[i]);
cout << "加密得到c" << i+1 << ":" << c[i] << endl;
}
cout << "4)计算明密文距离:" << endl;
for (int i = 0; i < maxm; i++)
{
d[i] = m[i] ^ c[i];
cout << "明密文距离d" << i+1 << ":" << d[i] << endl;
}
cout << "5)计算di汉明重量" << endl;
for (int i = 0; i < maxm; i++)
{
cout << "汉明重量w" << i+1 << "汉明重量:" << d[i].count() << endl;
}
cout << "6)统计汉明重量分组vi"<<endl;
int wset[6]={0,28,30,32,34,64};
int v[5]={0};
for (int i = 0; i < maxm; i++)
{
int cnt=d[i].count();
if(cnt<=wset[1]) v[0]++;
else if(cnt<=wset[2]) v[1]++;
else if(cnt<=wset[3]) v[2]++;
else if(cnt<=wset[4]) v[3]++;
else v[4]++;
}
for(int i=0 ;i<5;i++){
cout << "分组v"<<i+1<<"从"<<((i==0)?wset[i]:wset[i]+1)<<"到"<<wset[i+1]<<":\t"<<v[i]<<endl;
}
double obs=0;
double pi[5]={0.190866,0.163124,0.292020,0.163124,0.190866};//pi_i的值
for(int i=0;i<5;i++){
obs+=pow((double)v[i]-maxm*pi[i],2)/(maxm*pi[i]);
}
cout <<"obs:"<<obs<<endl;
return 0;
}