java 加密技術(一)

java 加密技術(一)

OutLine

1. java安全介紹

2. Base64加密

3. 消息摘要–MD

4. SHA消息摘要


1 java安全介紹

1.1 java安全組成

  • JCA (java Cryptography Architecture) java加密體系結構
  • JCE (java Cryptography Extension) java加密擴展包
  • JSSE(java Secure Socket Extension) java安全套接字的擴展包
  • JAAS (java Authentication and Authentication Service) java鑑別與安全服務

1.2 相關java包

  • java.security :信息摘要相關的包
  • javax.crypto: 安全消息摘要,消息驗證碼
  • java.net.ssl : 安全套接字

1.3 擴展jar包

  • Bouncy Castle
  • Commons Codec (Apache提供; Base64,二進制,十六進制, 字符集編碼; Url編碼/解碼)

2 Base64加密

2.1 Base64介紹

嚴格意義上,Base64算法不算是加解密算法,主要是進行編碼工作,它可以將特殊字符編碼成非特殊字符.但是存儲空間會比加密之前的文件存儲空間多出1/3.

2.2 代碼實現

下面我們簡稱java提供的jar包實現叫做jdk實現,Bouncy Castle的實現叫做BC實現, Commons Codec實現叫做CC實現.

package screte;

import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;

public class Base64Test {
public static String src = "i am gc base64";

public static void main(String[] args) {
    //jdk對Base64編碼的支持
    System.out.println("=====jdkBase64編碼測試=====");
    jdkBase64();
    System.out.println("==========================");
    System.out.println("=====CommonsCodec的Base64實現=====");
    commonsCodecBase64();
    System.out.println("==========================");
    System.out.println("=====BouncyCastle的Base64實現=====");
    bouncyCastleBase64();
    System.out.println("==========================");

}
public static void jdkBase64(){
    //加密
    //獲取Encoder對象
    Encoder encoder = Base64.getEncoder(); 
    //用Encoder對象對字符串進行加密
    byte[] result = encoder.encode(src.getBytes());
    System.out.println("Base64編碼之後::"+new String(result));

    //解密
    //獲取Decoder對象
    Decoder decoder = Base64.getDecoder();
    //用Decoder對象對加密之後的文件進行解密
    result = decoder.decode(result);
    System.out.println("將result解碼之後:"+new String(result));
}
public static void commonsCodecBase64(){
    //commonscodec的方便之處在於直接用Base64.encoderBase64和Base64.decoderBase64進行加解密
    //加密
    byte[] result = org.apache.commons.codec.binary.Base64.encodeBase64(src.getBytes());
    System.out.println("Base64編碼之後:"+new String(result));
    //解密
    result = org.apache.commons.codec.binary.Base64.decodeBase64(result);
    System.out.println("Base64解密之後:"+new String(result));
}
public static void bouncyCastleBase64(){
     //加密
    byte[] result = org.bouncycastle.util.encoders.Base64.encode(src.getBytes());
    System.out.println("Base64編碼之後:"+new String(result));
    //解密
    result = org.bouncycastle.util.encoders.Base64.decode(result);
    System.out.println("Base64解密之後:"+new String(result));
}

//運行結果如下
/*
        =====jdkBase64編碼測試=====
        Base64編碼之後::aSBhbSBnYyBiYXNlNjQ=
        將result解碼之後:i am gc base64
        ==========================
        =====CommonsCodec的Base64實現=====
        Base64編碼之後:aSBhbSBnYyBiYXNlNjQ=
        Base64解密之後:i am gc base64
        ==========================
        =====BouncyCastle的Base64實現=====
        Base64編碼之後:aSBhbSBnYyBiYXNlNjQ=
        Base64解密之後:i am gc base64
        ==========================
 */
}

其實無論是bc或者cc都提供了static方法對Base64加解密進行很好的操作支持
不建議使用jdk提供的方法進行操作

2.3 Base64應用場景

base64其實不算是加密,可以說是一種轉碼.比如對一些特殊字符的處理; 對文件內容的轉碼等.


3 消息摘要–MD

3.1 介紹

MD家族包括MD2, MD4, MD5,他們生成的消息摘要都是128位. 安全性上的比較也是越來越安全.
JDK僅僅提供了MD2,MD5的實現.

3.2 代碼實現

package secret;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.MD4Digest;
import org.bouncycastle.crypto.digests.MD5Digest;

public class MDTest {
public static String src = "i am gc MD";
public static void main(String[] args) {
    System.out.println("=====jdk提供的MD5=====");
    jdkMD5();
    System.out.println("=====================");
    System.out.println("=====jdk提供的MD2=====");
    jdkMD2();
    System.out.println("=====================");
    System.out.println("=====BC提供的MD4=====");
    bcMD4();
    System.out.println("=====================");
    System.out.println("=====BC提供的MD5=====");
    bcMD5();
    System.out.println("=====================");
    System.out.println("=====CC提供的MD5=====");
    ccMD5();
    System.out.println("=====================");
    System.out.println("=====CC提供的MD2=====");
    ccMD2();
    System.out.println("=====================");


    //運行結果
    /*=====jdk提供的MD5=====
        信息摘要之後的src: 8a63f68d49d7acfa716602e9ab620394
        =====================
        =====jdk提供的MD2=====
        信息摘要之後的src: 2d2df5c04ceeaac31bdffb019ccd03c8
        =====================
        =====BC提供的MD4=====
        信息摘要之後的src: 5ff5d77df559660ed4ff19ac2f5e2e2a
        =====================
        =====BC提供的MD5=====
        信息摘要之後的src: 8a63f68d49d7acfa716602e9ab620394
        =====================
        =====CC提供的MD5=====
        信息摘要之後的src: 8a63f68d49d7acfa716602e9ab620394
        =====================
        =====CC提供的MD2=====
        信息摘要之後的src: 2d2df5c04ceeaac31bdffb019ccd03c8
        =====================
     */
}
/*
 * jdkMD5方法
 */
public static void jdkMD5(){
    try {
        //jdk提供的MessageDegest類 創建對象時候需要傳入參數,可以是MD5, MD2
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] result = md.digest(src.getBytes());
        //因爲digest方法返回的使一個byte數組,如果想輸出字符串,必須將byte數組轉化成16進制等,但是jdk並沒有提供這樣的方法,所以你可以選擇自己寫或者使用bc或cc提供的方法
        //現在我們藉助cc提供的方法
        //輸出32位16進制數
        System.out.println("信息摘要之後的src: "+Hex.encodeHexString(result));
    } catch (Exception e) {
        e.printStackTrace();
    }
}
/*
 * jdkMD2信息摘要
 */
public static void jdkMD2(){
    try {
        //jdk提供的MessageDegest類 創建對象時候需要傳入參數,可以是MD5, MD2
        MessageDigest md = MessageDigest.getInstance("MD2");
        byte[] result = md.digest(src.getBytes());
        //因爲digest方法返回的使一個byte數組,如果想輸出字符串,必須將byte數組轉化成16進制等,但是jdk並沒有提供這樣的方法,所以你可以選擇自己寫或者使用bc或cc提供的方法
        //現在我們藉助cc提供的方法
        //輸出32位16進制數
        System.out.println("信息摘要之後的src: "+Hex.encodeHexString(result));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

//bc實現MD4
public static void bcMD4(){
    //Digest是一個藉口,MD4Degist僅僅是一個實現類
    Digest digest = new MD4Digest();
    //進行摘要
    digest.update(src.getBytes(), 0 , src.getBytes().length);
    //獲取算法摘要出來的長度
    byte[] result = new byte[digest.getDigestSize()];
    //摘要的輸出到變量裏
    digest.doFinal(result, 0);
    //進行轉換輸出
    System.out.println("信息摘要之後的src: "+Hex.encodeHexString(result));
}

/*
 * bc實現MD5
 * 跟bc實現MD4相似,在此不再加註釋
 */
public static void bcMD5(){
    Digest digest = new MD5Digest();
    digest.update(src.getBytes(), 0, src.getBytes().length);
    byte[] result = new byte[digest.getDigestSize()];
    digest.doFinal(result, 0);
    System.out.println("信息摘要之後的src: "+Hex.encodeHexString(result));
}

/*
 * cc對MD5的實現
 */
public static void ccMD5(){
    //說實話.CC提供的DegistUtils工具類對信息摘要的實現真的是簡單至極
    String result = DigestUtils.md5Hex(src.getBytes());
    System.out.println("信息摘要之後的src: "+result);
}
/*
 * cc對MD2的實現
 */
public static void ccMD2(){
    //說實話.CC提供的DegistUtils工具類對信息摘要的實現真的是簡單至極
    //但是CC做了個偷工減料的地方,CC僅僅是對jdk中MessageDegist的簡單包裝,所以CC中支持md4的實現
    String result = DigestUtils.md2Hex(src.getBytes());
    System.out.println("信息摘要之後的src: "+result);
}
}

3.3 MD5的應用

可以對用戶註冊的註冊密碼進行MD5消息摘要處理,然後再存數據庫.當用戶登陸時候,對用戶輸入的密碼再次進行MD5,之後在與數據庫中的MD5碼進行比對.這樣能夠很好的對密碼進行保護.但是要記住:MD5僅僅是單向的,不可逆的.


4 SHA消息摘要

4.1 介紹

SHA是一種安全散列算法,也是固定長度的消息摘要. 包括:SHA-1, SHA-2(SHA-224,SHA-256, SHA-384, SHA-512)
她是在MD4演變出來的

SHA-224等等後面的數字都使摘要的長度,比如SHA-224摘要出來的長度就是224位
這裏面只有SHA-224 jdk沒有提供實現

4,2 代碼實現

package secret;

import java.security.MessageDigest;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.digests.SHA224Digest;

public class SHATest {
    public static String src = "i am gc SHA";

    public static void main(String[] args) {
        System.out.println("=====jdk提供的SHA1=====");
        jdkSHA1();
        System.out.println("=====================");
        System.out.println("=====bc提供的SHA1=====");
        bcSHA1();
        System.out.println("=====================");
        System.out.println("=====cc提供的SHA1=====");
        ccSHA1();
        System.out.println("=====================");
        System.out.println("=====bc提供的SHA-256=====");
        jdkSHA256();
        System.out.println("=====================");
        System.out.println("=====bc提供的SHA224=====");
        bcSHA224();
        System.out.println("=====================");

        //運行結果
        /*
            =====jdk提供的SHA1=====
            消息摘要之後:02470457fc2738acb459ee266dd66976324ee5b8
            =====================
            =====bc提供的SHA1=====
            消息摘要之後:02470457fc2738acb459ee266dd66976324ee5b8
            =====================
            =====cc提供的SHA1=====
            消息摘要之後:02470457fc2738acb459ee266dd66976324ee5b8
            =====================
            =====bc提供的SHA-256=====
            消息摘要之後:dd855bed3dce767ad1ce3f051b8d6fba12a0c00fe2feaa142ca37f2ae88fbca3
            =====================
            =====bc提供的SHA224=====
            消息摘要之後:f2a63bc30d2d8fcebc9b5aa4f660b6f422328731588346dbd55a1a2f
            =====================
         */
    }

    /*
     * jdk對SHA算法實現
     */
    public static void jdkSHA1() {
        try {
            byte[] result;
            MessageDigest digest = MessageDigest.getInstance("SHA1");
            result = digest.digest(src.getBytes());
            System.out.println("消息摘要之後:" + Hex.encodeHexString(result));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * bc實現SHA1
     */
    public static void bcSHA1() {
        // 因爲都是用Digest接口裏的方法,在MD代碼裏已經註釋了,這裏就不再敘述
        Digest digest = new SHA1Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length);
        byte[] result = new byte[digest.getDigestSize()];
        digest.doFinal(result, 0);
        System.out.println("消息摘要之後:" + Hex.encodeHexString(result));
    }

    /*
     * jdk對SHA-256的支持
     */
    public static void jdkSHA256() {
        try {
            byte[] result;
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            result = digest.digest(src.getBytes());
            System.out.println("消息摘要之後:" + Hex.encodeHexString(result));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * bc實現SHA224
     */
    public static void bcSHA224() {
        // 因爲都是用Digest接口裏的方法,在MD代碼裏已經註釋了,這裏就不再敘述
        Digest digest = new SHA224Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length);
        byte[] result = new byte[digest.getDigestSize()];
        digest.doFinal(result, 0);
        System.out.println("消息摘要之後:" + Hex.encodeHexString(result));
    }

    /*
     * cc對SHA1的實現
     * 其實也是對jdk的包裝
     */
    public static void ccSHA1(){
        String result = DigestUtils.sha1Hex(src.getBytes());
        System.out.println("消息摘要之後:" +result);
    }
    /*
     * 其餘的SHA實現都與上面的方法相同
     */
}

4.3 應用

一些證書中的指紋摘要
對發送的消息進行驗證,消息是否被篡改


  • 文章中避免不了錯誤的出現,如果有讀者發現文章中的錯誤,或者有疑問的地方,請留言/Email To Gc
  • 請轉發OR複製的同學,標註出處,尊重作者勞動成果,謝謝親

博客地址遷移至 int32.me

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章