(原)
常用的加密有3種
1、正向加密,如MD5,加密后密文固定,目前還沒辦法破解,但是可以能過數據庫撞庫有一定概率找到,不過現在一般用這種方式加密都會加上鹽值。
2、對稱加密,通過一個固定的對稱密鑰,對需要傳輸的數據進行加解密,速度快,但是安全性不高,主要用於企業級內部系統中數據傳輸。
3、非對稱加密,N把公鑰,一把私鑰,私鑰存放在服務器一方保管,公鑰放可以放在任何一個客戶端,客戶端向服務器請求的密文只有拿到了私鑰的服務器一端可以解密。
這里有個概念解釋一下,
隨機鹽值(solt):
abcd -> MD5加密 -> E2FC714C4727EE9395F324CD2E7F331F
然后通過撞庫的方式,這種簡單的字符一般都能很快的被找到
如果我定義一個只有自己知道的字符串,放在要加密的文的任何地方,比如我在abcd第二個字符前加上:helloword123123,那么要加密的字符就變成了:ahelloword123123worldbcd。
我們對這個再次進行加密:
ahelloword123123worldbcd -> MD5加密 -> 978E1014EEFF5E0A708314DB2E7D6DA1
我們再次通過撞庫的方式來解密:
發現這次再通過撞庫的方式解密失敗了。這里的鹽值的作用相當於擾亂了正常要加密的字符,而這個規律只有開發者,服務端的人知道。
^(異或)運算的作用。
它的運算規則是二進制運算中,相同得0,不同得1,如:2的二進制是10,3的二進制是11,最后得到的結果是01,轉成十進制就是1。
如圖:
異或運算還有一個特殊的性質,就是逆運算,就拿剛才的例子來說,2^3=1,無論2、3、1中哪二個數做異或,結果永遠只會等於另一個數。
比如:
2^3=1
2^1=3
3^1=2,通過異或這種特殊的運算性質,用它來做對稱加密是比較好的選擇。
下面給一個JAVA的簡單實現:
將1234用密鑰abc加密。
思路:
1、先將1234轉換成二進制,即ASCII碼。
加密:
1、2、3、4分別對應着49、50、51、52
49 -> 加密過程為:49 ^ 密鑰 ^ 鹽值 -> m1
50 -> 加密過程為:50 ^ 密鑰 ^ m1 -> m2
51 -> 加密過程為:51 ^ 密鑰 ^ m2 -> m3
52 -> 加密過程為:52 ^ 密鑰 ^ m3 -> m4
經過上述運算后,密文就變成了m1、m2、m3、m4。
解密:
解密是上面加密的逆運算:已知條件為m1、m2、m3、m4
m4 -> 解密過程為:m4 ^ m3 ^ 密鑰 -> 52
m3 -> 解密過程為:m3^ m2 ^ 密鑰 -> 51
m2 -> 解密過程為:m2 ^ m1 ^ 密鑰 -> 50
m1 -> 解密過程為:m1 ^ 鹽值 ^ 密鑰 -> 49
下面給出JAVA實現代碼:
package com.lee; public class Encryption { public static void main(String[] args) { String content = "1234"; //需要加密的字符 String key = "abc"; //密鑰 byte[] result = encryption(content, key); System.out.println("1234加密后的值:" + new String(result)); System.out.println("---------------"); System.out.println("1234解密后的值:" +new String(decipher(new String(result), key))); } public static byte[] encryption(String content,String key){ byte[] contentBytes = content.getBytes(); byte[] keyBytes = key.getBytes(); byte dkey = 0; for(byte b : keyBytes){ dkey ^= b; } byte salt = 0; //隨機鹽值 byte[] result = new byte[contentBytes.length]; for(int i = 0 ; i < contentBytes.length; i++){ salt = (byte)(contentBytes[i] ^ dkey ^ salt); result[i] = salt; } return result; } public static byte[] decipher(String content,String key){ byte[] contentBytes = content.getBytes(); byte[] keyBytes = key.getBytes(); byte dkey = 0; for(byte b : keyBytes){ dkey ^= b; } byte salt = 0; //隨機鹽值 byte[] result = new byte[contentBytes.length]; for(int i = contentBytes.length - 1 ; i >= 0 ; i--){ if(i == 0){ salt = 0; }else{ salt = contentBytes[i - 1]; } result[i] = (byte)(contentBytes[i] ^ dkey ^ salt); } return result; } }
輸出結果為: