1. 程式人生 > >【資訊保安概論】實驗一

【資訊保安概論】實驗一

                                                                             


實驗一  古典密碼

  • 實驗目的

熟悉古典加密演算法,能夠程式設計實現各種常見的加密演算法。

二、實驗任務

1.程式設計實現歐幾里得演算法求最大公因子;

2.程式設計實現凱撒(Caesar)密碼;

3程式設計實現仿射密碼、和Hill密碼


 

三、部分參考答案

編寫實現古典密碼的程式,能對給定的明文或密文進行正確的加密和解密。


(1) 仿射密碼

引數選取:模數n=26+10=36k2為學號後2位;k1為與學號後2位最近的素數。

加解密:加密自己名字的全拼和學號,再解密。 
加密程式碼:

#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
int main()
{
    /*
    (1)    仿射密碼
    引數選取:模數n=26+10=36,k2為學號後2位;k1為與學號後2位最近的素數。
    加解密:加密自己名字的全拼和學號,再解密。
    */
    int n = 36;
    string m, c;
    int buff[32], len = 0, k1 = 0, k2 = 0;
    cout << "輸入明文:" << endl;
    cin >> m;
    cout << "輸入k1:";
    cin >> k1;
    cout << "輸入k2:";
    cin >> k2;
    //把明文轉化成10進位制整數,0-9,a-z分別代表十進位制0-36
    for (int i = 0; m[i] != '\0'; i++)
    {
        //字母轉10進位制整數
        if (m[i] > '9')
            buff[i] = m[i] - 87;
        else
            buff[i] = m[i] - 48;//0ASCII為48
        len++;
    }
    //加密運算,C=k1*m+k2 mod n;
    for (int i = 0; i < len; i++)
    {
        buff[i] = (buff[i] * k1 + k2) % n;
    }
    //把數字對應為密文空間內的字元
    for (int i = 0; i < len; i++)
    {
        if (buff[i] < 10)
            m[i] = buff[i] + 48;
        else
            m[i] = buff[i] + 87;

    }
    cout << "密文為:" << endl;
    for (int i = 0; i<len; i++)
    {
        cout << m[i];
    }
    cout << endl;
    //解密,M=(C-k2)*k1^(-1)
    system("pause");
    return 0;
}

解密程式碼:

#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
//求解x^(-1)mod p
int GetIne(int x, int p)
{
    for (int i = 0; i<p; i++)
    {
        if (x*i%p == 1)
        {
            x = i;
            break;
        }
    }
    return x;
}
int main()
{
    /*
    (1) 仿射密碼
    引數選取:模數n=26+10=36,k2為學號後2位;k1為與學號後2位最近的素數。
    加解密:加密自己名字的全拼和學號,再解密。
    */
    int n = 36;
    string m, c;
    int buff[32], len = 0, k1 = 0, k2 = 0, k = 0;
    cout << "輸入密文:" << endl;
    cin >> m;
    cout << "輸入k1:";
    cin >> k1;
    cout << "輸入k2:";
    cin >> k2;
    //把明文轉化成10進位制整數,0-9,a-z分別代表十進位制0-36
    //解密,M=(C-k2)*k1^(-1)
    for (int i = 0; m[i] != '\0'; i++)
    {
        //字母轉10進位制整數
        if (m[i] > '9')
            buff[i] = m[i] - 87;
        else
            buff[i] = m[i] - 48;//0ASCII為48
        len++;
    }
    //解密運算,M=(C-k2)*k1^(-1)
    k = GetIne(k1, n);
    for (int i = 0; i < len; i++)
    {
        buff[i] = ((buff[i] - k2)*k) % n;
        if (buff[i] < 0)
            buff[i] += n;
        //buff[i] = (buff[i] * k1 + k2) % n;
    }
    //把數字對應為明文空間內的字元
    for (int i = 0; i < len; i++)
    {
        if (buff[i] < 10)
            m[i] = buff[i] + 48;
        else
            m[i] = buff[i] + 87;

    }
    cout << "明文為:" << endl;
    for (int i = 0; i<len; i++)
    {
        cout << m[i];
    }
    cout << endl;
    system("pause");
    return 0;
}

 (2) 置換密碼

引數選取:分組長度為7;置換關係隨機選取;

加解密:加密自己名字的全拼和學號(長度不足時後面全補填充長度),再解密。 
 

/*置換密碼

引數選取:分組長度為7;置換關係隨機選取;

加解密:加密自己名字的全拼和學號(長度不足時後面全補

填充長度),再解密。

string中的函式:

swap()--交換字元

push_back() --插入字元

*/

加密程式碼:

#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
int main()
{
    string m;
    system("title = 加密");
    cout << "輸入明文:" << endl;
    cin >> m;

    //cout << "string長度:" << m.size()<<endl;
    ////遍歷明文
    //for (int i=0;m[i]!='\0';i++)
    //{
    //  cout << m[i];
    //}
    //cout << endl;
    //如果明文不足7的倍數就填字元A
    for (int i = m.size(); i % 7 != 0; i++)
    {
        m.push_back('A'); //在字串後面插入字元A
    }
    //cout << "string長度:" << m.size() << endl;
    ////遍歷
    //for (int i = 0;i<m.size(); i++)
    //{
    //  cout << m[i];
    //}
    //加密
    for (int i = 0; i < m.size(); i += 7)
    {
        swap(m[i], m[i + 2]);//f(1) 
        swap(m[i], m[i + 6]);//f(2) 
        swap(m[i], m[i + 3]);//f(3) 
        swap(m[i], m[i + 0]);//f(4) 
        swap(m[i], m[i + 5]);//f(5) 
        swap(m[i], m[i + 1]);//f(6) 
        swap(m[i], m[i + 4]);//f(7) 
    }
    //輸出密文
    cout << "密文為:" << endl;
    for (int i = 0; i<m.size(); i++)
    {
        if (i != 0 && i % 7 == 0)
            cout << endl;
        cout << m[i];
    }
    cout << endl;
    system("pause");
    return 0;
}

2./*置換密碼

引數選取:分組長度為7;置換關係隨機選取;

加解密:加密自己名字的全拼和學號(長度不足時後面全補

填充長度),再解密。

string中的函式:

swap()交換字元

push_back()插入字元

*/

解密程式碼:

#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
int main()
{
    string m;
    cout << "輸入密文:" << endl;
    cin >> m;
    system("title = 解密");
    //cout << "string長度:" << m.size()<<endl;
    ////遍歷明文
    //for (int i=0;m[i]!='\0';i++)
    //{
    //  cout << m[i];
    //}
    //cout << endl;
    //cout << "string長度:" << m.size() << endl;
    ////遍歷
    //for (int i = 0;i<m.size(); i++)
    //{
    //  cout << m[i];
    //}
    //解密
    for (int i = 0; i < m.size(); i += 7)
    {
        swap(m[i], m[i + 4]);//f(7)
        swap(m[i], m[i + 1]);//f(6)
        swap(m[i], m[i + 5]);//f(5) 
        swap(m[i], m[i + 0]);//f(4)
        swap(m[i], m[i + 3]);//f(3) 
        swap(m[i], m[i + 6]);//f(2) 
        swap(m[i], m[i + 2]);//f(1) 
    }
    //輸出明文
    cout << "明文為:" << endl;
    for (int i = 0;m[i] != 'A'; i++)
    {
        /*if (i != 0 && i % 7 == 0)
        cout << endl;*/
        cout << m[i];
    }
    cout << endl;
    system("pause");
    return 0;
}

(3) Hill密碼  

加密程式碼:

#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
int main()
{
    string m;
    int buffer[4];
    int a[4];//存放m*A mod 26的結果
    int b[16];//存放m和A的轉置矩陣的乘積
              //矩陣A的轉置矩陣
    int A[] = { 8,6,5,10,
        6,9,8,6,
        9,5,4,11,
        5,10,9,4 };
    ////A的逆矩陣的轉置矩陣
    //int B[] = { 23,2,2,25,
    //  20,11,20,2,
    //  5,18,6,22,
    //  1,1,25,25 };
    cout << "輸入明文:" << endl;
    cin >> m;
    system("title = 加密");
    //把字元轉化成10進位制整數
    for (int i = 0; m[i] != '\0'; i++)
    {
        buffer[i] = m[i] - 97;
    }

    cout << "buffer陣列中的元素:" << endl;
    for (int i = 0; i<4; i++)
    {
        cout << buffer[i] << ",";
    }
    cout << endl;
    //加密C = m * A mod 26,把結果放入陣列a
    for (int i = 0; i<16; i++)
    {
        b[i] = buffer[i % 4] * A[i];
    }
    cout << "b陣列中的元素:" << endl;
    for (int i = 0; i<16; i++)
    {
        cout << b[i] << ",";
    }
    cout << endl;
    for (int i = 0; i < 16; i += 4)
    {
        a[i / 4] = (b[i] + b[i + 1] + b[i + 2] + b[i + 3]) % 26;
        if (a[i / 4] < 0)
            a[i / 4] += 26;
    }

    cout << "a陣列中的元素:" << endl;
    for (int i = 0; i<4; i++)
    {
        cout << a[i] << ",";
    }
    cout << endl;
    //轉換為字元
    cout << "密文為:" << endl;
    for (int i = 0; i<4; i++)
    {
        m[i] = a[i] + 97;
        cout << m[i];
    }
    cout << endl;
    system("pause");
    return 0;
}

解密程式碼:

#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
int main()
{
    string m;
    int buffer[4];
    int a[4];
    int b[16];//存放m和A的轉置矩陣的乘積
              //矩陣A的轉置矩陣
    /*int A[] = { 8,6,5,10,
        6,9,8,6,
        9,5,4,11,
        5,10,9,4 };*/
    //A的逆矩陣的轉置矩陣
    int B[] = { 23,2,2,25,
        20,11,20,2,
        5,18,6,22,
        1,1,25,25 };
    cout << "輸入密文:" << endl;
    cin >> m;
    system("title = 解密");
    //把字元轉化成10進位制整數
    for (int i = 0; m[i] != '\0'; i++)
    {
        buffer[i] = m[i] - 97;
    }

    cout << "buffer陣列中的元素:" << endl;
    for (int i = 0; i<4; i++)
    {
        cout << buffer[i] << ",";
    }
    cout << endl;
    //解密M = C * B mod 26,把結果放入陣列a,B是A的逆矩陣
    for (int i = 0; i<16; i++)
    {
        b[i] = buffer[i % 4] * B[i];
    }
    cout << "b陣列中的元素:" << endl;
    for (int i = 0; i<16; i++)
    {
        cout << b[i] << ",";
    }
    cout << endl;
    for (int i = 0; i < 16; i += 4)
    {
        a[i / 4] = (b[i] + b[i + 1] + b[i + 2] + b[i + 3]) % 26;
        if (a[i / 4] < 0)
            a[i / 4] += 26;
    }

    cout << "a陣列中的元素:" << endl;
    for (int i = 0; i<4; i++)
    {
        cout << a[i] << ",";
    }
    cout << endl;
    //轉換為字元
    cout << "明文為:" << endl;
    for (int i = 0; i<4; i++)
    {
        m[i] = a[i] + 97;
        cout << m[i];
    }
    cout << endl;
    system("pause");
    return 0;
}