Java加密 真好(我轉載的)

Java加密算法

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

Base64#

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

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

加密數據:

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類的方法:

複製代碼

    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的是不一樣的,不同包中的類,只是名字一樣:

複製代碼

    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值提供我們效驗下載的文件是否完整,可以用於根據數據生成其唯一的摘要值,無法根據摘要值知道原數據,屬於不可逆的

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的實現方式:

按 Ctrl+C 複製代碼

 

按 Ctrl+C 複製代碼

 

作者:OverZeal

出處:https://www.cnblogs.com/lz2017/p/6917049.html

本站使用「署名 4.0 國際」創作共享協議,轉載請在文章明顯位置註明作者及出處。

標籤: JavaEE工具

0

0

« 上一篇:jQuery筆記——Ajax
» 下一篇:jQuery解析JSON出現SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data

posted @ 2017-05-28 23:52 OverZeal 閱讀(11480) 評論(0) 編輯 收藏

刷新評論刷新頁面

註冊用戶登錄後才能發表評論,請 登錄 或 註冊訪問網站首頁。

Copyright ©2019 OverZeal

這個世界已存在1547618701366毫秒

Powered By Cnblogs | Theme Silence v1.1.1

00:00/04:39

 

 

 

作曲:陳昇

作詞:陳昇 劉佳慧

One Night in 北京

我留下許多情

不管你愛與不愛

都是歷史的塵埃

One Night in 北京

我留下許多情

不敢在午夜問路

怕走到了百花深處

人說百花的深處

住着老情人

縫着繡花鞋

面容安詳的老人

依舊等着那出征的歸人

One Night in 北京

你可別喝太多酒

走在地安門外

沒有人不動真情

One Night in 北京

我留下許多情

把酒高歌的男兒

是北方的狼族

人說北方的狼族

會在寒風起站在城門外

穿着腐朽的鐵衣

呼喚城門外

眼中含着淚

嗚 我已等待了千年

爲何城門還不開

哇 我已等待了千年

爲何良人不歸來

One Night in 北京

我留下許多情

不敢在午夜問路

怕觸動了傷心的魂

One Night in 北京

我留下許多情

不敢在午夜問路

怕走到了地安門

不想再問你

你到底在何方

不想再思量

你能否歸來嘛

想着你的心

想着你的臉

想捧在胸口

能不放就不放

One Night In 北京 One Night In 北京

One Night In 北京 One Night In 北京

One Night In 北京 One Night In 北京

目錄

X

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