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)但金鑰對是怎樣生成的?步驟如下:
- 求N
- 求L(L為中間過程的中間數)
- 求E
- 求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這類的編碼呢!