加密算法

加密,是以某種特殊的算法改變原有的信息數據,使得未受權的用戶即便得到了已加密的信息,但因不知解密的方法,仍然沒法瞭解信息的內容。html

 

 

雙向加密:大致意思就是明文加密後造成密文,能夠經過算法還原成明文。
單向加密:只是對信息進行了摘要計算,不能經過算法生成明文,單向加密從嚴格意思上說不能算是加密的一種,應該算是摘要算法。
 
主要算法提供方
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就是將內容按照該格式進行編碼。能夠對數據編碼和解碼,是可逆的,安全度較低,不過,也能夠做爲最基礎最簡單的加密算法用於加密要求較弱的狀況。
JDk實現主要使用用BASE64Encoder和BASE64Decoder類的方法(注意:在Eclipse中使用JDK的Base64可能會出現找不到的問題,是由於Base64Encoder並不屬於JDK標準庫範疇,可是又包含在了JDK中,須要咱們手動導入\jre\lib目錄下的rt.jar包便可)。
注意點:
一、標準的Base64並不適合直接放在URL裏傳輸;
二、不是加密算法,而是一種將數據編碼爲64位二進制字符;
package com.paic.java8;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Base64;
import java.util.UUID;

public class Base64Demo {

    public static void main(String args[]) {
        try {

            // 使用基本編碼
            String bStr = "I am a hero!";
            System.out.println("字符串:"+bStr);
            String base64encodedString = Base64.getEncoder().encodeToString(bStr.getBytes("utf-8"));
            System.out.println("基本(編碼) :" + base64encodedString);

            // 解碼
            byte[] base64decodedBytes = Base64.getDecoder().decode(base64encodedString);
            System.out.println("基本(解碼): " + new String(base64decodedBytes, "utf-8"));

            //-----------------------
            String urlStr = "TutorialsPoint?java8";
            System.out.println("URL字符串:"+urlStr);
            base64encodedString = Base64.getUrlEncoder().encodeToString(urlStr.getBytes("utf-8"));
            System.out.println("URL(編碼) :" + base64encodedString);
            base64decodedBytes = Base64.getUrlDecoder().decode(base64encodedString);
            System.out.println("URL(解碼): " + new String(base64decodedBytes, "utf-8"));

            //---------------------------
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < 10; ++i) {
                stringBuilder.append(UUID.randomUUID().toString());
            }
            System.out.println("MIME字符串 :"+stringBuilder.toString());
            byte[] mimeBytes = stringBuilder.toString().getBytes("utf-8");
            String mimeEncodedString = Base64.getMimeEncoder().encodeToString(mimeBytes);
            System.out.println("MIME(編碼) :" + mimeEncodedString);
            base64decodedBytes = Base64.getMimeDecoder().decode(mimeEncodedString);
            System.out.println("MIME(解碼): " + new String(base64decodedBytes, "utf-8"));

        } catch (UnsupportedEncodingException e) {
            System.out.println("Error :" + e.getMessage());
        }
    }
}
字符串:I am a hero!
基本(編碼) :SSBhbSBhIGhlcm8h
基本(解碼): I am a hero!
URL字符串:TutorialsPoint?java8
URL(編碼) :VHV0b3JpYWxzUG9pbnQ_amF2YTg=
URL(解碼): TutorialsPoint?java8
MIME字符串 :ff3eb049-2440-4776-ba6d-becccda60c6f5def99b1-2009-433b-a09c-7fc393305e0641629364-0a92-4d5e-8c5d-1c5ad6a14025ec2ad8ce-2a51-4a0e-b633-ddbb9b2671a15a4fe3e9-7217-4209-a2f1-c478f29cf2dc591579bb-5e31-4984-b4c2-a960924e06e125b28902-aea3-4f76-bcd2-afe533a65cccb66a5eda-71e4-46ba-93fa-0ce685e7e67b9f704c87-34a0-441c-88fc-867a861d771d450d445d-a7ef-4309-b884-f787615f0512
MIME(編碼) :ZmYzZWIwNDktMjQ0MC00Nzc2LWJhNmQtYmVjY2NkYTYwYzZmNWRlZjk5YjEtMjAwOS00MzNiLWEw
OWMtN2ZjMzkzMzA1ZTA2NDE2MjkzNjQtMGE5Mi00ZDVlLThjNWQtMWM1YWQ2YTE0MDI1ZWMyYWQ4
Y2UtMmE1MS00YTBlLWI2MzMtZGRiYjliMjY3MWExNWE0ZmUzZTktNzIxNy00MjA5LWEyZjEtYzQ3
OGYyOWNmMmRjNTkxNTc5YmItNWUzMS00OTg0LWI0YzItYTk2MDkyNGUwNmUxMjViMjg5MDItYWVh
My00Zjc2LWJjZDItYWZlNTMzYTY1Y2NjYjY2YTVlZGEtNzFlNC00NmJhLTkzZmEtMGNlNjg1ZTdl
NjdiOWY3MDRjODctMzRhMC00NDFjLTg4ZmMtODY3YTg2MWQ3NzFkNDUwZDQ0NWQtYTdlZi00MzA5
LWI4ODQtZjc4NzYxNWYwNTEy
MIME(解碼): ff3eb049-2440-4776-ba6d-becccda60c6f5def99b1-2009-433b-a09c-7fc393305e0641629364-0a92-4d5e-8c5d-1c5ad6a14025ec2ad8ce-2a51-4a0e-b633-ddbb9b2671a15a4fe3e9-7217-4209-a2f1-c478f29cf2dc591579bb-5e31-4984-b4c2-a960924e06e125b28902-aea3-4f76-bcd2-afe533a65cccb66a5eda-71e4-46ba-93fa-0ce685e7e67b9f704c87-34a0-441c-88fc-867a861d771d450d445d-a7ef-4309-b884-f787615f0512
View Code

 

二、摘要算法

摘要算法主要分爲MD,SHA和Hmac算法(已經被攻破,彩虹表和MD5站點)。摘要算法實際上是 用於效驗數據完整性的,咱們在下載某些文件時,會有MD5和SHA1值提供咱們校驗下載的文件是否完整,能夠用於根據數據生成其惟一的摘要值,沒法根據摘要值知道原數據,屬於不可逆的。
原理:摘要由一個單向Hash加密函數對消息進行做用而產生,HASH函數的抗衝突性使得若是一段明文稍有變化,哪怕只更改該段落的一個字母,經過哈希算法做用後都將產生不一樣的值。而HASH算法的單向性使得要找到哈希值相同的兩個不一樣的輸入消息,在計算上是不可能的。因此數據的哈希值,即消息摘要, 能夠檢驗數據的完整性
 
主要過程以下:

 

 說明:java

一、以上是壞蛋不知密鑰狀況下,發送請求,第三方根據請求參數+密鑰生成sign與請求的sign比較;算法

二、而若是壞蛋經過截獲的sign,解密md5得到明文,而且經過大量的請求分析出密鑰與消息體的拼接規則,則依然存在安全問題;

MD5

注意:這裏128位是二進制,換算16進制32位apache

如:安全

 

package com.paic.java8;

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

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

public class MDXDemo {

    public static void main(String[] args) {
        String screctKey = "123";
        String content = "Hello";
        encrypt(content,screctKey);
    }

    /**
     * 加密
     * @param content
     * @param screctKey
     */
    public static void encrypt(String content,String screctKey){
        MessageDigest md5= null;
        MessageDigest md2= null;

        //內容 + 密鑰
        //緣由:若是單單只是內容,攻擊方也是能夠經過MD5獲得sign1,拼接攻擊方不知到的密鑰,在攻擊方篡改內容後將獲得不一樣的sign2
        //固然攻擊方能夠根據sign1解密從而得到密鑰
        String src = content + screctKey;
        try {
            md5 = MessageDigest.getInstance("MD5");
            md2 = MessageDigest.getInstance("MD2");
            byte[] digest5 = md5.digest(src.getBytes());
            byte[] digest2 = md2.digest(src.getBytes());
            System.out.println("JDK MD5: "+ Hex.encodeHexString(digest5));
            System.out.println("JDK MD2: "+ Hex.encodeHexString(digest2));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
}

32位字符網絡

JDK MD5: d0aabe9a362cb2712ee90e04810902f3
JDK MD2: 014b1eb8d5557bb786b83a18c9fbbe2eapp

解密,在線上測試下:https://www.somd5.com/dom

SHA

 

 安全性:SHA1所產生的摘要比MD5長32位。若兩種散列函數在結構上沒有任何問題的話,SHA1比MD5更安全ide

 

package com.paic.java8;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;

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

public class SHAXDemo {

    public static void main(String[] args) {
        String content = "Hello";
        jdkSHA1(content);
        ccsha(content);
    }

    /**
     * JDK實現方式(一樣是使用MessageDigest)
     * @param src
     */
    public static void jdkSHA1(String src){
        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();
        }
    }

    /**
     * cc的實現方式
     * @param src
     */
    public static void ccsha(String src){
        System.out.println("CC  SHA1:"+ DigestUtils.sha1Hex(src));
    }

    //BC略...
}

JDK SHA1:f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0
CC   SHA1:f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0函數

Hmac

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

package com.paic.java8.encry;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class HmacDemo {

    public static void main(String[] args) {
        encrypt("Hello","aaaaaaaaaa");
    }

    /**
     * JDK的實現方式  BC略
     * @param content
     * @param key
     */
    public static void encrypt(String content,String key){
        SecretKey secretKey = getSecretKey(key);

        try {
            Mac mac= Mac.getInstance(secretKey.getAlgorithm());

            //初始化mac
            mac.init(secretKey);
            byte[] hmacMD5Bytes=mac.doFinal(content.getBytes());

            //jdk hmacMD5: bfb61695a42d5d16add45743a4e0eea4
            System.out.println("jdk hmacMD5: "+Hex.encodeHexString(hmacMD5Bytes));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
    }

    /**
     * 獲取默認密鑰
     * @return
     */
    public static SecretKey getDefaultSecretKey() {
        SecretKey secretKey = null;
        //初始化KeyGenerator
        KeyGenerator keyGenerator = null;
        try {
            keyGenerator = KeyGenerator.getInstance("HmacMD5");
            //產生密鑰
            secretKey = keyGenerator.generateKey();


        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return secretKey;
    }

    /**
     * 自定義密鑰
     * @param key
     * @return
     */
    public static SecretKey getSecretKey(String key){
        SecretKey secretKey = null;
        byte[] keyByteArr= null;
        try {
            //長度必須偶數
            boolean flag = (null == key)? true : ((key.length()) & 1) != 0;
            if(flag){
                throw new DecoderException("Key長度必須偶數");
            }
            keyByteArr = Hex.decodeHex(key.toCharArray());
            secretKey = new SecretKeySpec(keyByteArr,"HmacMD5");
        } catch (DecoderException e) {
            e.printStackTrace();
        }
        return secretKey;
    }
}

 

    /**
     * BC方式
     */
    public static void bcHmacMd5(){

        String src = "Hello,World";

        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

package com.paic.java8.encry;

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

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;

public class DesSemo {

    public static void main(String[] args) {
        //jdkDES加密: cfa7121606a4413138d8d3781afeaa1c
        try {

            SecretKey key = getSecretKey("aaaabbbbcc");
            byte[] content = jdkDESEncrypt("Hello DES", key);
            jdkDESDecrypt(content, key);

            bcDES();

        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
    }

    public static SecretKey getDefaultSecretKey() {
        KeyGenerator keyGenerator = null;
        SecretKey secretKey = null;
        try {
            keyGenerator = KeyGenerator.getInstance("DES");
            keyGenerator.init(56);      //指定key長度,同時也是密鑰長度(56位)
            secretKey = keyGenerator.generateKey(); //生成key的材料
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return secretKey;
    }

    /**
     * key 長度 > 8
     *
     * @param key
     * @return
     * @throws InvalidKeyException
     */
    public static SecretKey getSecretKey(String key) throws InvalidKeyException {
        SecretKey secretKey = null;

        byte[] keyByteArr = key.getBytes();

        if (keyByteArr.length - 0 < 8) {
            throw new InvalidKeyException("Wrong key size");
        }

        DESKeySpec desKeySpec = null;
        try {
            desKeySpec = new DESKeySpec(keyByteArr);
            SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
            secretKey = factory.generateSecret(desKeySpec);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }

        return secretKey;
    }

    /**
     * DES 加密
     *
     * @param content
     * @param key2
     */
    public static byte[] jdkDESEncrypt(String content, SecretKey key2) {
        //加密
        Cipher cipher = null;

        byte[] result = null;
        try {
            //算法類型/工做方式/填充方式
            cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            //指定爲加密模式
            cipher.init(Cipher.ENCRYPT_MODE, key2);
            result = cipher.doFinal(content.getBytes());

            //轉換爲十六進制
            //desResult = Hex.encodeHexString(result);

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 解密
     *
     * @param encrypt
     * @param key
     */
    public static void jdkDESDecrypt(byte[] encrypt, SecretKey key) {
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            //解密
            cipher.init(Cipher.DECRYPT_MODE, key);  //相同密鑰,指定爲解密模式
            byte[] result = cipher.doFinal(encrypt);   //根據加密內容解密
            System.out.println("jdkDES解密: " + new String(result));  //轉換字符串
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }

    }

    /**
     * BC方式
     */
    public static void bcDES(){
        String src = "Hello DES";
        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();
        }
    }
}

3DES

package com.paic.java8.encry;

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

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import java.security.SecureRandom;
import java.security.Security;

public class Des3Demo {

    private static String src="Hello 3DES";

    public static void main(String[] args) {

    }

    /**
     * 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

 

四、非對稱加密

 待續

相關文章
相關標籤/搜索