古典密码(凯撒密码/维吉尼亚密码/Play fair密码/Hill密码)的实现(MFC界面)

学了一些MFC的编程刚好结合密码学的四种古典密码算法实现结合一下,写了一个自己的带MFC界面的加密解密系统。
《古典密码(凯撒密码/维吉尼亚密码/Play fair密码/Hill密码)的实现(MFC界面)》
具体的密码算法原理在此就不贴出了,直接贴相关的源码:
简单解释:
i:凯撒密码的密钥是数字,也就是偏移量
ii:维吉尼亚密码的密钥是字符串
iii:Play fair密码的密钥是字符串,来构造5*5的字母密钥表
iiii:Hill密钥的密钥是n*n的可逆矩阵,这里我只对明文空间为5的明文进行加密解密,可以点击生成5*5的加密矩阵,以及其伴随矩阵
【源码下载】
链接:http://pan.baidu.com/s/1nuXDdUx 密码:3jjd
(1)左边四种算法的选择用的是radio button:



void CEn_DeDlg::OnBnClickedRadio1() { // TODO: 在此添加控件通知处理程序代码 choose = 1; MessageBox(_T(" 输入密钥,密钥为数字")); } void CEn_DeDlg::OnBnClickedRadio2() { // TODO: 在此添加控件通知处理程序代码 choose = 2; MessageBox(_T(" 输入密钥,密钥为字符串")); } void CEn_DeDlg::OnBnClickedRadio3() { // TODO: 在此添加控件通知处理程序代码 choose = 3; MessageBox(_T(" 输入密钥,密钥为字符串,来生成5*5字符矩阵")); } void CEn_DeDlg::OnBnClickedRadio4() { // TODO: 在此添加控件通知处理程序代码 choose = 4; MessageBox(_T(" 无需输入密钥,明文空间为5,密钥为n*n的数字矩阵,可点击右上方生成按钮生成符合条件的5*5矩阵密钥")); } 

加密函数:


//加密
void CEn_DeDlg::OnBnClickedButton1()
{
    // TODO: 在此添加控件通知处理程序代码
    // 将各控件中的数据保存到相应的变量 
    UpdateData(TRUE);


    switch (choose)
    {
    case 1://凯撒 
    {
              CString s = m_ming;
              CString ss;
              int t = 0;
              while (t < s.GetLength())
              {

                  if (s[t] <= 'z'&&s[t] >= 'a')
                      ss.AppendChar('a' + (s[t] - 'a' + _ttoi(m_key)) % 26);
                  else if (s[t] <= 'Z'&&s[t] >= 'A')
                      ss.AppendChar('A' + (s[t] - 'A' + _ttoi(m_key)) % 26);
                  else
                  {
                      ss.AppendChar(s[t]);
                  }

                  t++;
              }
              m_mi = ss;
              break;
    }

    case 2://维吉尼亚 
    {
              int i, j, s = 0;
              j = m_key.GetLength();
              int size1 = m_ming.GetLength();
              m_ming.MakeLower();
              for (i = 0; i<size1; i++) {
                  if (isalpha(m_ming[i])) {
                      m_mi.AppendChar( (m_ming[i] - 'a' + m_key[s%j] - 'a') % 26 + 'a');
                      s++;
                  }
                  else
                      m_mi.AppendChar(m_ming[i]);
              }
              m_mi.MakeUpper();
              break;
    }

    case 3://play fair 
    {
        m_key2 = _T("");
        int l,i,j;
        char p[1000];
        m_key1 = _T("");
        dealkey(m_key);
        l=m_ming.GetLength();

        for(i=0;i<l;i++)
        {
            p[i]=m_ming[i];
        }

        for(i=0;i<l;i++)
        {
            if(p[i]=='j')
            {
                p[i]='i';
            }
        }

        for(i=0;i<l;i=i+2)
        {
            if(p[i]==p[i+1])
            {
                l++;
                for(int n=l-1;n>i+1;n--)
                {
                    p[n]=p[n-1];
                }
                p[i+1]='q';
            }
        }

        if(l%2!=0)
        {
            p[l]='q';
            l++;
        }
        p[l]='\0';

        int c,d,e,f;
        char h[1000];
        int k=0;

        for(int o=0;o<l;o=o+2)
        {
            for(i=0;i<5;i++)
            {
                for(j=0;j<5;j++)
                {
                    if(p[o]==m[i][j])
                    {
                        c=i;
                        d=j;
                    }
                    if(p[o+1]==m[i][j])
                    {
                        e=i;
                        f=j;
                    }
                }
            }

            if(c==e)
            {
                h[k]=m[c][(d+1)%5];
                k++;
                h[k]=m[e][(f+1)%5];
                k++;
            }
            else
            {
                if(d==f)
                {
                    h[k]=m[(c+1)%5][d];
                    k++;
                    h[k]=m[(e+1)%5][f];
                    k++;
                }
                else
                {
                    h[k]=m[c][f];
                    k++;
                    h[k]=m[e][d];
                    k++;
                }
            }
        }
        h[k]='\0';
        m_mi=h;
              break;
    }

    case 4://Hill
    {


        //利用所选密钥,对给定的5元明文信息进行加解密

        m_mi=encryption(m_ming);

              break;
    }

    default:
        break;

    }
    // 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值 
    UpdateData(FALSE);
}

(备注:其中一些非主要函数没有贴出)

解密函数:


//解密
void CEn_DeDlg::OnBnClickedButton2()
{
    // 将各控件中的数据保存到相应的变量 
    UpdateData(TRUE);
    // TODO: 在此添加控件通知处理程序代码
    switch (choose)
    {
    case 1:
    {
        CString s = m_mi;
        CString ss;
        int t = 0;
        while (t < s.GetLength())
        {

            if (s[t] <= 'z'&&s[t] >= 'a')
                ss.AppendChar('z' - ('z' - s[t] + _ttoi(m_key)) % 26);
            else if (s[t] <= 'Z'&&s[t] >= 'A')
                ss.AppendChar('Z' - ('Z' - s[t] + _ttoi(m_key)) % 26);
            else
            {
                ss.AppendChar(s[t]);
            }

            t++;
        }
        m_rming = ss;
        break;
    }

    case 2:
    {
        int i, j, s=0;
         j=m_key.GetLength();
         int size1 = m_mi.GetLength();
         m_mi.MakeLower();
         for(i=0; i<size1; i++)
         if(isalpha(m_mi[i])) {
             m_rming.AppendChar((m_mi[i]-m_key[s%j]+26)%26+'a');
             s++;
             }
         else
             m_rming.AppendChar( m_mi[i]);
        break;
    }

    case 3:
    {
        int l,i,j;
        char p[1000];
        m_key1 = _T("");
        dealkey(m_key);
        l=m_mi.GetLength();

        for(i=0;i<l;i++)
        {
            p[i]=m_mi[i];
        }

        int c,d,e,f;
        char h[1000];
        int k=0;

        for(int o=0;o<l;o=o+2)
        {
            for(i=0;i<5;i++)
            {
                for(j=0;j<5;j++)
                {
                    if(p[o]==m[i][j])
                    {
                        c=i;
                        d=j;
                    }
                    if(p[o+1]==m[i][j])
                    {
                        e=i;
                        f=j;
                    }
                }
            }
    // printf("%d %d ",c,e);

            if(c==e)
            {
                h[k]=m[c][(d-1+5)%5];
                k++;
                h[k]=m[e][(f-1+5)%5];
                k++;
            }
            else
            {
                if(d==f)
                {
                    h[k]=m[(c-1+5)%5][d];
                    k++;
                    h[k]=m[(e-1+5)%5][f];
                    k++;
                }
                else
                {
                    h[k]=m[c][f];
                    k++;
                    h[k]=m[e][d];
                    k++;
                }
            }
        }
        h[k]='\0';

        for(i=0;i<k;i=i+2)
        {
            if((h[i]==h[i+2])&&(h[i+1]=='q'))
            {
                for(j=i+1;j<k;j++)
                {
                    h[j]=h[j+1];
                }
                k=k-1;
            }
        }
        if(h[k-1]=='q')
        {
            h[k-1]='\0';
        }

        m_rming=h;
        int size2 = m_rming.GetLength();
        char str[1000];
        for (int i = 0; i < size2; i++)
        {
            str[i] = m_rming[i];
        }
        for (int i = 0; i < size2; i++)
        {
            if (str[i] == 'q'&&str[i - 1] == str[i + 1])
            {
                for (int j = i; j < size2; j++)
                {
                    str[j] = str[j + 1];

                }
                i--;
                size2--;
            }

        }
        str[size2] = '\0';
        m_rming = str;
        break;
    }

    case 4:
    {

        m_rming = deciphering(m_mi);

        break;
    }

    default:
        break;

    }
    // 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值 
    UpdateData(FALSE);
}

生成矩阵按钮函数:


//生成矩阵
void CEn_DeDlg::OnBnClickedButton7()
{
    // TODO: 在此添加控件通知处理程序代码
    UpdateData(TRUE);
    m_key1 = _T("");
    m_key2 = _T("");
    srand((unsigned)time(0));
    random_Matrix();
    while (!Inverse(K))
    {

        random_Matrix();
    }
    int determinant = Det(K, ROW);
    int inver = inverse(determinant, 26);
    adjoint_matrix(K, ROW);   //伴随矩阵
    m_key1.AppendChar('\n');
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            CString temp;
            temp.Format(_T("%d"), K[i][j]);
            m_key1.Append(temp);
            m_key1.AppendChar(' ');
            if (K[i][j] < 10)
            {
                m_key1.AppendChar(' ');
                m_key1.AppendChar(' ');
            }


        }
        m_key1.AppendChar('\n');
    }

    m_key2.AppendChar('\n');
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            CString temp;
            temp.Format(_T("%d"), D[i][j]);
            m_key2.Append(temp);
            m_key2.AppendChar(' ');
            if (D[i][j] < 10)
            {
                m_key2.AppendChar(' ');
                m_key2.AppendChar(' ');
            }


        }
        m_key2.AppendChar('\n');
    }
    UpdateData(FALSE);
}

Playfair密码需要用到的函数:


void CEn_DeDlg::dealkey(CString p)
{

    int length;
    int i, j;
    char key[1000];

    length = p.GetLength();
    for (i = 0; i<length; i++)
    {
        key[i] = p[i];
    }

    for (i = 0; i<length; i++)
    {
        if (key[i] == 'j')
        {
            for (int t = i; t<length; t++)
            {
                key[t] = key[t + 1];
            }
            i--;
            length--;
        }
    }

    for (i = 0; i<length; i++)
    {
        for (j = i + 1; j<length; j++)
        {
            if (key[i] == key[j])
            {
                for (int t = j; t<length; t++)
                {
                    key[t] = key[t + 1];
                }
                j--;
                length--;
            }
        }
        if (j == 1)
        {
            key[j] = 0;
            break;
        }
    }

    char a = 'a';
    while (a <= 'z')
    {
        if (a == 'j')
        {
            a++;
        }
        for (i = 0; i<length; i++)
        {
            if (a == key[i])
            {
                a++;
                break;
            }
        }
        if (i == length)
        {
            key[length] = a;
            length++;
            a++;
        }
    }
    key[length] = '\0';

    int n = 0;
    while (n<length)
    {
        m_key1.AppendChar('\n');
        for (i = 0; i<5; i++)
        {
            for (j = 0; j<5; j++)
            {
                m[i][j] = key[n];
                char temp = toupper(key[n]);
                m_key1.AppendChar(temp);
                m_key1.AppendChar(' ');
                n++;
            }
            m_key1.AppendChar('\n');
        }
    }


}

前三个密码算法已经在上面两个函数中实现了,另外贴一下Hill加密解密需要的函数的实现:



 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); } 

清空按钮函数:


void CEn_DeDlg::OnBnClickedButton8()
{
    // TODO: 在此添加控件通知处理程序代码
    UpdateData(TRUE);
    m_ming = _T("");
    UpdateData(FALSE);
}


void CEn_DeDlg::OnBnClickedButton9()
{
    // TODO: 在此添加控件通知处理程序代码
    UpdateData(TRUE);
    m_key = _T("");
    UpdateData(FALSE);
}


void CEn_DeDlg::OnBnClickedButton10()
{
    // TODO: 在此添加控件通知处理程序代码
    UpdateData(TRUE);
    m_mi = _T("");
    UpdateData(FALSE);
}


void CEn_DeDlg::OnBnClickedButton11()
{
    // TODO: 在此添加控件通知处理程序代码
    UpdateData(TRUE);
    m_rming = _T("");
    UpdateData(FALSE);
}

编写得简单粗暴,见谅。

    原文作者:维吉尼亚加密问题
    原文地址: https://blog.csdn.net/huangmx1995/article/details/52756532
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞