小談加密算法

一、爲何要用加密

網站中有不少相似金錢、密碼等重要業務數據,一旦被監聽、攔截,可能會形成嚴重的損失。
好比下圖:前端

咱們能夠很容易的看到某個請求的相關參數數據
這裏寫圖片描述java

二、應用場景

加密算法有不少種應用場景,最多見的是用戶登陸、身份驗證、驗籤等等。目的在於經過算法,將明文轉換爲密文。將明文轉換爲密文只是第一步,更深一步的作法是結合sessionId、隨機數、token或者https等,最大限度的防止信息被盜取。算法

三、類型

加密算法一般分爲對稱性加密算法和非對稱性加密算法。後端

3.1 對稱性加密

只存在一把鑰匙key,若是A想要與B通信,那麼A使用鑰匙進行加密,B接收到密文的鑰匙後,使用鑰匙解密,得到明文信息。安全

這裏寫圖片描述

優缺點
效率高、使用維護簡單,缺點就是密碼一旦泄露,通信信息就會暴露。markdown

經常使用加密算法:
DES、三重DES、AES等,稍後會以AES爲例,介紹具體用法。session

3.2 非對稱加密

非對稱加密有兩把鑰匙:私鑰和公鑰。
這裏有幾個原則和前提須要先說明:
1)公鑰和私鑰是成對出現的。
2)公開的是公鑰,私鑰只有本身知道。
3)用公鑰加密的信息,只能用對應的私鑰進行解密。網站

這裏寫圖片描述

A、B各有一對密鑰,A的密鑰包括:公鑰0一、私鑰02,B的密鑰包括:公鑰0三、私鑰04。其中,A擁有B的公鑰03,一樣的,B也擁有A的公鑰01。編碼

當A要與B通信時,A使用B的公鑰03加密,當B拿到密文後,拿本身的私鑰04解密。加密

優缺點:
非對稱加密的優缺點正好與對稱加密相反,可參照上面。

經常使用加密算法:
RSA,DSA,ECC

除了上面兩種主要類型的加密算法,還有一大類是線性散列算法,也叫簽名算法。經常使用算法有:MD5,SHA1,HMAC。這類算法能夠生成一長串不可逆的密文,常常用在校驗數據在傳輸過程當中是否通過修改。

四、實例

場景:用戶登陸,使用res加密,前端js加密,後端解密。

4.1 js文件

//加密key
   var key =CryptoJS.enc.Utf8.parse("*******"); 
   //pwd爲加密信息 
   var srcs = CryptoJS.enc.Utf8.parse(pwd); 
   var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});

4.2 後臺解密

/** * 密鑰,要與加密時的密鑰保持一致 */
    private static final String KEY = "*******";
    /** * 算法 */
    private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";

    /** * aes解密 * * @param encrypt * 內容 * @return * @throws Exception */
    public static String aesDecrypt(String encrypt) throws Exception {
        return aesDecrypt(encrypt, KEY);
    }

    /** * aes加密 * * @param content * @return * @throws Exception */
    public static String aesEncrypt(String content) throws Exception {
        return aesEncrypt(content, KEY);
    }

    /** * 將byte[]轉爲各類進制的字符串 * * @param bytes * byte[] * @param radix * 能夠轉換進制的範圍,從Character.MIN_RADIX到Character.MAX_RADIX,超出範圍後變爲10進制 * @return 轉換後的字符串 */
    public static String binary(byte[] bytes, int radix) {
        return new BigInteger(1, bytes).toString(radix);// 這裏的1表明正數
    }

    /** * base 64 encode * * @param bytes * 待編碼的byte[] * @return 編碼後的base 64 code */
    public static String base64Encode(byte[] bytes) {
        return Base64.encodeBase64String(bytes);
    }

    /** * base 64 decode * * @param base64Code * 待解碼的base 64 code * @return 解碼後的byte[] * @throws Exception */

     public static byte[] base64Decode(String base64Code) throws Exception{
         return StringUtil.isEmpty(base64Code) ? null : new  BASE64Decoder().decodeBuffer(base64Code); 
     }


    /** * AES加密 * * @param content * 待加密的內容 * @param encryptKey * 加密密鑰 * @return 加密後的byte[] * @throws Exception */
    public static byte[] aesEncryptToBytes(String content, String encryptKey)
            throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        cipher.init(Cipher.ENCRYPT_MODE,
                new SecretKeySpec(encryptKey.getBytes(), "AES"));

        return cipher.doFinal(content.getBytes("utf-8"));
    }

    /** * AES加密爲base 64 code * * @param content * 待加密的內容 * @param encryptKey * 加密密鑰 * @return 加密後的base 64 code * @throws Exception */
    public static String aesEncrypt(String content, String encryptKey)
            throws Exception {
        return base64Encode(aesEncryptToBytes(content, encryptKey));
    }

    /** * AES解密 * * @param encryptBytes * 待解密的byte[] * @param decryptKey * 解密密鑰 * @return 解密後的String * @throws Exception */
    public static String aesDecryptByBytes(byte[] encryptBytes,
            String decryptKey) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);

        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        cipher.init(Cipher.DECRYPT_MODE,
                new SecretKeySpec(decryptKey.getBytes(), "AES"));
        byte[] decryptBytes = cipher.doFinal(encryptBytes);

        return new String(decryptBytes);
    }

    /** * 將base 64 code AES解密 * * @param encryptStr * 待解密的base 64 code * @param decryptKey * 解密密鑰 * @return 解密後的string * @throws Exception */
    public static String aesDecrypt(String encryptStr, String decryptKey)
            throws Exception {
        return StringUtil.isEmpty(encryptStr) ? null : aesDecryptByBytes(
                base64Decode(encryptStr), decryptKey);
    }

public static void main(String[] args) throws Exception {
        String content = "123456";
        System.out.println("加密前:" + content);

        String encrypt = aesEncrypt(content, KEY);
        System.out.println("加密後:" + encrypt);

        String decrypt = aesDecrypt(encrypt, KEY);
        System.out.println("解密後:" + decrypt);
    }

五、小結

上面說到對稱加密和非對稱加密各有優缺點,前者效率高,但密鑰不安全;後者安全但加密解密時間較長。

實踐中比較經常使用的作法是,採用非對稱加密算法管理對稱算法的密鑰,而後用對稱加密算法加密數據,這樣咱們就集成了兩類加密算法的優勢,既實現了加密速度快的優勢,又實現了安全方便管理密鑰的優勢。

相關文章
相關標籤/搜索