Java加密算法

JDK中帶有部分加密算法的實現類,主要的是java.security和javax.crypto包下的類,還能夠使用Bouncy Castle(豐富JDK中加密算法的不足)jar包是:bcprov-jdk15on-1.57.jar和Commons Codec(簡化JDK中加密的操做)jar包是:commons-codec-1.10.jarhtml

Base64

Base64用於網絡中傳輸的數據進行編碼,嚴格意義上屬於編碼的格式,有64個字符的對應的編碼,Base64就是將內容按照該格式進行編碼。能夠對數據編碼和解碼,是可逆的,安全度較低,不過,也能夠做爲最基礎最簡單的加密算法用於加密要求較弱的狀況java

Base64能夠使用JDk中自帶的類實現,還能夠使用Bouncy Castle(簡稱bc)或Commons Codec(簡稱cc)實現算法

加密數據:apache

private static String src="Hello Base64";

導入的類:安全

import java.io.IOException;

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

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

JDk實現主要使用用BASE64Encoder和BASE64Decoder類的方法(注意在Eclipse中使用JDK的Base64可能會出現找不到的問題,是由於Base64Encoder並不屬於JDK標準庫範疇,可是又包含在了JDK中,須要咱們手動導入\jre\lib目錄下的rt.jar包便可):網絡

    public static void jdkBase64(){
        try {
            BASE64Encoder encoder=new BASE64Encoder();
            String encode = encoder.encode(src.getBytes());
            System.out.println("encode: "+encode);
            
            BASE64Decoder decoder=new BASE64Decoder();
            String decode=new String(decoder.decodeBuffer(encode));
            System.out.println("decode: "+decode);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

bc實現主要是用Base64類的方法:oracle

    public static void bouncybastleBase64(){
        byte[] encode = org.bouncycastle.util.encoders.Base64.encode(src.getBytes());
        System.out.println("encode: "+new String(encode));
        
        byte[] decode = org.bouncycastle.util.encoders.Base64.decode(encode);
        System.out.println("decode: "+new String(decode));
    }

cc實現也是用Base64類,不過與bc的是不同的,不一樣包中的類,只是名字同樣:dom

    public static void commonscodecBase64(){
        byte[] encode=Base64.encodeBase64(src.getBytes());
        System.out.println("encode: "+new String(encode));  //須要轉化爲String
        
        byte[] decode = Base64.decodeBase64(encode);
        System.out.println("decode: "+new String(decode));
    }

摘要算法

摘要算法主要分爲MD,SHA和Hmac算法,摘要算法實際上是用於效驗數據完整性的,咱們在下載某些文件時,會有MD5和SHA1值提供咱們效驗下載的文件是否完整,能夠用於根據數據生成其惟一的摘要值,沒法根據摘要值知道原數據,屬於不可逆的ide

MD:

加密數據:函數

private static String src="Hello MD";

導入的類:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
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;

JDK有MD2和MD5的實現,使用的是MessageDigest類,而沒有MD4的實現:

    public static void jdkMD5(){
        try {
            MessageDigest md=MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(src.getBytes());
            System.out.println("JDK MD5: "+Hex.encodeHexString(digest));           //使用的是cc中帶的Hex須要轉換爲十六進制
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        
    }
    
    public static void jdkMD2(){
        try {
            MessageDigest md=MessageDigest.getInstance("MD2");
            byte[] digest = md.digest(src.getBytes());
            System.out.println("JDK MD2: "+Hex.encodeHexString(digest));   
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        
    }

而bc這三種都有,使用的是Digest 類:

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的方式,將sun的改成bc的provider)
        try {
            Security.addProvider(new BouncyCastleProvider());  //經過添加provider的方式
            MessageDigest md=MessageDigest.getInstance("MD4");
            byte[] digest = md.digest(src.getBytes());
            System.out.println("BC MD4: "+Hex.encodeHexString(digest));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
    
    public static void bcMD5(){
        Digest digest=new MD5Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length);
        byte[] md4Bytes=new byte[digest.getDigestSize()];
        digest.doFinal(md4Bytes, 0);
        System.out.println("BC MD5: "+org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
    }
    
    public static void bcMD2(){
        Digest digest=new MD2Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length);
        byte[] md4Bytes=new byte[digest.getDigestSize()];
        digest.doFinal(md4Bytes, 0);
        System.out.println("BC MD2: "+org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
    }

cc和JDK是同樣的,畢竟是對JDK加密的簡化,直接使用DigestUtils中的方法,很簡單,並且前兩種方法還須要將MD值轉換爲十六進制,cc直接就幫咱們轉了:

    public static void ccMD2(){        //有方法直接就能夠轉換十六進制
        System.out.println("CC MD2: "+DigestUtils.md2Hex(src.getBytes()));
    }
    
    public static void ccMd5(){
        System.out.println("CC MD5: "+DigestUtils.md5Hex(src.getBytes()));
    }

SHA:

這裏只是使用SHA-1,其餘類型相似

加密數據:

private static String src="Hello SHA";

要導入的類:

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.SHA1Digest;import sun.security.provider.SHA;

JDK實現方式(一樣是使用MessageDigest):

    public static void jdkSHA1(){
        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("SHA");
            digest.update(src.getBytes());
            System.out.println("JDK SHA1: "+Hex.encodeHexString(digest.digest()));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

bc的實現方式(一樣是Digest 類):

    public static void mcSHA1(){
        Digest digest=new SHA1Digest();
        digest.update(src.getBytes(),0,src.getBytes().length);
        byte[] sha1Byte1=new byte[digest.getDigestSize()];
        digest.doFinal(sha1Byte1, 0);
        System.out.println("MC SHA1:"+org.bouncycastle.util.encoders.Hex.toHexString(sha1Byte1));
    }

cc的實現方式:

    public static void ccsha(){
        System.out.println("CC sha1:"+DigestUtils.sha1Hex(src));
    }

Hmac(含有密鑰的摘要算法,也有簡稱mac,密鑰不一樣摘要也不一樣):

要加密的數據:

private static String src="Hello HMAC";

要導入的類:

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;

JDK的實現方式:

    public static void jdkHmacMD5(){
        try {
            KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacMD5");  //初始化KeyGenerator
            SecretKey secretKey=keyGenerator.generateKey(); //產生密鑰
            //byte[] key=secretKey.getEncoded();     //得到密鑰(默認生成)
            
            byte[] key=Hex.decodeHex(new char[]{'a','a','a','a','a','a','a','a','a','a'});  //手動生成密鑰(十位)
            
            SecretKey secretKey2=new SecretKeySpec(key, "HmacMD5"); //還原密鑰
            Mac mac=Mac.getInstance(secretKey2.getAlgorithm());  //實例化mac
            //初始化mac
            mac.init(secretKey2);
            byte[] hmacMD5Bytes=mac.doFinal(src.getBytes());
            System.out.println("jdk hmacMD5: "+Hex.encodeHexString(hmacMD5Bytes));
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }

bc的實現方式:

    public static void bcHmacMd5(){
        HMac hMac=new HMac(new MD5Digest());
        hMac.init(new KeyParameter(org.bouncycastle.util.encoders.Hex.decode("aaaaaaaaaa")));  //須要十位密鑰
        hMac.update(src.getBytes(),0,src.getBytes().length);
        
        byte[] hmacMD5=new byte[hMac.getMacSize()];
        hMac.doFinal(hmacMD5, 0);
        System.out.println("bc hmacMD5: "+org.bouncycastle.util.encoders.Hex.toHexString(hmacMD5));

    }

對稱加密算法

嚴格意義上的加密算法,分爲對稱和非對稱加密算法,所謂對稱是說發送方和接收方的密鑰是同樣的,而非對稱咱們後面再說。由於密鑰同樣因此安全性跟非對稱比較來講就不太安全了

對稱加密算法主要分爲:DES , 3DES(3重DES) , AES(想要替代DES)  , PBE(基於口令的對稱算法)

DES:

加密數據 :

private static String src="Hello DES";

導入的類:

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.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

JDK的實現方式:

    public static void jdkDES(){
        try {
            //生成key
            KeyGenerator keyGenerator=KeyGenerator.getInstance("DES");
            keyGenerator.init(56);      //指定key長度,同時也是密鑰長度(56位)
            SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料
            byte[] key = secretKey.getEncoded();  //生成key
            
            //key轉換成密鑰
            DESKeySpec desKeySpec=new DESKeySpec(key);
            SecretKeyFactory factory=SecretKeyFactory.getInstance("DES");
            SecretKey key2 = factory.generateSecret(desKeySpec);      //轉換後的密鑰
            
            //加密
            Cipher cipher=Cipher.getInstance("DES/ECB/PKCS5Padding");  //算法類型/工做方式/填充方式
            cipher.init(Cipher.ENCRYPT_MODE, key2);   //指定爲加密模式
            byte[] result=cipher.doFinal(src.getBytes());
            System.out.println("jdkDES加密: "+Hex.encodeHexString(result));  //轉換爲十六進制
            
            //解密
            cipher.init(Cipher.DECRYPT_MODE,key2);  //相同密鑰,指定爲解密模式
            result = cipher.doFinal(result);   //根據加密內容解密
            System.out.println("jdkDES解密: "+new String(result));  //轉換字符串
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

bc的實現方式,爲了和JDK的實現方式一致(不想記太多類),採用了添加provider的方式 :

public static void bcDES(){
        try {
            //經過改變provider的方式
            Security.addProvider(new BouncyCastleProvider());
            
            //生成key,使用bc須要在後面指定"BC"
            KeyGenerator keyGenerator=KeyGenerator.getInstance("DES","BC");
            
            keyGenerator.getProvider();
            
            keyGenerator.init(56);      //指定key長度,同時也是密鑰長度
            SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料
            byte[] key = secretKey.getEncoded();  //生成key
            
            //key轉換成密鑰
            DESKeySpec desKeySpec=new DESKeySpec(key);
            SecretKeyFactory factory=SecretKeyFactory.getInstance("DES");
            SecretKey key2 = factory.generateSecret(desKeySpec);      //轉換後的密鑰
            
            //加密
            Cipher cipher=Cipher.getInstance("DES/ECB/PKCS5Padding");  //算法類型/工做方式/填充方式
            cipher.init(Cipher.ENCRYPT_MODE, key2);
            byte[] result=cipher.doFinal(src.getBytes());
            System.out.println("bcDES加密: "+Hex.encodeHexString(result));  //轉換爲十六進制
            
            //解密
            cipher.init(Cipher.DECRYPT_MODE,key2);  //相同密鑰
            result = cipher.doFinal(result);   //根據加密內容解密
            System.out.println("bcDES解密: "+new String(result));  //轉換字符串
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

就是記得添加bc的provider,和KeyGenerator.getInstance的參數("DES","BC")

3DES(使用DESede做爲標識):

要加密的數據:

private static String src="Hello 3DES";

導入的類:

import java.security.SecureRandom;
import java.security.Security;

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

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

JDK的實現方法:

    public static void jdkDES(){
        try {
            //生成key
            KeyGenerator keyGenerator=KeyGenerator.getInstance("DESede");
            //keyGenerator.init(112);      //3DES須要112 or 168位
            keyGenerator.init(new SecureRandom());   //或者使用這種方式默認長度,無需指定長度
            SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料
            byte[] key = secretKey.getEncoded();  //生成key
            
            //key轉換成密鑰
            DESedeKeySpec desKeySpec=new DESedeKeySpec(key);
            SecretKeyFactory factory=SecretKeyFactory.getInstance("DESede");
            SecretKey key2 = factory.generateSecret(desKeySpec);      //轉換後的密鑰
            
            //加密
            Cipher cipher=Cipher.getInstance("DESede/ECB/PKCS5Padding");  //算法類型/工做方式/填充方式
            cipher.init(Cipher.ENCRYPT_MODE, key2);   //指定爲加密模式
            byte[] result=cipher.doFinal(src.getBytes());
            System.out.println("jdk3DES加密: "+Hex.encodeHexString(result));  //轉換爲十六進制
            
            //解密
            cipher.init(Cipher.DECRYPT_MODE,key2);  //相同密鑰,指定爲解密模式
            result = cipher.doFinal(result);   //根據加密內容解密
            System.out.println("jdk3DES解密: "+new String(result));  //轉換字符串
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

bc的實現方式:

public static void bcDES(){
        try {
            //經過改變provider的方式,其餘操做同樣
            Security.addProvider(new BouncyCastleProvider());
            
            //生成key
            KeyGenerator keyGenerator=KeyGenerator.getInstance("DESede");
            keyGenerator.init(new SecureRandom());
            SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料
            byte[] key = secretKey.getEncoded();  //生成key
            
            //key轉換成密鑰
            DESedeKeySpec desKeySpec=new DESedeKeySpec(key);
            SecretKeyFactory factory=SecretKeyFactory.getInstance("DESede");
            SecretKey key2 = factory.generateSecret(desKeySpec);      //轉換後的密鑰
            
            //加密
            Cipher cipher=Cipher.getInstance("DESede/ECB/PKCS5Padding");  //算法類型/工做方式/填充方式
            cipher.init(Cipher.ENCRYPT_MODE, key2);   //指定爲加密模式
            byte[] result=cipher.doFinal(src.getBytes());
            System.out.println("jdk3DES加密: "+Hex.encodeHexString(result));  //轉換爲十六進制
            
            //解密
            cipher.init(Cipher.DECRYPT_MODE,key2);  //相同密鑰,指定爲解密模式
            result = cipher.doFinal(result);   //根據加密內容解密
            System.out.println("jdk3DES解密: "+new String(result));  //轉換字符串
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

AES:

 

基本實現和DES相似,只不過在實現該算法的時候,設置密鑰長度大於128會出現錯誤:Illegal key size or default parameters,這是由於美國的出口限制,Sun經過權限文件(local_policy.jar、US_export_policy.jar)作了相應限制,Oracle在其官方網站上提供了無政策限制權限文件(Unlimited Strength Jurisdiction Policy Files),咱們只須要將其部署在JRE環境中,就能夠解決限制問題

JDK8的無政策限制權限文件(http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html)

將下載的local_policy.jar和US_export_policy.jar替換JDK的JRE環境中,或者是JRE環境中上述兩個jar文件便可

非對稱的ELGamal加密算法算法也有該問題,解決方法相同

加密的數據:

private static String src="Hello AES";

導入的類:

import java.security.Key;
import java.security.SecureRandom;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

JDK的實現:

public static void jdkAES(){
        try {
            //生成key
            KeyGenerator keyGenerator=KeyGenerator.getInstance("AES");
            keyGenerator.init(new SecureRandom());
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] key1 = secretKey.getEncoded();
            
            //key轉換爲密鑰
            Key key2 = new SecretKeySpec(key1, "AES");
            
            //加密
            Cipher cipher=Cipher.getInstance("AES/ECB/PKCS5padding");
            cipher.init(Cipher.ENCRYPT_MODE, key2);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("jdkAES加密: "+Hex.encodeHexString(result));  //轉換爲十六進制
            
            //解密
            cipher.init(Cipher.DECRYPT_MODE, key2);
            result = cipher.doFinal(result);
            System.out.println("jdkAES解密: "+new String(result));  //轉換字符串
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

bc的實現(一樣使用了添加provider的作法):

public static void bcAES(){
        try {
            Security.addProvider(new BouncyCastleProvider());
            
            //生成key
            KeyGenerator keyGenerator=KeyGenerator.getInstance("AES", "BC");
            keyGenerator.getProvider();
            keyGenerator.init(128);      //顯示指定密鑰長度
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] key1 = secretKey.getEncoded();
            
            //key轉換爲密鑰
            Key key2 = new SecretKeySpec(key1, "AES");
            
            //加密
            Cipher cipher=Cipher.getInstance("AES/ECB/PKCS5padding");
            cipher.init(Cipher.ENCRYPT_MODE, key2);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("jdkAES加密: "+Hex.encodeHexString(result));  //轉換爲十六進制
            
            //解密
            cipher.init(Cipher.DECRYPT_MODE, key2);
            result = cipher.doFinal(result);
            System.out.println("jdkAES解密: "+new String(result));  //轉換字符串
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

PBE:

基於口令的對稱加密算法(它實際上是對以前的算法的包裝,好比說MD5和DES,我這裏就是的是對MD5和DES包裝的PBE算法,還有其餘類型的PBE),口令就是咱們俗話說的密碼,PBE中有一個salt(鹽)的概念,鹽就是干擾碼

加密的數據:

private static String src="Hello PBE";

導入的類:

import java.security.Key;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import org.apache.commons.codec.binary.Base64;

JDk的實現:

public static void jdkPBE(){
        try {
            //初始化鹽
            SecureRandom random=new SecureRandom();
            byte[] salt = random.generateSeed(8);   //指定爲8位的鹽 (鹽就是干擾碼,經過添加干擾碼增長安全)
            
            //口令和密鑰
            String password="lynu";              //口令
            PBEKeySpec pbeKeySpec=new PBEKeySpec(password.toCharArray());
            SecretKeyFactory factory=SecretKeyFactory.getInstance("PBEWITHMD5andDES");
            Key key=factory.generateSecret(pbeKeySpec);  //密鑰
            
            //加密
            PBEParameterSpec pbeParameterSpec=new PBEParameterSpec(salt, 100);   //參數規範,第一個參數是鹽,第二個是迭代次數(通過散列函數屢次迭代)
            Cipher cipher=Cipher.getInstance("PBEWITHMD5andDES");
            cipher.init(Cipher.ENCRYPT_MODE, key,pbeParameterSpec);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("jdk PBE加密: "+Base64.encodeBase64String(result));
            
            
            //解密
            cipher.init(Cipher.DECRYPT_MODE, key,pbeParameterSpec);
            result = cipher.doFinal(result);
            System.out.println("jdk PBE解密: "+new String(result));
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }

非對稱的算法:

非對稱算法就是發送方和接收方的密鑰是不同的,非對稱相對於對稱來講,有公鑰和私鑰的概念,基本上公鑰是公開的,好比會在網絡上傳輸,而私鑰安全性要求就要高不少了,由於私鑰是要保密的

基本的非對稱算法有DH,RSA,ELGamal算法

DH:

基於交換交換的非對稱算法,接收方須要獲得接收方的key構建本地密鑰,而接收方也須要獲得發送方的key構建本身本地的密鑰。只有JDK的實現

須要加密的數據:

private static String src="Hello DH";

須要導入的類:

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;

JDK的實現:

    public static void jdkDH(){
        try {
            //初始化發送方密鑰
            KeyPairGenerator senderKeyPairGenerator=KeyPairGenerator.getInstance("DH");
            senderKeyPairGenerator.initialize(512);   //密鑰長度
            KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair();
            byte[] senderPublicKeyEnc = senderKeyPair.getPublic().getEncoded();  //發送方key,需傳遞給接收方(網絡,文件)
            
            //初始化接收方密鑰
            KeyFactory factory=KeyFactory.getInstance("DH");
            X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(senderPublicKeyEnc);  //根據從發送方獲得的key解析
            PublicKey receiverPublicKey=factory.generatePublic(x509EncodedKeySpec);
            DHParameterSpec dhParameterSpec=((DHPublicKey)receiverPublicKey).getParams();
            KeyPairGenerator receiverKeyPairGenerator=KeyPairGenerator.getInstance("DH");
            receiverKeyPairGenerator.initialize(dhParameterSpec);
            KeyPair receiverKeyPair = receiverKeyPairGenerator.generateKeyPair();
            PrivateKey receiverPrivateKey = receiverKeyPair.getPrivate();
            byte[] receiverPublicKeyEnc = receiverKeyPair.getPublic().getEncoded();
            
            //密鑰構建
            KeyAgreement receiverKeyAgreement=KeyAgreement.getInstance("DH");
            receiverKeyAgreement.init(receiverPrivateKey);
            receiverKeyAgreement.doPhase(receiverPublicKey, true);
            SecretKey receiverDESKey=receiverKeyAgreement.generateSecret("DES");  //發送發密鑰(公鑰)
            KeyFactory senderKeyFactory=KeyFactory.getInstance("DH");
            x509EncodedKeySpec=new X509EncodedKeySpec(receiverPublicKeyEnc);
            PublicKey senderPublicKey=senderKeyFactory.generatePublic(x509EncodedKeySpec);
            KeyAgreement senderKeyAgreement=KeyAgreement.getInstance("DH");
            senderKeyAgreement.init(senderKeyPair.getPrivate());
            senderKeyAgreement.doPhase(senderPublicKey, true);
            SecretKey senderDESKey=senderKeyAgreement.generateSecret("DES");        //接收方密鑰(私鑰)
            if(Objects.equals(receiverDESKey, senderDESKey)){
                System.out.println("雙方密鑰相同");
            }
            //加密
            Cipher cipher=Cipher.getInstance("DES");
            cipher.init(Cipher.ENCRYPT_MODE, senderDESKey);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("jdk DH加密: "+org.apache.commons.codec.binary.Base64.encodeBase64String(result));
            
            //解密            
            cipher.init(Cipher.DECRYPT_MODE, receiverDESKey);
            result=cipher.doFinal(result);
            System.out.println("jdk DH解密: "+new String(result));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

RSA:

RSA相較於DH算法的實現簡單,適用範圍較廣,公鑰和私鑰的建立較簡單,並且支持公鑰加密,私鑰解密或者是私鑰加密,公鑰解密兩種方式

要加密的數據:

private static String src="Hello RSA";

要導入的類:

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;

JDK的實現,公鑰加密,私鑰解密和私鑰加密,公鑰解密兩種方式:

public static void jdkRSA(){
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(512);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            RSAPublicKey rsaPublicKey=(RSAPublicKey) keyPair.getPublic();           //公鑰
            RSAPrivateKey rsaPrivateKey=(RSAPrivateKey) keyPair.getPrivate();       //私鑰
            System.out.println("public key:"+Base64.encodeBase64String(rsaPublicKey.getEncoded()));
            System.out.println("private key:"+Base64.encodeBase64String(rsaPrivateKey.getEncoded()));
            
            //私鑰加密,公鑰解密--加密
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
            KeyFactory keyFactory=KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            Cipher cipher=Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("RSA私鑰加密,公鑰解密--加密:"+Base64.encodeBase64String(result));
            
            //私鑰加密,公鑰解密--解密
            X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(rsaPublicKey.getEncoded());
            keyFactory=KeyFactory.getInstance("RSA");
            PublicKey publicKey=keyFactory.generatePublic(x509EncodedKeySpec);
            cipher=Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE,publicKey);
            result = cipher.doFinal(result);
            System.out.println("RSA私鑰加密,公鑰解密--解密:"+new String(result));
            
            //公鑰加密,私鑰解密--加密
            x509EncodedKeySpec=new X509EncodedKeySpec(rsaPublicKey.getEncoded());
            keyFactory=KeyFactory.getInstance("RSA");
            publicKey=keyFactory.generatePublic(x509EncodedKeySpec);
            cipher=Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE,publicKey);
            result = cipher.doFinal(src.getBytes());
            System.out.println("RSA公鑰加密,私鑰解密--加密:"+Base64.encodeBase64String(result));
            
            //公鑰加密,私鑰解密--解密
            pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
            keyFactory=KeyFactory.getInstance("RSA");
            privateKey =keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            cipher=Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE,privateKey);
            result=cipher.doFinal(result);
            System.out.println("RSA公鑰加密,私鑰解密--解密:"+new String(result));
            
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

ELGamal:

ELGamal算法的和AES同樣存在密鑰長度的限制,解決方法和AES一致。不過ELGamal只支持公鑰加密,私鑰解密這種方式。只有bc的實現方式

要加密的數據:

private static String src="Hello ELGamal";

導入的類:

import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import javax.crypto.spec.DHParameterSpec;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

bc的實現方式:

public static void bcELGamal(){
        try {
            //加載provider
            Security.addProvider(new BouncyCastleProvider());
            
            //初始化密鑰
            AlgorithmParameterGenerator algorithmParameterGenerator=AlgorithmParameterGenerator.getInstance("ELGamal");
            algorithmParameterGenerator.init(256);
            AlgorithmParameters algorithmParameters=algorithmParameterGenerator.generateParameters();
            DHParameterSpec dhParameterSpec=(DHParameterSpec)algorithmParameters.getParameterSpec(DHParameterSpec.class);
            KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("ELGamal");
            keyPairGenerator.initialize(dhParameterSpec, new SecureRandom());
            KeyPair keyPair=keyPairGenerator.generateKeyPair();
            PublicKey elGamalPublicKey=keyPair.getPublic();        //公鑰
            PrivateKey elGamalPrivateKey=keyPair.getPrivate();     //私鑰
            System.out.println("public key:"+Base64.encodeBase64String(elGamalPublicKey.getEncoded()));
            System.out.println("private key:"+Base64.encodeBase64String(elGamalPrivateKey.getEncoded()));
            
            //公鑰加密,私鑰解密--加密
            X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
            KeyFactory keyFactory=KeyFactory.getInstance("ELGamal");
            PublicKey publicKey=keyFactory.generatePublic(x509EncodedKeySpec);
            Cipher cipher=Cipher.getInstance("ELGamal");
            cipher.init(Cipher.ENCRYPT_MODE,publicKey);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("ELGamal加密:"+Base64.encodeBase64String(result));
            
            //公鑰加密,私鑰解密--解密
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
            keyFactory=KeyFactory.getInstance("ELGamal");
            PrivateKey privateKey =keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            cipher=Cipher.getInstance("ELGamal");
            cipher.init(Cipher.DECRYPT_MODE,privateKey);
            result=cipher.doFinal(result);
            System.out.println("ElGamal解密:"+new String(result));
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
相關文章
相關標籤/搜索