1. 程式人生 > >RSA,MD5,DES,Base64演算法原理大全

RSA,MD5,DES,Base64演算法原理大全

RSA,MD5,DES,Base64這幾種加密演算法專案中均有用過。網上多是某一演算法實現程式碼,或者某一演算法原理加實現。比較全面的比較少,所以我整理下常用加密演算法原理做下搬運工。

1. 什麼是RSA

RSA演算法是現今使用最廣泛的公鑰密碼演算法,也是號稱地球上最安全的加密演算法。在瞭解RSA演算法之前,先熟悉下幾個術語  根據金鑰的使用方法,可以將密碼分為對稱密碼和公鑰密碼  對稱密碼:加密和解密使用同一種金鑰的方式  公鑰密碼:加密和解密使用不同的密碼的方式,因此公鑰密碼通常也稱為非對稱密碼。

2. RSA加密

RSA的加密過程可以使用一個通式來表達

密文=明文EmodN密文=明文EmodN

也就是說RSA加密是對明文的E次方後除以N後求餘數的過程。就這麼簡單?對,就是這麼簡單。  從通式可知,只要知道E和N任何人都可以進行RSA加密了,所以說E、N是RSA加密的金鑰,也就是說E和N的組合就是公鑰,我們用(E,N)來表示公鑰

公鑰=(E,N)公鑰=(E,N)

不過E和N不併不是隨便什麼數都可以的,它們都是經過嚴格的數學計算得出的,關於E和N擁有什麼樣的要求及其特性後面會講到。順便囉嗦一句E是加密(Encryption)的首字母,N是數字(Number)的首字母

3. RSA解密

RSA的解密同樣可以使用一個通式來表達

明文=密文DmodN明文=密文DmodN

也就是說對密文進行D次方後除以N的餘數就是明文,這就是RSA解密過程。知道D和N就能進行解密密文了,所以D和N的組合就是私鑰

私鑰=(D,N)私鑰=(D,N)

從上述可以看出RSA的加密方式和解密方式是相同的,加密是求“E次方的mod N”;解密是求“D次方的mod N”  此處D是解密(Decryption)的首字母;N是數字(Number)的首字母。

小結下

公鑰 (E,N)
私鑰 (D,N)
金鑰對 (E,D,N)
加密

密文=明文EmodN密文=明文EmodN

解密

明文=密文DmodN明文=密文DmodN

4. 生成金鑰對

既然公鑰是(E,N),私鑰是(D,N)所以金鑰對即為(E,D,N)但金鑰對是怎樣生成的?步驟如下:

  1. 求N
  2. 求L(L為中間過程的中間數)
  3. 求E
  4. 求D

4.1 求N

準備兩個質數p,q。這兩個數不能太小,太小則會容易破解,將p乘以q就是N

N=p∗qN=p∗q

4.2 求L

L 是 p-1 和 q-1的最小公倍數,可用如下表達式表示

L=lcm(p-1,q-1)L=lcm(p-1,q-1)

4.3 求E

E必須滿足兩個條件:E是一個比1大比L小的數,E和L的最大公約數為1  用gcd(X,Y)來表示X,Y的最大公約數則E條件如下:

1 < E < L

gcd(E,L)=1

之所以需要E和L的最大公約數為1是為了保證一定存在解密時需要使用的數D。現在我們已經求出了E和N也就是說我們已經生成了金鑰對中的公鑰了。

4.4 求D

數D是由數E計算出來的。D、E和L之間必須滿足以下關係:

1 < D < L

E*D mod L = 1

只要D滿足上述2個條件,則通過E和N進行加密的密文就可以用D和N進行解密。  簡單地說條件2是為了保證密文解密後的資料就是明文。  現在私鑰自然也已經生成了,金鑰對也就自然生成了。  小結下:

求N N= p * q ;p,q為質數
求L L=lcm(p-1,q-1) ;L為p-1、q-1的最小公倍數
求E 1 < E < L,gcd(E,L)=1;E,L最大公約數為1(E和L互質)
求D 1 < D < L,E*D mod L = 1

5 實踐下吧

我們用具體的數字來實踐下RSA的金鑰對對生成,及其加解密對全過程。為方便我們使用較小數字來模擬。

5.1 求N

我們準備兩個很小對質數,  p = 17  q = 19  N = p * q = 323

5.2 求L

L = lcm(p-1, q-1)= lcm(16,18) = 144  144為16和18對最小公倍數

5.3 求E

求E必須要滿足2個條件:1 < E < L ,gcd(E,L)=1  即1 < E < 144,gcd(E,144) = 1  E和144互為質數,5顯然滿足上述2個條件  故E = 5

此時公鑰=(E,N)= (5,323)

5.4 求D

求D也必須滿足2個條件:1 < D < L,E*D mod L = 1  即1 < D < 144,5 * D mod 144 = 1  顯然當D= 29 時滿足上述兩個條件  1 < 29 < 144  5*29 mod 144 = 145 mod 144 = 1  此時私鑰=(D,N)=(29,323)

5.5 加密

準備的明文必須時小於N的數,因為加密或者解密都要mod N其結果必須小於N  假設明文 = 123  則 密文=明文EmodN=1235mod323=225密文=明文EmodN=1235mod323=225

5.6 解密

明文=密文DmodN=22529mod323=123明文=密文DmodN=22529mod323=123  解密後的明文為123。

好了至此RSA的演算法原理已經講解完畢,是不是很簡單?

MD5訊息摘要演算法,屬Hash演算法一類。MD5演算法對輸入任意長度的訊息進行執行,產生一個128位的訊息摘要。

以下所描述的訊息長度、填充資料都以位(Bit)為單位,位元組序為小端位元組。

演算法原理

1、資料填充

對訊息進行資料填充,使訊息的長度對512取模得448,設訊息長度為X,即滿足X mod 512=448。根據此公式得出需要填充的資料長度。

填充方法:在訊息後面進行填充,填充第一位為1,其餘為0。

2、新增訊息長度

在第一步結果之後再填充上原訊息的長度,可用來進行的儲存長度為64位。如果訊息長度大於264,則只使用其低64位的值,即(訊息長度 對 264取模)。

在此步驟進行完畢後,最終訊息長度就是512的整數倍。

3、資料處理

準備需要用到的資料:

  • 4個常數: A = 0x67452301, B = 0x0EFCDAB89, C = 0x98BADCFE, D = 0x10325476;
  • 4個函式:F(X,Y,Z)=(X & Y) | ((~X) & Z); G(X,Y,Z)=(X & Z) | (Y & (~Z));  H(X,Y,Z)=X ^ Y ^ Z; I(X,Y,Z)=Y ^ (X | (~Z));

把訊息分以512位為一分組進行處理,每一個分組進行4輪變換,以上面所說4個常數為起始變數進行計算,重新輸出4個變數,以這4個變數再進行下一分組的運算,如果已經是最後一個分組,則這4個變數為最後的結果,即MD5值。

DES演算法原理完整版

    Base64編碼,是我們程式開發中經常使用到的編碼方法。它是一種基於用64個可列印字元來表示二進位制資料的表示方法。它通常用作儲存、傳輸一些二進位制資料編碼方法!也是MIME(多用途網際網路郵件擴充套件,主要用作電子郵件標準)中一種可列印字元表示二進位制資料的常見編碼方法!它其實只是定義用可列印字元傳輸內容一種方法,並不會產生新的字符集!有時候,我們學習轉換的思路後,我們其實也可以結合自己的實際需要,構造一些自己介面定義編碼方式。好了,我們一起看看,它的轉換思路吧!

Base64實現轉換原理

    它是用64個可列印字元表示二進位制所有資料方法。由於2的6次方等於64,所以可以用每6個位元為一個單元,對應某個可列印字元。我們知道三個位元組有24個位元,就可以剛好對應於4個Base64單元,即3個位元組需要用4個Base64的可列印字元來表示。在Base64中的可列印字元包括字母A-Z、a-z、數字0-9 ,這樣共有62個字元,此外兩個可列印符號在不同的系統中一般有所不同。但是,我們經常所說的Base64另外2個字元是:“+/”。這64個字元,所對應表如下。

編號 字元 編號 字元 編號 字元 編號 字元
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31 f 47 v 63 /

    轉換的時候,將三個byte的資料,先後放入一個24bit的緩衝區中,先來的byte佔高位。資料不足3byte的話,於緩衝區中剩下的bit用0補足。然後,每次取出6個bit,按照其值選擇ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字元作為編碼後的輸出。不斷進行,直到全部輸入資料轉換完成。

    如果最後剩下兩個輸入資料,在編碼結果後加1個“=”;如果最後剩下一個輸入資料,編碼結果後加2個“=”;如果沒有剩下任何資料,就什麼都不要加,這樣才可以保證資料還原的正確性。

    編碼後的資料比原始資料略長,為原來的4/3。無論什麼樣的字元都會全部被編碼,因此不像Quoted-printable 編碼,還保留部分可列印字元。所以,它的可讀性不如Quoted-printable編碼! 

文字 M a n
ASCII編碼 77 97 110
二進位制位 0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 0
索引 19 22 5 46
Base64編碼 T W F u

     M的Ascii碼是77,前六位對應值為19,對應base64字元是T,如此類推。其它字元編碼就可以自動轉換得到!我們看看另外不是剛好是3個位元組的情況! 

文字(1 Byte) A
二進位制位 0 1 0 0 0 0 0 1
二進位制位(補0) 0 1 0 0 0 0 0 1 0 0 0 0
Base64編碼 Q Q = =
文字(2 Byte) B C
二進位制位 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 x x x x x x
二進位制位(補0) 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 0 0 x x x x x x
Base64編碼 Q k M  =

Base64轉換程式碼實現

     既然知道了方法,那麼我們如果要自己寫個簡單轉換,好像也是很容易的!下面,我寫下我做轉換php程式碼!

<?php

/**

*base64編碼方法、本方法只是做base64轉換過程程式碼舉例說明,通過該例子可以任意改造不同語言版

*@author 程默

*@param $src 原字串

*@return string base64字串*

*/

function c_base64_encode($src)

{

static $base="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

////將原始的3個位元組轉換為4個位元組

$slen=strlen($src);

$smod = ($slen%3);

$snum floor($slen/3);

$desc array();

for($i=0;$i<$snum;$i++)

{

////讀取3個位元組

$_arr array_map('ord',str_split(substr($src,$i*3,3)));

///計算每一個base64值

$_dec0$_arr[0]>>2;

$_dec1= (($_arr[0]&3)<<4)|($_arr[1]>>4);

$_dec2= (($_arr[1]&0xF)<<2)|($_arr[2]>>6);  

$_dec3$_arr[2]&63;

$desc array_merge($desc,array($base[$_dec0],$base[$_dec1],$base[$_dec2],$base[$_dec3]));

}

if($smod==0) return implode('',$desc);

///計算非3倍數字節

$_arr array_map('ord',str_split(substr($src,$snum*3,3)));

$_dec0$_arr[0]>>2;

///只有一個位元組

if(!isset($_arr[1]))

{

$_dec1= (($_arr[0]&3)<<4);

$_dec2=$_dec3="=";

}

else

{

///2個位元組

$_dec1= (($_arr[0]&3)<<4)|($_arr[1]>>4);

$_dec2$base[($_arr[1]&7)<<2];

$_dec3="=";

}

$desc array_merge($desc,array($base[$_dec0],$base[$_dec1],$_dec2,$_dec3));

return implode('',$desc);

}

    好了,通過這個例子,我想base64編碼轉換原理、演算法有些瞭解了吧!它轉換過程很簡單,只需要做個對映表,然後將原先做一些移位運算就可以完成!我們通過該例子,是不是可以做個自己的base32這類的編碼呢!