古典密碼(凱撒密碼/維吉尼亞密碼/Play fair密碼/Hill密碼)的實現(MFC介面)
阿新 • • 發佈:2018-12-30
void CEn_DeDlg::random_Matrix()
{
int i, j;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
K[i][j] = rand() % 26; //產生一個5*5模26的矩陣
}
}
}
//求矩陣的行列式
int CEn_DeDlg::Det(int matrix[5][5], int row)
{
int i, j;
int cofa[5][5]; //用於存放餘子陣
int l; //l為所遞迴的餘子陣的行
int p = 0, q = 0;
int sum = 0;
//由於行和列相同(方陣),所以行列式的值一定存在,故不需要判斷是否為方陣
//遞迴基
if (row == 1)
return matrix[0][0];
for (i = 0; i < row; i++)
{
for (l = 0; l < row - 1; l++)
{
if (l < i)
p = 0;
else
p = 1;
for (j = 0; j< row - 1; j++)
{
cofa[l][j] = matrix[l + p][j + 1];
}
}
//相當於(-1)^i
if (i % 2 == 0)
q = 1;
else
q = (-1);
sum = sum + matrix[i][0] * q * Det(cofa, row - 1 );
}
return sum;
}
//求兩個數的最大公約數
int CEn_DeDlg::gcd(int a, int b)
{
int temp;
//交換兩個數的大小,使得a為較大數
if (a < b)
{
temp = a;
a = b;
b = temp;
}
while (a % b)
{
temp = b;
b = a % b;
a = temp;
}
return b;
}
/*
*判斷矩陣K是否在模26的情況下可逆
*因為矩陣在模26的情形下存在可逆矩陣的充分必要條件是
*gcd(det K,26) = 1
*/
bool CEn_DeDlg::Inverse(int matrix[5][5])
{
if (gcd(Det(matrix, ROW), M) == 1)
return true;
else
return false;
}
void CEn_DeDlg::multiphy(int matrix[5][5], int p[5], int row)
{
int i, j;
//先將密文單元清零
memset(C, 0, sizeof(C));
for (i = 0; i < ROW; i++)
{
for (j = 0; j < ROW; j++)
{
C[i] += P[j] * K[j][i];
}
}
}
//將明文加密為密文
CString CEn_DeDlg::encryption(CString plaintext)
{
int i;
CString ciphertext;
//將字串轉化為明文陣列
for (i = 0; i < ROW; i++)
{
P[i] = plaintext[i] - 'a';
}
multiphy(K, P, ROW);
//將密文陣列轉化為密文
for (i = 0; i < ROW; i++)
//這裡先將其模26,再翻譯為對應的字母
{
C[i] = Mod(C[i]);
ciphertext.AppendChar(C[i] + 'A');
}
return ciphertext;
}
//求出伴隨矩陣
void CEn_DeDlg::adjoint_matrix(int matrix[5][5], int row)
{
int i, j, k, l;
int p, q;
p = q = 0;
int temp[5][5];
for (i = 0; i < ROW; i++)
{
for (j = 0; j < ROW; j++)
{
for (k = 0; k < ROW - 1; k++)
{
if (k < i)
p = 0;
else
p = 1;
for (l = 0; l < ROW - 1; l++)
{
if (l < j)
q = 0;
else
q = 1;
temp[k][l] = matrix[k + p][l + q];
}
}
D[j][i] = (int)pow(-1, (double)i + j)*Det(temp, ROW - 1);
D[j][i] = Mod(D[j][i]);
}
}
}
//將密文解密為明文(為了辨識清楚,我們統一以小寫字母作為明文,大寫字母作為密文)
CString CEn_DeDlg::deciphering(CString ciphertext)
{
//求出矩陣的逆
CString text;
int determinant = Det(K, ROW);
int inver = inverse(determinant, 26);
adjoint_matrix(K, ROW); //伴隨矩陣
//cout << "行列式的值: " << determinant << endl;
int i, j;
memset(F, 0, sizeof(F));
for (i = 0; i < ROW; i++)
{
for (j = 0; j < ROW; j++)
{
F[i] += C[j] * D[j][i];
}
F[i] *= inver;
F[i] = Mod(F[i]); //算到的結果要模去26
}
for (i = 0; i < ROW; i++)
text.AppendChar(F[i] + 'a');
return text;
}
GCD CEn_DeDlg::extended_Euclid(int a, int b)
{
GCD aa, bb;
if (b == 0)
{
aa.x = 1;
aa.y = 0;
aa.d = a;
return aa;
}
else
{
bb = extended_Euclid(b, a%b);
aa.x = bb.y;
aa.y = bb.x - (a / b) * bb.y;
aa.d = bb.d;
}
return aa;
}
int CEn_DeDlg::inverse(int a, int m)
{
GCD aa;
aa = extended_Euclid(a, m);
return aa.x;
}
int CEn_DeDlg::Mod(int a)
{
return a >= 0 ? a % M : (M + a % M);
}