
#include<bits/stdc++.h>
using namespace std;
//int key[3][3];
int key[3][3] = {
17,17,5,
21,18,21,
2,2,19
}; //加密密钥
int mod26(int x) //取模
{
return x >= 0 ? (x % 26) : 26 - (abs(x) % 26);
}
/* 求矩阵的|A| */
int findDet(int m[3][3], int n)
{
int det;
if (n == 2) //2阶矩阵
{
det = m[0][0] * m[1][1] - m[0][1] * m[1][0];
}
else if (n == 3) //3阶矩阵
{
det = m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1])
- m[0][1] * (m[1][0] * m[2][2] - m[2][0] * m[1][2])
+ m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
}
else det = 0; // 无效输入
return mod26(det);
}
int findDetInverse(int R, int D = 26) // R=|A|
{
int i = 0;
int p[100] = { 0,1 };
int q[100] = { 0 }; //商
while (R != 0)
{
q[i] = D / R;
int oldD = D;
D = R;
R = oldD % R;
if (i > 1)
{
p[i] = mod26(p[i - 2] - p[i - 1] * q[i - 2]);
}
i++;
}
if (i == 1)
return 1;
else
return p[i] = mod26(p[i - 2] - p[i - 1] * q[i - 2]);
}
//矩阵乘法
void multiplyMatrices(int a[1000][3], int a_rows, int a_cols, int b[1000][3], int b_rows, int b_cols, int res[1000][3])
{
for (int i = 0; i < a_rows; i++)
{
for (int j = 0; j < b_cols; j++)
{
for (int k = 0; k < b_rows; k++)
{
res[i][j] += a[i][k] * b[k][j];
}
res[i][j] = mod26(res[i][j]);
}
}
}
/* findInverse(输入矩阵 , 阶数 , 输出矩阵) */
//矩阵的逆
void findInverse(int m[3][3], int n, int m_inverse[3][3])
{
int adj[3][3] = { 0 };
int det = findDet(m, n); // key矩阵的行列式
int detInverse = findDetInverse(det);
if (n == 2) //二阶矩阵的逆
{
adj[0][0] = m[1][1];
adj[1][1] = m[0][0];
adj[0][1] = -m[0][1];
adj[1][0] = -m[1][0];
}
else if (n == 3) //三阶矩阵的逆
{
int temp[5][5] = { 0 };
//填充 5x5 矩阵
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
temp[i][j] = m[i % 3][j % 3];
}
}
/* 除第一行和第一列外,沿行乘元素,并沿列放置元素*/
for (int i = 1; i <= 3; i++)
{
for (int j = 1; j <= 3; j++)
{
adj[j - 1][i - 1] = temp[i][j] * temp[i + 1][j + 1] - temp[i][j + 1] * temp[i + 1][j];
}
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
m_inverse[i][j] = mod26(adj[i][j] * detInverse);
/* Inverse = (matrix * detInverse) mod 26 */
}
}
}
// C = PK
string encrypt(string pt, int n)
{
int P[1000][3] = { 0 }; // 明文 , 3列矩阵
int C[1000][3] = { 0 }; // 密文
int ptIter = 0;
while (pt.length() % n != 0)
{
pt += "x"; // 用x填补
}
int row = (pt.length()) / n; // P的行数=字母个数/3(n)
for (int i = 0; i < row; i++)
{
for (int j = 0; j < n; j++)
{
P[i][j] = pt[ptIter++] - 'a'; //明文矩阵
}
}
// multiplyMatrices(输入矩阵 , 行数 , 列数 , 密钥, 密钥行数, 密钥列数 , 结果矩阵)
//矩阵乘法
multiplyMatrices(P, row, n, key, n, n, C); // C = PK
string ct = ""; //密文
for (int i = 0; i < row; i++)
{
for (int j = 0; j < n; j++)
{
ct += (C[i][j] + 'a');
}
}
return ct;
}
// P = C*(k_inverse)
string decrypt(string ct, int n)
{
int P[1000][3] = { 0 }; // 明文矩阵
int C[1000][3] = { 0 }; // 密文矩阵
int ctIter = 0;
int row = ct.length() / n; // 密文的行数
for (int i = 0; i < row; i++)
{
for (int j = 0; j < n; j++)
{
C[i][j] = ct[ctIter++] - 'a';
}
}
int k_inverse[3][3] = { 0 }; //密文的逆矩阵
findInverse(key, n, k_inverse);
// P = C*(k_inverse)
multiplyMatrices(C, row, n, k_inverse, n, n, P);
string pt = "";
for (int i = 0; i < row; i++)
{
for (int j = 0; j < n; j++)
{
pt += (P[i][j] + 'a');
}
}
return pt;
}
int main(void)
{
string pt="rlx";
/*cout << "请输入要加密的明文: ";
cin >> pt;*/
/*cout << "请输入加密矩阵的阶数: ";
cin >> n;
cout << "请输入加密矩阵(必须可逆): " << endl;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> key[i][j];
}
}*/
cout << "\n明文 : " << pt << endl;
string ct = encrypt(pt, 3);
cout << "密文 : " << ct << endl;
string dt = decrypt(ct, 3);
cout << "解密t : " << dt << endl;
}