md5加密java原理
Ⅰ md5是什麼呀
MD5即Message-Digest Algorithm 5(信息-摘要演算法 5),是在計算機語言當中普遍使用的一種雜湊程序,由於它類似於函數,我們稱為演算法。此雜湊函數是由MD2、MD3和MD4完善而來。其基本原理就是將一個字元串(包括漢字等)通過一定的函數轉換為一種新的字元串,並且這種雜湊運算是以不可逆轉的形式存在。在1992年8月Ronald L. Rivest在向IEFT提交了一份重要文件,描述了這種演算法的原理,由於這種演算法的公開性和安全性,在90年代被廣泛使用在各種程序語言中,用以確保資料傳遞無誤等。
由於MD5演算法的可靠性,被廣泛用於雜湊資料正確性驗證。經過許多程序員的努力,MD5演算法已經被各種語言實現,.asp,.php,.java ,c,c#,vb,vc++,delphi等語言。
MD5演算法以16個32位子分組即512位分組來提供數據雜湊,經過程序流程,生成四個32位數據,最後聯合起來成為一個128位散列。基本方式為,求余、取余、調整長度、與鏈接變數進行循環運算。得出結果。
MD5由MD4、MD3、MD2改進而來,主要是增加了演算法難度和不可逆性。
雖然目前對MD5演算法本身還沒有已知或已公布的攻擊方法,但是由於它是一種比較老的演算法,使用MD5計算出的的散列值長度只有128位,隨著現代計算機運算能力的提高,通過一些方式,尋找一個可能的「碰撞」(沖突)已經變得可能。因此,MD5在一些對安全要求比較高的場合已經逐步被其它的演算法所替代。
由於MD5使用的廣泛性和可靠性,諸多程序員對其進行了大量的研究,並取得了一些成果,但是並未改變MD5演算法的可逆性,沒有完整的反MD5函數出現。
Ⅱ 求Java的MD5加密解密實現類。 要實現對用戶的密碼進行加密! 然後驗證用戶的密碼!
我簡單說下吧,加密就是存進資料庫的時候變成MD5存進去,解密,就是對比的時候,將用戶輸入的密碼轉換成MD5和資料庫裡面的對比。
Ⅲ 可變MD5加密(Java實現)
可變在這里含義很簡單 就是最終的加密結果是可變的 而非必需按標准MD 加密實現 Java類庫security中的MessageDigest類就提供了MD 加密的支持 實現起來非常方便 為了實現更多效果 我們可以如下設計MD 工具類
Java代碼
package ** ** util;
import java security MessageDigest;
/**
* 標准MD 加密方法 使用java類庫的security包的MessageDigest類處理
* @author Sarin
*/
public class MD {
/**
* 獲得MD 加密密碼的方法
*/
public static String getMD ofStr(String origString) {
String origMD = null;
try {
MessageDigest md = MessageDigest getInstance( MD );
byte[] result = md digest(origString getBytes());
origMD = byteArray HexStr(result);
} catch (Exception e) {
e printStackTrace();
}
return origMD ;
}
/**
* 處理位元組數組得到MD 密碼的方法
*/
private static String byteArray HexStr(byte[] bs) {
StringBuffer *** = new StringBuffer();
for (byte b : bs) {
*** append(byte HexStr(b));
}
return *** toString();
}
/**
* 位元組標准移位轉十六進制方法
*/
private static String byte HexStr(byte b) {
String hexStr = null;
int n = b;
if (n < ) {
//若需要自定義加密 請修改這個移位演算法即可
n = b & x F + ;
}
hexStr = Integer toHexString(n / ) + Integer toHexString(n % );
return hexStr toUpperCase();
}
/**
* 提供一個MD 多次加密方法
*/
public static String getMD ofStr(String origString int times) {
String md = getMD ofStr(origString);
for (int i = ; i < times ; i++) {
md = getMD ofStr(md );
}
return getMD ofStr(md );
}
/**
* 密碼驗證方法
*/
public static boolean verifyPassword(String inputStr String MD Code) {
return getMD ofStr(inputStr) equals(MD Code);
}
/**
* 重載一個多次加密時的密碼驗證方法
*/
public static boolean verifyPassword(String inputStr String MD Code int times) {
return getMD ofStr(inputStr times) equals(MD Code);
}
/**
* 提供一個測試的主函數
*/
public static void main(String[] args) {
System out println( : + getMD ofStr( ));
System out println( : + getMD ofStr( ));
System out println( sarin: + getMD ofStr( sarin ));
System out println( : + getMD ofStr( ));
}
}
可以看出實現的過程非常簡單 因為由java類庫提供了處理支持 但是要清楚的是這種方式產生的密碼不是標準的MD 碼 它需要進行移位處理才能得到標准MD 碼 這個程序的關鍵之處也在這了 怎麼可變?調整移位演算法不就可變了么!不進行移位 也能夠得到 位的密碼 這就不是標准加密了 只要加密和驗證過程使用相同的演算法就可以了
MD 加密還是很安全的 像CMD 那些窮舉破解的只是針對標准MD 加密的結果進行的 如果自定義移位演算法後 它還有效么?可以說是無解的了 所以MD 非常安全可靠
為了更可變 還提供了多次加密的方法 可以在MD 基礎之上繼續MD 就是對 位的第一次加密結果再MD 恩 這樣去破解?沒有任何意義
這樣在MIS系統中使用 安全可靠 歡迎交流 希望對使用者有用
我們最後看看由MD 加密演算法實現的類 那是非常龐大的
Java代碼
import java lang reflect *;
/**
* **********************************************
* md 類實現了RSA Data Security Inc 在提交給IETF
* 的RFC 中的MD message digest 演算法
* ***********************************************
*/
public class MD {
/* 下面這些S S 實際上是一個 * 的矩陣 在原始的C實現中是用#define 實現的
這里把它們實現成為static final是表示了只讀 切能在同一個進程空間內的多個
Instance間共享*/
static final int S = ;
static final int S = ;
static final int S = ;
static final int S = ;
static final int S = ;
static final int S = ;
static final int S = ;
static final int S = ;
static final int S = ;
static final int S = ;
static final int S = ;
static final int S = ;
static final int S = ;
static final int S = ;
static final int S = ;
static final int S = ;
static final byte[] PADDING = {
};
/* 下面的三個成員是MD 計算過程中用到的 個核心數據 在原始的C實現中
被定義到MD _CTX結構中
*/
private long[] state = new long[ ]; // state (ABCD)
private long[] count = new long[ ]; // number of bits molo ^ (l *** first)
private byte[] buffer = new byte[ ]; // input buffer
/* digestHexStr是MD 的唯一一個公共成員 是最新一次計算結果的
進制ASCII表示
*/
public String digestHexStr;
/* digest 是最新一次計算結果的 進制內部表示 表示 bit的MD 值
*/
private byte[] digest = new byte[ ];
/*
getMD ofStr是類MD 最主要的公共方法 入口參數是你想要進行MD 變換的字元串
返回的是變換完的結果 這個結果是從公共成員digestHexStr取得的.
*/
public String getMD ofStr(String inbuf) {
md Init();
md Update(inbuf getBytes() inbuf length());
md Final();
digestHexStr = ;
for (int i = ; i < ; i++) {
digestHexStr += byteHEX(digest[i]);
}
return digestHexStr;
}
// 這是MD 這個類的標准構造函數 JavaBean要求有一個public的並且沒有參數的構造函數
public MD () {
md Init();
return;
}
/* md Init是一個初始化函數 初始化核心變數 裝入標準的幻數 */
private void md Init() {
count[ ] = L;
count[ ] = L;
///* Load magic initialization constants
state[ ] = x L;
state[ ] = xefcdab L;
state[ ] = x badcfeL;
state[ ] = x L;
return;
}
/* F G H I 是 個基本的MD 函數 在原始的MD 的C實現中 由於它們是
簡單的位運算 可能出於效率的考慮把它們實現成了宏 在java中 我們把它們
實現成了private方法 名字保持了原來C中的 */
private long F(long x long y long z) {
return (x & y) | ((~x) & z);
}
private long G(long x long y long z) {
return (x & z) | (y & (~z));
}
private long H(long x long y long z) {
return x ^ y ^ z;
}
private long I(long x long y long z) {
return y ^ (x | (~z));
}
/*
FF GG HH和II將調用F G H I進行近一步變換
FF GG HH and II transformations for rounds and
Rotation is separate from addition to prevent reputation
*/
private long FF(long a long b long c long d long x long s long ac) {
a += F(b c d) + x + ac;
a = ((int) a << s) | ((int) a >>> ( s));
a += b;
return a;
}
private long GG(long a long b long c long d long x long s long ac) {
a += G(b c d) + x + ac;
a = ((int) a << s) | ((int) a >>> ( s));
a += b;
return a;
}
private long HH(long a long b long c long d long x long s long ac) {
a += H(b c d) + x + ac;
a = ((int) a << s) | ((int) a >>> ( s));
a += b;
return a;
}
private long II(long a long b long c long d long x long s long ac) {
a += I(b c d) + x + ac;
a = ((int) a << s) | ((int) a >>> ( s));
a += b;
return a;
}
/*
md Update是MD 的主計算過程 inbuf是要變換的位元組串 inputlen是長度 這個
函數由getMD ofStr調用 調用之前需要調用md init 因此把它設計成private的
*/
private void md Update(byte[] inbuf int inputLen) {
int i index partLen;
byte[] block = new byte[ ];
index = (int) (count[ ] >>> ) & x F;
// /* Update number of bits */
if ((count[ ] += (inputLen << )) < (inputLen << ))
count[ ]++;
count[ ] += (inputLen >>> );
partLen = index;
// Transform as many times as possible
if (inputLen >= partLen) {
md Memcpy(buffer inbuf index partLen);
md Transform(buffer);
for (i = partLen; i + < inputLen; i += ) {
md Memcpy(block inbuf i );
md Transform(block);
}
index = ;
} else
i = ;
///* Buffer remaining input */
md Memcpy(buffer inbuf index i inputLen i);
}
/*
md Final整理和填寫輸出結果
*/
private void md Final() {
byte[] bits = new byte[ ];
int index padLen;
///* Save number of bits */
Encode(bits count );
///* Pad out to mod
index = (int) (count[ ] >>> ) & x f;
padLen = (index < ) ? ( index) : ( index);
md Update(PADDING padLen);
///* Append length (before padding) */
md Update(bits );
///* Store state in digest */
Encode(digest state );
}
/* md Memcpy是一個內部使用的byte數組的塊拷貝函數 從input的inpos開始把len長度的
位元組拷貝到output的outpos位置開始
*/
private void md Memcpy(byte[] output byte[] input int outpos int inpos int len) {
int i;
for (i = ; i < len; i++)
output[outpos + i] = input[inpos + i];
}
/*
md Transform是MD 核心變換程序 有md Update調用 block是分塊的原始位元組
*/
private void md Transform(byte block[]) {
long a = state[ ] b = state[ ] c = state[ ] d = state[ ];
long[] x = new long[ ];
Decode(x block );
/* Round */
a = FF(a b c d x[ ] S xd aa L); /* */
d = FF(d a b c x[ ] S xe c b L); /* */
c = FF(c d a b x[ ] S x dbL); /* */
b = FF(b c d a x[ ] S xc bdceeeL); /* */
a = FF(a b c d x[ ] S xf c fafL); /* */
d = FF(d a b c x[ ] S x c aL); /* */
c = FF(c d a b x[ ] S xa L); /* */
b = FF(b c d a x[ ] S xfd L); /* */
a = FF(a b c d x[ ] S x d L); /* */
d = FF(d a b c x[ ] S x b f afL); /* */
c = FF(c d a b x[ ] S xffff bb L); /* */
b = FF(b c d a x[ ] S x cd beL); /* */
a = FF(a b c d x[ ] S x b L); /* */
d = FF(d a b c x[ ] S xfd L); /* */
c = FF(c d a b x[ ] S xa eL); /* */
b = FF(b c d a x[ ] S x b L); /* */
/* Round */
a = GG(a b c d x[ ] S xf e L); /* */
d = GG(d a b c x[ ] S xc b L); /* */
c = GG(c d a b x[ ] S x e a L); /* */
b = GG(b c d a x[ ] S xe b c aaL); /* */
a = GG(a b c d x[ ] S xd f dL); /* */
d = GG(d a b c x[ ] S x L); /* */
c = GG(c d a b x[ ] S xd a e L); /* */
b = GG(b c d a x[ ] S xe d fbc L); /* */
a = GG(a b c d x[ ] S x e cde L); /* */
d = GG(d a b c x[ ] S xc d L); /* */
c = GG(c d a b x[ ] S xf d d L); /* */
b = GG(b c d a x[ ] S x a edL); /* */
a = GG(a b c d x[ ] S xa e e L); /* */
d = GG(d a b c x[ ] S xfcefa f L); /* */
c = GG(c d a b x[ ] S x f d L); /* */
b = GG(b c d a x[ ] S x d a c aL); /* */
/* Round */
a = HH(a b c d x[ ] S xfffa L); /* */
d = HH(d a b c x[ ] S x f L); /* */
c = HH(c d a b x[ ] S x d d L); /* */
b = HH(b c d a x[ ] S xfde cL); /* */
a = HH(a b c d x[ ] S xa beea L); /* */
d = HH(d a b c x[ ] S x bdecfa L); /* */
c = HH(c d a b x[ ] S xf bb b L); /* */
b = HH(b c d a x[ ] S xbebfbc L); /* */
a = HH(a b c d x[ ] S x b ec L); /* */
d = HH(d a b c x[ ] S xeaa faL); /* */
c = HH(c d a b x[ ] S xd ef L); /* */
b = HH(b c d a x[ ] S x d L); /* */
a = HH(a b c d x[ ] S xd d d L); /* */
d = HH(d a b c x[ ] S xe db e L); /* */
c = HH(c d a b x[ ] S x fa cf L); /* */
b = HH(b c d a x[ ] S xc ac L); /* */
/* Round */
a = II(a b c d x[ ] S xf L); /* */
d = II(d a b c x[ ] S x aff L); /* */
c = II(c d a b x[ ] S xab a L); /* */
b = II(b c d a x[ ] S xfc a L); /* */
a = II(a b c d x[ ] S x b c L); /* */
d = II(d a b c x[ ] S x f ccc L); /* */
c = II(c d a b x[ ] S xffeff dL); /* */
b = II(b c d a x[ ] S x dd L); /* */
a = II(a b c d x[ ] S x fa e fL); /* */
d = II(d a b c x[ ] S xfe ce e L); /* */
c = II(c d a b x[ ] S xa L); /* */
b = II(b c d a x[ ] S x e a L); /* */
a = II(a b c d x[ ] S xf e L); /* */
d = II(d a b c x[ ] S xbd af L); /* */
c = II(c d a b x[ ] S x ad d bbL); /* */
b = II(b c d a x[ ] S xeb d L); /* */
state[ ] += a;
state[ ] += b;
state[ ] += c;
state[ ] += d;
}
/*Encode把long數組按順序拆成byte數組 因為java的long類型是 bit的
只拆低 bit 以適應原始C實現的用途
*/
private void Encode(byte[] output long[] input int len) {
int i j;
for (i = j = ; j < len; i++ j += ) {
output[j] = (byte) (input[i] & xffL);
output[j + ] = (byte) ((input[i] >>> ) & xffL);
output[j + ] = (byte) ((input[i] >>> ) & xffL);
output[j + ] = (byte) ((input[i] >>> ) & xffL);
}
}
/*Decode把byte數組按順序合成成long數組 因為java的long類型是 bit的
只合成低 bit 高 bit清零 以適應原始C實現的用途
*/
private void Decode(long[] output byte[] input int len) {
int i j;
for (i = j = ; j < len; i++ j += )
output[i] = b iu(input[j]) | (b iu(input[j + ]) << ) | (b iu(input[j + ]) << )
| (b iu(input[j + ]) << );
return;
}
/*
b iu是我寫的一個把byte按照不考慮正負號的原則的"升位"程序 因為java沒有unsigned運算
*/
public static long b iu(byte b) {
return b < ? b & x F + : b;
}
/*byteHEX() 用來把一個byte類型的數轉換成十六進制的ASCII表示
因為java中的byte的toString無法實現這一點 我們又沒有C語言中的
sprintf(outbuf % X ib)
*/
public static String byteHEX(byte ib) {
char[] Digit = { A B C D E F };
char[] ob = new char[ ];
ob[ ] = Digit[(ib >>> ) & X F];
ob[ ] = Digit[ib & X F];
String s = new String(ob);
return s;
}
public static void main(String args[]) {
MD m = new MD ();
if (Array getLength(args) == ) { //如果沒有參數 執行標準的Test Suite
System out println( MD Test suite: );
System out println( MD ( ): + m getMD ofStr( ));
System out println( MD ( a ): + m getMD ofStr( a ));
System out println( MD ( abc ): + m getMD ofStr( abc ));
System out println( MD ( ): + m getMD ofStr( ));
System out println( MD ( ): + m getMD ofStr( ));
System out println( MD ( message digest ): + m getMD ofStr( message digest ));
System out println( MD ( abcdefghijklmnopqrstuvwxyz ): + m getMD ofStr( abcdefghijklmnopqrstuvwxyz ));
System out println( MD ( ):
+ m getMD ofStr( ));
} else
System out println( MD ( + args[ ] + )= + m getMD ofStr(args[ ]));
}
lishixin/Article/program/Java/hx/201311/26604
Ⅳ java中使用MD5加密演算法進行加密
在各種應用系統的開發中 經常需要存儲用戶信息 很多地方都要存儲用戶密碼 而將用戶密碼直接存儲亮衫唯在伺服器上顯然是不安全的 本文簡要介紹工作中常用的 MD 加密演算法 希望能拋磚引玉
(一)消息摘要簡介
一個消息摘要就是一個數據塊的數字指紋 即對一個任意敬培長度的一個數據塊進行計算 產生一個唯一指印(對於SHA 是產生一個 位元組的二進制數組) 消息摘要是一種與消息認證碼結合使用以確保消息完整性的技術 主要使用單向散列函數演算法 可用於檢驗消息的完整性 和通過散列密碼直接以文本形式保存等 目前廣泛使用的演算法有MD MD SHA
消息摘要有兩個基本屬性
兩個不同的報文難以生成相同的摘要難以對指定的摘要生成一個報文 而可以由該報文反推算出該指定的摘要代表 美國國家標准技術研究所的SHA 和麻省理工學院Ronald Rivest提出的MD
(二)對字元串進行加密
/***//**利用MD 進行加密*@paramstr待加密的字元串*@return加密後的字元串*塌仔@沒有這種產生消息摘要的演算法*@*/publicStringEncoderByMd (Stringstr) UnsupportedEncodingException {//確定計算方法MessageDigestmd =MessageDigest getInstance( MD );BASE Encoderbase en=newBASE Encoder();//加密後的字元串Stringnewstr=base en encode(md digest(str getBytes( utf )));returnnewstr;}調用函數 String str=
System out println(EncoderByMd (str))
輸出 eB eJF ptWaXm bijSPyxw==
(三)驗證密碼是否正確
/***//**判斷用戶密碼是否正確*@paramnewpasswd用戶輸入的密碼*@paramoldpasswd資料庫中存儲的密碼--用戶密碼的摘要*@return*@*@*/publicbooleancheckpassword(Stringnewpasswd Stringoldpasswd) UnsupportedEncodingException {if(EncoderByMd (newpasswd) equals(oldpasswd))returntrue;elsereturnfalse;} lishixin/Article/program/Java/hx/201311/26374
Ⅳ java中md5加密
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class md5 {
public String str;
public void md5s(String plainText) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(plainText.getBytes());
byte b[] = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
str = buf.toString();
System.out.println("result: " + buf.toString());// 32位的加密
System.out.println("result: " + buf.toString().substring(8, 24));// 16位的加密
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String agrs[]) {
md5 md51 = new md5();
md51.md5s("4");//加密4
}
}
Ⅵ MD5演算法原理及實現
散列函數,也稱作哈希函數,消息摘要函數,單向函數或者雜湊函數。散列函數主要用於驗證數據的完整性。通過散列函數,可以創建消息的「數字指紋」,消息接收方可以通過校驗消息的哈希值來驗證消息的完整性,防止消息被篡改。散列函數具有以下特性:
任何消息經過散列函數處理後,都會產生一個唯一的散列值,這個散列值可以用來驗證消息的完整性。計算消息散列值的過程被稱為「消息摘要」,計算消息散列值的演算法被稱為消息摘要演算法。常使用的消息摘要演算法有:MD—消息摘要演算法,SHA—安全散列演算法,MAC—消息認證碼演算法。本文主要來了解MD演算法。
MD5演算法是典型的消息摘要演算法,它是由MD4,MD3和MD2演算法演變而來。無論是哪一種MD演算法,其原理都是接受一個任意長度的消息並產生一個128位的消息摘要。如果把得到的消息摘要轉換成十六進制字元串,則會得到一個32位元組長度的字元串,我們平常見到的大部分MD數字指紋就是一個長度為32的十六進制字元串。
假設原始消息長度是b(以bit為單位),注意這里b可以是任意長度,並不一定要是8的整數倍。計算該消息MD5值的過程如下:
在計算消息的MD5值之前,首先對原始信息進行填充,這里的信息填充分為兩步。
第一步,對原始信息進行填充,填充之後,要求信息的長度對512取余等於448。填充的規則如下:假設原始信息長度為b bit,那麼在信息的b+1 bit位填充1,剩餘的位填充0,直到信息長度對512取余為448。這里有一點需要注意,如果原始信息長度對512取余正好等於448,這種情況仍然要進行填充,很明顯,在這時我們要填充的信息長度是512位,直到信息長度對512取余再次等於448。所以,填充的位數最少為1,最大為512。
第二步,填充信息長度,我們需要把原始信息長度轉換成以bit為單位,然後在第一步操作的結果後面填充64bit的數據表示原始信息長度。第一步對原始信息進行填充之後,信息長度對512取余結果為448,這里再填充64bit的長度信息,整個信息恰好可以被512整除。其實從後續過程可以看到,計算MD5時,是將信息分為若干個分組進行處理的,每個信息分組的長度是512bit。
在進行MD5值計算之前,我們先來做一些定義。
下面就是最核心的信息處理過程,計算MD5的過程實際上就是輪流處理每個信息分組的過程。
MD5演算法實現如下所示。
這里也和Java提供的標准MD5演算法進行了對比,通過測試可以看到該MD5計算的結果和Java標准MD5演算法的計算結果是一樣的。
Ⅶ 開發中常見的加密方式及應用
開發中常見的加密方式及應用
一、base64
簡述:Base64是網路上最常見的用於傳輸8Bit 位元組碼 的編碼方式之一,Base64就是一種基於64個可列印字元來表示二進制數據的方法。所有的數據都能被編碼為並只用65個字元就能表示的文本文件。( 65字元:A~Z a~z 0~9 + / = )編碼後的數據~=編碼前數據的4/3,會大1/3左右(圖片轉化為base64格式會比原圖大一些)。
應用:Base64編碼是從二進制到字元的過程,可用於在 HTTP 環境下傳遞較長的標識信息。例如,在Java Persistence系統Hibernate中,就採用了Base64來將一個較長的唯一 標識符 (一般為128-bit的UUID)編碼為一個字元串,用作HTTP 表單 和HTTP GET URL中的參數。在其他應用程序中,也常常需要把二進制 數據編碼 為適合放在URL(包括隱藏 表單域 )中的形式。此時,採用Base64編碼具有不可讀性,需要解碼後才能閱讀。
命令行進行Base64編碼和解碼
編碼:base64 123.png -o 123.txt
解碼:base64 123.txt -o test.png -D Base64編碼的原理
原理:
1)將所有字元轉化為ASCII碼;
2)將ASCII碼轉化為8位二進制;
3)將二進制3個歸成一組(不足3個在後邊補0)共24位,再拆分成4組,每組6位;
4)統一在6位二進制前補兩個0湊足8位;
5)將補0後的二進制轉為十進制;
6)從Base64編碼表獲取十進制對應的Base64編碼;
Base64編碼的說明:
a.轉換的時候,將三個byte的數據,先後放入一個24bit的緩沖區中,先來的byte占高位。
b.數據不足3byte的話,於緩沖區中剩下的bit用0補足。然後,每次取出6個bit,按照其值選擇查表選擇對應的字元作為編碼後的輸出。
c.不斷進行,直到全部輸入數據轉換完成。
d.如果最後剩下兩個輸入數據,在編碼結果後加1個「=」;
e.如果最後剩下一個輸入數據,編碼結果後加2個「=」;
f.如果沒有剩下任何數據,就什麼都不要加,這樣才可以保證資料還原的正確性。
二、HASH加密/單向散列函數
簡述:Hash演算法特別的地方在於它是一種單向演算法,用戶可以通過Hash演算法對目標信息生成一段特定長度(32個字元)的唯一的Hash值,卻不能通過這個Hash值重新獲得目標信息。對用相同數據,加密之後的密文相同。 常見的Hash演算法有MD5和SHA。由於加密結果固定,所以基本上原始的哈希加密已經不再安全,於是衍生出了加鹽的方式。加鹽:先對原始數據拼接固定的字元串再進行MD5加密。
特點:
1) 加密 後密文的長度是定長(32個字元的密文)的
2)如果明文不一樣,那麼散列後的結果一定不一樣
3)如果明文一樣,那麼加密後的密文一定一樣(對相同數據加密,加密後的密文一樣)
4)所有的加密演算法是公開的
5)不可以逆推反算(不能根據密文推算出明文),但是可以暴力 破解 ,碰撞監測
原理:MD5消息摘要演算法,屬Hash演算法一類。MD5演算法對輸入任意長度的消息進行運行,產生一個128位的消息摘要。
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值。
三、對稱加密
經典演算法:
1)DES數據加密標准
DES演算法的入口參數有三個:Key、Data、Mode。其中Key為8個位元組共64位,是DES演算法的工作密鑰;Data也為8個位元組64位,是要被加密或被解密的數據;Mode為DES的工作方式,有兩種:加密或解密。
DES演算法是這樣工作的:如Mode為加密,則用Key去把數據Data進行加密, 生成Data的密碼形式(64位)作為DES的輸出結果;如Mode為解密,則用Key去把密碼形式的數據Data解密,還原為Data的明碼形式(64位)作為DES的輸出結果。在通信網路的兩端,雙方約定一致的Key,在通信的源點用Key對核心數據進行DES加密,然後以密碼形式在公共通信網(如電話網)中傳輸到通信網路的終點,數據到達目的地後,用同樣的Key對密碼數據進行解密,便再現了明碼形式的核心數據。這樣,便保證了核心數據(如PIN、MAC等)在公共通信網中傳輸的安全性和可靠性。
2)3DES使用3個密鑰,對消息進行(密鑰1·加密)+(密鑰2·解密)+(密鑰3·加密)
3)AES高級加密標准
如圖,加密/解密使用相同的密碼,並且是可逆的
四、非對稱加密
特點:
1)使用公鑰加密,使用私鑰解密
2)公鑰是公開的,私鑰保密
3)加密處理安全,但是性能極差
經典演算法RSA:
1)RSA原理
(1)求N,准備兩個質數p和q,N = p x q
(2)求L,L是p-1和q-1的最小公倍數。L = lcm(p-1,q-1)
(3)求E,E和L的最大公約數為1(E和L互質)
(4)求D,E x D mode L = 1
五、數字簽名
原理以及應用場景:
1)數字簽名的應用場景
需要嚴格驗證發送方身份信息情況
2)數字簽名原理
(1)客戶端處理
對"消息"進行HASH得到"消息摘要"
發送方使用自己的私鑰對"消息摘要"加密(數字簽名)
把數字簽名附著在"報文"的末尾一起發送給接收方
(2)服務端處理
對"消息" HASH得到"報文摘要"
使用公鑰對"數字簽名"解密
對結果進行匹配
六、數字證書
簡單說明:
證書和駕照很相似,裡面記有姓名、組織、地址等個人信息,以及屬於此人的公鑰,並有認證機構施加數字簽名,只要看到公鑰證書,我們就可以知道認證機構認證該公鑰的確屬於此人。
數字證書的內容:
1)公鑰
2)認證機構的數字簽名
證書的生成步驟:
1)生成私鑰openssl genrsa -out private.pem 1024
2)創建證書請求openssl req -new -key private.pem -out rsacert.csr
3)生成證書並簽名,有效期10年openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt
4)將PEM格式文件轉換成DER格式openssl x509 -outform der -in rsacert.crt -out rsacert.der
5)導出P12文件openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt
iOS開發中的注意點:
1)在iOS開發中,不能直接使用PEM格式的證書,因為其內部進行了Base64編碼,應該使用的是DER的證書,是二進制格式的;
2)OpenSSL默認生成的都是PEM格式的證書。
七、https
HTTPS和HTTP的區別:
超文本傳輸協議HTTP協議被用於在Web瀏覽器和網站伺服器之間傳遞信息。HTTP協議以明文方式發送內容,不提供任何方式的數據加密,如果攻擊者截取了Web瀏覽器和網站伺服器之間的傳輸報文,就可以直接讀懂其中的信息,因此HTTP協議不適合傳輸一些敏感信息,比如信用卡號、密碼等。
為了解決HTTP協議的這一缺陷,需要使用另一種協議:安全套接字層超文本傳輸協議HTTPS。為了數據傳輸的安全,HTTPS在HTTP的基礎上加入了SSL協議,SSL依靠證書來驗證伺服器的身份,並為瀏覽器和伺服器之間的通信加密。
HTTPS和HTTP的區別主要為以下四點:
1)https協議需要到ca申請證書,一般免費證書很少,需要交費。
2)http是 超文本傳輸協議 ,信息是明文傳輸,https則是具有 安全性 的 ssl 加密傳輸協議。
3)http和https使用的是完全不同的連接方式,用的埠也不一樣,前者是80,後者是443。
4)http的連接很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的 網路協議 ,比http協議安全。
5)SSL:Secure Sockets Layer安全套接字層;用數據加密(Encryption)技術,可確保數據在網路上傳輸過程中不會被截取及竊聽。目前一般通用之規格為40 bit之安全標准,美國則已推出128 bit之更高安全標准,但限制出境。只要3.0版本以上之I.E.或Netscape 瀏覽器 即可支持SSL。目前版本為3.0。SSL協議位於TCP/IP協議與各種應用層協議之間,為數據通訊提供安全支持。SSL協議可分為兩層:SSL記錄協議(SSL Record Protocol):它建立在可靠的傳輸協議(如TCP)之上,為高層協議提供數據封裝、壓縮、加密等基本功能的支持。SSL握手協議(SSL Handshake Protocol):它建立在SSL記錄協議之上,用於在實際的數據傳輸開始前,通訊雙方進行身份認證、協商加密演算法、交換加密密鑰等。