1. 程式人生 > >對稱加密詳解,以及JAVA簡單實現

對稱加密詳解,以及JAVA簡單實現

turn bsp 十進制 stat mage 需要 對稱密鑰 else ges

(原)

常用的加密有3種

1、正向加密,如MD5,加密後密文固定,目前還沒辦法破解,但是可以能過數據庫撞庫有一定概率找到,不過現在一般用這種方式加密都會加上鹽值。

2、對稱加密,通過一個固定的對稱密鑰,對需要傳輸的數據進行加解密,速度快,但是安全性不高,主要用於企業級內部系統中數據傳輸。

3、非對稱加密,N把公鑰,一把私鑰,私鑰存放在服務器一方保管,公鑰放可以放在任何一個客戶端,客戶端向服務器請求的密文只有拿到了私鑰的服務器一端可以解密。

這裏有個概念解釋一下,

隨機鹽值(solt):

abcd -> MD5加密 -> E2FC714C4727EE9395F324CD2E7F331F

然後通過撞庫的方式,這種簡單的字符一般都能很快的被找到

技術分享

如果我定義一個只有自己知道的字符串,放在要加密的文的任何地方,比如我在abcd第二個字符前加上:helloword123123,那麽要加密的字符就變成了:ahelloword123123world。

我們對這個再次進行加密:

ahelloword123123world -> 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;
    }
}

輸出結果為:

技術分享

對稱加密詳解,以及JAVA簡單實現