現代加密體系的各種加密方式


一、現代加密體系的概覽

二、加密算法介紹

  關於編碼和解碼,正常的編碼是指將字符串轉化為特定的編碼的二進制,例如,java在內存中使用unicode碼,在向外發送數據時,使用不同的編碼會將同樣的字符串編碼成不同的二進制碼,如utf-8或gbk。二解碼,則是將二進制碼根據指定的編碼方式,轉化成字符串。

  base64編碼,跟常用的編碼方式是相反的運作,它的編碼,是將二進制碼轉化成字符串;解碼則是將字符串轉化成二進制碼。

1、base64位加密

  base64中64是指2的6次方,在編碼時,會使用6位二進制碼表示一個字符。

  base64編碼表:

 

 

如圖實例:字符串one使用ascii編碼后的二進制碼,在base64編碼后是b25l。

base64編碼,使用6位二進制進行編碼,而一個字節有8位二進制。為了能對所有的字節進行編碼,且不造成更多的base64字符。采用8和6的最小公倍數,24位二進制位一個單位,也就是說base64編碼后的二進制個數是24的整倍數。

 

當有空出的字節數時:

對不能填滿6位的二進制補0,完全空出的6位二進制用=代替。如下圖:onex的base64編碼是b25lfA==

base64加密實現——java:

在java的加密體系中,常規加密有三種支持,jdk自帶的相關包,bouncy Castle對jdk的補充提供更強的加密強度,Commons Codec是apache提供的安全支持,它一般只是對jdk實現的擴展,比如jdk實現md2和md5算法,Commons Codec也只有md2和md5的實現。實際使用中可以根據需要選擇bouncy Castle或Commons Codec。

package com.tsinkai.ettp.practice;

import java.io.IOException;

import org.apache.commons.codec.binary.Base64;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;    

public class Base64Pra {
    
    private static String src = "hello world!";
    
    public static void main(String[] args) {
        jdkBase64();
        commonsCodesBase64();
        bouncyCastleBase64();
    }
    
    /**
     * jdk自帶的base64編碼,需要在eclipse里打開相應的包,jdk內部使用,不建議使用。
     */
    public static void jdkBase64() {
        
        try {
            //編碼
            BASE64Encoder  encoder = new BASE64Encoder();
            String encodeStr = encoder.encode(src.getBytes());
            System.out.println("jdk encode:" + encodeStr);
            //解碼
            BASE64Decoder decoder = new BASE64Decoder();
            System.out.println("jdk decode:"+new String(decoder.decodeBuffer(encodeStr)));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * commonsCodes中的base64編碼
     */
    public static void commonsCodesBase64() {
        //編碼
         byte[] encodeBytes = Base64.encodeBase64(src.getBytes());
         String baseStr = Base64.encodeBase64String(src.getBytes());
         System.out.println("cc encode:" + new String(encodeBytes)+"||"+baseStr);
         
         //解碼
         byte[] decodeBytes = Base64.decodeBase64(encodeBytes);
         System.out.println("cc decode:" + new String(decodeBytes));
    }
    
    /**
     * bouncyCastle中的base64編碼
     */
    public static void bouncyCastleBase64() {
        //編碼
        byte[] encodeBatys =  org.bouncycastle.util.encoders.Base64.encode(src.getBytes());
        System.out.println("bc encode:" + new String(encodeBatys));
        
        //解碼
        System.out.println("bc decode:" + new String(org.bouncycastle.util.encoders.Base64.decode(encodeBatys)));
    }
}

 2、消息摘要算法

  消息摘要算法是一種驗證消息完整性的算法,它通過一個單向hash加密函數,把字符串加密成固定長度的bit位,不同的字符串產生的輸出不同,同樣的字符串輸出一定相同。同時它是單向加密,不能解密。但是,消息摘要有一定的碰撞率,即不同的明文可能產生相同的密文。

  在驗證消息完整性時,只需要將明文字符串使用相同的摘要算法加密,跟接收到的密文進行對比,即可驗證消息摘要的完整性。它是數字簽名的核心算法。

  MD5和SHA1的算法已經被破解。

消息摘要的三類實現:

MD(Message Digest)

SHA(Secure Hash Algorithm)

MAC(Message Authentication Code)

a、MD算法

 

 

 MD算法的實現——java:

package com.tsinkai.ettp.practice;

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

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

public class MDPra {
    
    private static String src = "hello world";
    
    public static void main(String[] args) {
        jdkMD2();
        jdkMD5();
        
        bcMD2();
        bcMD4();
        bcMD5ForProvider();
        bcMD4ForProvider();
        
        ccMD2();
        ccMD5();
    }
    
    //JDK實現MD2
    public static void jdkMD2() {
        try {
            MessageDigest md = MessageDigest.getInstance("MD2");
            byte[] md2bytes = md.digest(src.getBytes());
            //字節數組輸出要先轉成16進制,可以借助HEX類轉換
            System.out.println("JDK MD2:" + Hex.encodeHexString(md2bytes));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
    
    //JDK實現MD5
    public static void jdkMD5() {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] md5bytes = md.digest(src.getBytes());
            //字節數組輸出要先轉成16進制,可以借助HEX類轉換
            System.out.println("JDK MD5:" + Hex.encodeHexString(md5bytes));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
    
    //Bouncy Castle實現MD2
    public static void bcMD2() {
        Digest digest = new MD2Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length); 
        byte[] MD2Bytes = new byte[digest.getDigestSize()];
        digest.doFinal(MD2Bytes, 0);
        System.out.println("BC MD2:" + org.bouncycastle.util.encoders.Hex.toHexString(MD2Bytes));
    }
    
    //Bouncy Castle實現MD4
    public static void bcMD4() {
        Digest digest = new MD4Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length);
        byte[] MD4Bytes = new byte[digest.getDigestSize()];
        digest.doFinal(MD4Bytes, 0);
        System.out.println("BC MD4:" + org.bouncycastle.util.encoders.Hex.toHexString(MD4Bytes));
    }
    //通過設置provider,使用jdk的包調用bouncyCastle的實現,MD5
    //該種方式的provider是sun,若是使用該方式調用MD4,則實現則是BC
    public static void bcMD5ForProvider() {
        
        try {
            Security.addProvider(new BouncyCastleProvider());
            MessageDigest md = MessageDigest.getInstance("MD5");
            System.err.println("JDKforProvider MD5:"+md.getProvider());
            byte[] md5bytes = md.digest(src.getBytes());
            //字節數組輸出要先轉成16進制,可以借助HEX類轉換
            System.out.println("BC MD5ForProvider:" + Hex.encodeHexString(md5bytes));
            
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
    //通過設置provider,使用jdk的包調用bouncyCastle的實現,MD4
    public static void bcMD4ForProvider() {
            
            try {
                Security.addProvider(new BouncyCastleProvider());
                MessageDigest md = MessageDigest.getInstance("MD4");
                System.err.println("JDKforProvider MD4:"+md.getProvider());
                byte[] md5bytes = md.digest(src.getBytes());
                //字節數組輸出要先轉成16進制,可以借助HEX類轉換
                System.out.println("BC MD4ForProvider:" + Hex.encodeHexString(md5bytes));
                
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
    //Commons Codes實現MD2
    public static void ccMD2() {
        System.out.println("CC MD2:"+ DigestUtils.md2Hex(src.getBytes()));
    }
    
    //Commons Codes實現MD5
    public static void ccMD5() {
        System.out.println("CC MD5:"+ DigestUtils.md5Hex(src.getBytes()));
    }
}

 b.SHA算法

  相比於md5,相近的字符串加密后的密文區別很大。

  sha共有5中算法,一般般sha-1外的算法稱為sha-2

算法 摘要長度 實現方
SHA-1 160 JDK、CC、BC
SHA-224 224 BC
SHA-256 256 JDK、CC、BC
SHA-384 384 JDK、CC、BC
SHA-512 512 JDK、CC、BC
package com.tsinkai.ettp.practice;

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

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;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.SHA384Digest;
import org.bouncycastle.crypto.digests.SHA3Digest;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.jcajce.provider.digest.SHA3;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class SHAPra {
    private static String src = "hello world!";
    
    public static void main(String[] args) {
        jdkSHA1();
        bcSHA();
        ccSha();
    }
    
    /**
     * jdk實現方式
     */
    public static void jdkSHA1() {
        try {
            //getInstance("SHA-1")該參數可填列表:MD2, MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512
            //填寫SHA等同於SHA-1
            MessageDigest md = MessageDigest.getInstance("SHA");//默認調用jdk實現:sun.security.provider.SHA
//            MessageDigest md = MessageDigest.getInstance("SHA224");//默認調用bc實現:org.bouncycastle.jcajce.provider.digest.SHA224
//            MessageDigest md = MessageDigest.getInstance("SHA256");//默認調用bc實現:org.bouncycastle.jcajce.provider.digest.SHA256
//            MessageDigest md = MessageDigest.getInstance("SHA384");//默認調用bc實現:org.bouncycastle.jcajce.provider.digest.SHA384
//            MessageDigest md = MessageDigest.getInstance("SHA512");//默認調用bc實現:org.bouncycastle.jcajce.provider.digest.SHA512
//            md.update(src.getBytes());//使用update后后續方法不需要再添加字節數組
            System.out.println("jdk SHA-1:" + Hex.encodeHexString(md.digest(src.getBytes())));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        
    }
    
    /**
     * Bouncy Castle 實現方式
     */
    public static void bcSHA() {
        Digest digest = new SHA1Digest();
//        Digest digest = new SHA224Digest();
//        Digest digest = new SHA256Digest();
//        Digest digest = new SHA384Digest();
//        Digest digest = new SHA512Digest();
        digest.update(src.getBytes(),0,src.getBytes().length);
        System.out.println(digest.getDigestSize());
        byte[] sha1Bytes = new byte[digest.getDigestSize()];
        digest.doFinal(sha1Bytes, 0);
        System.out.println("bc sha-1:" + org.bouncycastle.util.encoders.Hex.toHexString(sha1Bytes));
    }
    
    /**
     * Commons condc實現方式
     */
    public static void ccSha() {
        System.out.println("cc sha1:" + DigestUtils.sha1Hex(src));//改方法底層仍是調用MessageDigest.getInstance("SHA-1");
        System.out.println("CC SHA256:"+DigestUtils.sha256Hex(src));
        System.out.println("CC SHA384:"+DigestUtils.sha384Hex(src));
        System.out.println("CC SHA512:"+DigestUtils.sha512Hex(src));
        
    }
}

 c、mac——帶有秘鑰的摘要算法

package com.tsinkai.ettp.practice;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;

public class HMacPra {
    
    public static String src = "hello world";
    
    public static void main(String[] args) {
        jdkHMacMD5();
        bcHMacMD5();
    }
    
    public static void jdkHMacMD5() {
        try {
            //獲得jdk默認實現的秘鑰
            KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] key = secretKey.getEncoded();
            //可以自定義生成,必須是偶數位
//            byte[] key = Hex.decodeHex(new char[] {'a','a','a','a','a','a','a','a'});
            
            
            SecretKey restreSecretKey = new SecretKeySpec(key, "HmacMD5");//該步驟是為了生成一個符合HMacMD5的秘鑰
            Mac mac = Mac.getInstance(restreSecretKey.getAlgorithm());
            mac.init(restreSecretKey);
            byte[] hmacMD5Bytes = mac.doFinal(src.getBytes());
            System.out.println("jdk hmacMD5:"+Hex.encodeHexString(hmacMD5Bytes));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void bcHMacMD5() {
        HMac hmac = new HMac(new MD5Digest());
        hmac.init(new KeyParameter(org.bouncycastle.util.encoders.Hex.decode("123456")));
        hmac.update(src.getBytes(),0,src.getBytes().length);
        
        byte[] hMacMD5bytes = new byte[hmac.getMacSize()];
        hmac.doFinal(hMacMD5bytes, 0);
        
        System.out.println("bc hmacMD5:" + Hex.encodeHexString(hMacMD5bytes));
    }
}

3、對稱加密算法

  加密和解密使用相同的秘鑰。

 a、DES加密

  

package com.tsinkai.ettp.practice;

import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class DESPra {
    public static String src = "hello";
    public static void main(String[] args) {
        jdkDES();
        bcDES();
    }
    
    public static void jdkDES() {
        try {
            //生成key
            KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
            keyGenerator.init(56);
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] key = secretKey.getEncoded();
            
            //轉化key
            DESKeySpec desKeySpec = new DESKeySpec(key);
            SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
            SecretKey convertSecretKey = factory.generateSecret(desKeySpec);
            
            //加密
            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("jdk DES encrypt:" + Base64.encodeBase64String(result));
            
            //解密
            cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
            result = cipher.doFinal(result);
            System.out.println("jdk des decrypy:" + new String(result));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }
    
    public static void bcDES() {
        //2種方式1、使用setprovider方式,2、使用bc原生的方式

        try {
            Security.addProvider(new BouncyCastleProvider());
            //生成key
            KeyGenerator keyGenerator = KeyGenerator.getInstance("DES","BC");//通過參數指定使用provider
            System.out.println(keyGenerator.getProvider());
            keyGenerator.init(56);
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] key = secretKey.getEncoded();
            
            //轉化key
            DESKeySpec desKeySpec = new DESKeySpec(key);
            SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
            SecretKey convertSecretKey = factory.generateSecret(desKeySpec);
            
            //加密
            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("bc DES encrypt:" + Base64.encodeBase64String(result));
            
            //解密
            cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
            result = cipher.doFinal(result);
            System.out.println("bc des decrypy:" + new String(result));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    
    }
}

b、AES加密

  

package com.tsinkai.ettp.practice;

import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class AESPra {
    public static String src = "hello";
    
    public static void main(String[] args) {
        jdkAES();
    }
    
    public static void jdkAES() {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(128);
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] keyBytes = secretKey.getEncoded();
            System.out.println("key0:" + Base64.encodeBase64String(keyBytes));
            //key轉化
            Key key = new SecretKeySpec(keyBytes, "AES");
            System.out.println("key:" + Base64.encodeBase64String(key.getEncoded()));
            //加密
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("加:" + result.length);
            System.out.println("jdk AES encrypt:"+Base64.encodeBase64String(result));
            
            //解密
            cipher.init(Cipher.DECRYPT_MODE, key);
            System.out.println("解:"+Base64.decodeBase64(Base64.encodeBase64String(result)).length);
            result = cipher.doFinal(Base64.decodeBase64(Base64.encodeBase64String(result)));
            System.out.println("jdk AES decrypt:" + new String(result));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM