1. 程式人生 > >密碼學筆記(一)古典密碼

密碼學筆記(一)古典密碼

密碼學的階段劃分

  密碼學的發展按照其對演算法和祕鑰的保密程度大致可以分為如下三個階段。

  • 古典密碼階段(1949年前)
    在這個階段演算法和祕鑰都是保密的,祕鑰空間較小,資訊的安全性主要依賴於對於加密和解密演算法的保密。
  • 對稱密碼階段(1949-1975年)
    在這之後就進入到了現代密碼學的階段,和古典密碼階段的主要區別在於這個階段的加密和解密演算法無需保密,資訊的安全性主要依賴於對祕鑰的保密。需要解決的主要問題是在不可信通道下的祕鑰傳輸問題。
  • 公鑰密碼階段(1976年-至今)
    在公鑰密碼階段,加密祕鑰(公鑰)可以公開,僅對解密祕鑰(私鑰)保密,基於一些數學難題保證很難通過公鑰推出私鑰。

數學知識

  • 整除與約簡
  • 同餘
  • 素數的相關性質
    每一個正整數都可以分解為一系列素數的乘積,且這種分解是唯一的。
    n=pe11+pe22...pemmei>0,i=1,2,....m
  • 歐幾里得演算法和拓展歐幾里得演算法
    歐幾里得演算法(輾轉相除法)略
    在學拓展歐幾里得演算法的時候遇到了一些困難就多記一下了。
    先說一條定理:對於任意x和y不同時為0的整數,x和y的最大公因子(x,y)是以ax+by表示的最小整數。
    而拓展歐幾里得演算法就是用來求這個a和b的。下圖是計算方法的推導過程:
    推導過程
    通過上面的推導可以寫出下面這樣的一個式子:
    [011qn][011qn1]...
    [011q1][xy]=[gcd(x,y)0]

    將矩陣相乘即可求得a,b,根據求解方向的不同可以得到遞迴和非遞迴的演算法,矩陣從左向右算為遞迴演算法(從左向右也可以寫成非遞迴演算法,不過需要一個數組記錄qn),矩陣從右向左演算法為非遞迴演算法。
    遞迴演算法實現:
void exgcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return;
    }
    exgcd(b,a%b,x,y);
    int t=x;
    x=y;
    y=t-a/b*y
; return; }

非遞迴演算法一實現

void exgcd(int m,int n,int &x,int &y)
{
    int r=1;
    vector<int> qList;
    while (r!=0){          //迴圈計算q並放入vector中
        r=m%n;
        int q=m/n;
        qList.push_back(q);
        m=n;
        n=r;
    }
    int listSize=qList.size();
    x=0;
    y=1;
    for(int i=listSize-2;i>=0;--i){ //計算x,y
        int tempX=x;
        x=y;
        y=tempX-y*qList[i];
    }
}

非遞迴演算法二實現:

void exgcd(int m,int n,int &x,int &y)
{
    int x1,y1,x0,y0;
    x0=1; y0=0;
    x1=0; y1=1;
    x=0; y=1;
    int r=m%n;
    int q=(m-r)/n;
    while(r)
    {
        x=x0-q*x1; y=y0-q*y1;
        x0=x1; y0=y1;
        x1=x; y1=y;
        m=n; n=r; r=m%n;
        q=(m-r)/n;
    }
}
  • 乘法逆元
    定義:n模m的乘法逆t記做(n1%m)滿足n*t%m=1
    乘法逆存在的條件:(n,m)=1
    簡單證明:
    n*t%m=1 =>n*t=k*m+1
    (k*m+1,k*m)=1 => (k*m+1,m)=1 =>(n*t,m)=1
    (n*t,m)=1 =>(n,m)=1
    得證
    計算乘法逆的方法:使用拓展歐幾里得演算法求得an+bm=1,則a為其乘法逆。

古典密碼學-代替密碼

  密碼學中對資訊進行處理的主要方式有兩種換位和代替,顧名思義換位就是將原有的明文字元的順序打亂,而代替則是按照一定的規律將明文字元替換成一些其他的字元。按照處理方式的不同,具體的分類如下圖所示(盜的上課ppt上的圖(◔◡◔)):
  古典密碼分類
  下面就分別介紹一些常見的古典密碼的實現。

Caesar 密碼

  Caesar 密碼非常簡單,它的一般表示式如下所示:
  

y=f(x)=(x+k)%26x=f(y)=(yk)%26
  Caesar密碼的加密祕鑰k和解密祕鑰是相同的,同時祕鑰空間的大小為25,通過不斷嘗試k的數值我們可以非常輕易的得到祕鑰。

仿射密碼

  由於Caesar 密碼的祕鑰空間較小,通過增加引數提升祕鑰空間大小就得到了仿射密碼。
  

y=y=Ea,b(x)=(ax+b)%26Da,b=(a1ya1b)%26
通過分析我們可以知道其祕鑰空間大小為311,其計算公式為12*26-1。12表示的是a的可能性,因為a模26的乘法逆必須存在,所以其值為φ(26),26為b的可能性,減一是a=1,b=0的特殊情況。仿射密碼的祕鑰長度雖然得到擴大但是依然有限,同時其本質上依然為單表代替密碼,密文中依然保留著明文中字元的統計規律,易被破解。

Vignere密碼

  Vignere的多表代替密碼中最著名的也是最簡單,它本質上不過是多個Caesar密碼組合,每隔一位就換一個Caesar密碼的祕鑰,直到結束又開始迴圈,其祕鑰序列表示為:K=k0,K1,K2,...Km1,可以看出Caesar密碼是Vignere密碼祕鑰長度為1時的特殊情況,具體加解密公式如下:

yi=(xi+ki%m)%26xi=(yiki%m)%26
可以看出Vignere密碼的祕鑰空間為26m,祕鑰空間可以說是非常大了,但是因為其還是保留許多頻率分佈的特徵,通過Kasiski測試法和重合指數攻擊在祕鑰不大長的情況下可以比較簡單的進行破解,對多表替代密碼的攻擊方式下次再寫。

OTP密碼(一次一密密碼)

  演算法原理:加密的祕鑰和明文一樣長,而且祕鑰本身只使用一次。具體的加密方式可以任意可以是Vignere密碼也可以是Vernam密碼。
  一次一密密碼在理論上保證了資訊的完全安全,因為任意一段有意義的明文都會對於一段唯一的祕鑰,而攻擊者如果採用窮舉攻擊的方式,將會得到大量有意義的明文,攻擊者將無法判斷哪個才是正確的。缺點:大規模隨機祕鑰的產生非常困難,同時更為麻煩的是祕鑰的分發和儲存。

古典密碼-換位密碼