加密和解密

目錄介紹

  • 1.加密和解密php

    • 1.1 問答環節
    • 1.2 加解密概況
  • 2.對稱加密和非對稱加密java

    • 2.1 什麼是對稱加密
    • 2.2 什麼是非對稱加密
    • 2.3 常見對稱加密有什麼
    • 2.4 常見非對稱加密有什麼
    • 2.5 非對稱加密用途
  • 3.關於單向加密android

    • 3.1 MD加密
    • 3.2 什麼叫作加鹽
  • 4.加密和解密代碼展現git

    • 4.1 DES加密和解密
    • 4.2 AES解密和解密
  • 5.RSA非對稱加解密github

    • 5.1 公鑰加密,私鑰解密
    • 5.2 私鑰加密,公鑰解密
    • 5.3 完整工具類代碼
    • 5.4 注意RSA加密填充方式
    • 5.5 RSA加密內容長度限制問題
    • 5.6 加解密效率測試
    • 5.7 分段加密解密工具類代碼

好消息

  • 博客筆記大彙總【16年3月到至今】,包括Java基礎及深刻知識點,Android技術博客,Python學習筆記等等,還包括平時開發中遇到的bug彙總,長期更新維護而且修正,持續完善……開源的文件是markdown格式的!轉載請註明出處,謝謝!
  • https://github.com/yangchong2...

1.加密和解密

1.1 問答環節

  • 1.1.1 常見的加密和解密有哪些?
  • 1.1.2 MD5加密是屬於什麼類型?是否可逆,以及有哪些應用場景?
  • 1.1.3 實際開發中有哪些加解密的應用場景?

1.2 加解密概況

  • 1)在對稱加密算法中,雙方使用的密鑰相同,要求解密方事先必須知道加密密鑰。這類加密算法技術較爲成熟,加密效率高。
  • 2)在非對稱加密算法中,收發雙方使用不一樣的密鑰,發方使用公開密鑰對消息進行加密,收發使用私有密鑰機型解密,保密性更高,但效率更低。
  • 3)單向加密算法在加密過程當中不須要使用密鑰,輸入明文後由算法直接加密成密文,密文沒法解密,只有從新輸入密文,並通過一樣的加密算法處理,獲得形同的密文並被系統從新識別後,才能真正的解密,這種算法很是複雜,一般只在數據量有限的情形下使用,如普遍應用在計算機系統中的口令加密等。

2.對稱加密和非對稱加密

2.1 什麼是對稱加密

  • 密鑰能夠本身指定,只有一把密鑰,若是密鑰暴露,文件就會被暴露
  • 特色是加密速度很快,可是缺點是安全性較低,由於只要密鑰暴漏,數據就能夠被解密了。
  • 一句話歸納:加密和解密都是用相同密鑰

2.2 什麼是非對稱加密

  • 有兩把鑰匙(密鑰對),公鑰和私鑰,公鑰的話給別人,私鑰本身保存
  • 把密鑰一般是經過程序生成,不能本身指定
  • 特色是加密速度慢些,可是安全係數很高
  • 加密和解密的規則是:公鑰加密只能私鑰解密,私鑰加密只能公鑰解密
  • 應用場景舉例:在集成支付寶支付sdk時,須要生成私鑰和公鑰,公鑰須要設置到支付寶網站的管理後臺,在程序中調用支付接口的時候,使用咱們本身的私鑰進行加密,這樣支付寶因爲有公鑰能夠解密,其餘人即時劫持了數據,可是沒有公鑰,也沒法解密。
  • image

2.3 常見對稱加密有什麼

  • DES算法(Data Encryption Standard)
  • AES算法(Advanced Encryption Standard)

2.4 常見非對稱加密有什麼

  • RSA

2.5 非對稱加密用途

  • 身份認證算法

    • 一條加密信息若能用A 的公鑰能解開,則該信息必定是用A 的私鑰加密的,該能肯定該用戶是A。
    • image
  • 陌生人通訊segmentfault

    • A 和B 兩我的互不認識,A把本身的公鑰發給B,B也把本身的公鑰發給A,則雙方能夠經過對方的公鑰加密信息通訊。C 雖然也能獲得A、B 的公鑰,可是他解不開密文。
    • image
  • 支付寶支付加密數組

    • 具體能夠參考支付寶sdk的官方demo

3.關於單向加密

  • MD5安全

    • 關於MD5加密的工具類代碼以下所示

4.加密和解密代碼展現

4.1 DES加密和解密【對稱加密】

  • 加密過程服務器

    • 須要加密的內容,也就是明文;而後須要密鑰。最後經過工具類加密獲得加密後的密文
    private final String desEncryptString = "yangchong";
    private final String desEncryptKey = "19930311";
    s1 = DES.encryptDES(desEncryptString, desEncryptKey);
    Log.e("加密和解密", s1);
    加密和解密: 84r1gS+D3Op8yrSnF5ZDrQ==
    //s1爲加密後的密文
  • 解密過程

    • 利用加密後的密文,與設置的key,也就是密鑰,則能夠解密獲得加密的內容
    String s2 = DES.decryptDES(s1, desEncryptKey);
    Log.e("加密和解密", s2);
    //加密和解密: yangchong
  • Android中實現DES加密和解密的核心代碼以下
public class DES {

    //初始化向量,隨意填寫
    private static byte[] iv = {1,2,3,4,5,6,7,8};

    /**
     *
     * @param encryptString         明文
     * @param encryptKey            密鑰
     * @return                      加密後的密文
     */
    public static String encryptDES(String encryptString,String encryptKey){
        try {
            //實例化IvParameterSpec對象,使用指定的初始化向量
            IvParameterSpec zeroIv=new IvParameterSpec(iv);
            //實例化SecretKeySpec,根據傳入的密鑰得到字節數組來構造SecretKeySpec
            SecretKeySpec key =new SecretKeySpec(encryptKey.getBytes(),"DES");
            //建立密碼器
            Cipher cipher=Cipher.getInstance("DES/CBC/PKCS5Padding");
            //用密鑰初始化Cipher對象
            cipher.init(Cipher.ENCRYPT_MODE,key,zeroIv);
            //執行加密操做
            byte[]encryptedData=cipher.doFinal(encryptString.getBytes());
            return Base64.encodeToString(encryptedData,0);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 解密的過程與加密的過程大體相同
     * @param decryptString         密文
     * @param decryptKey            密鑰
     * @return  返回明文
     */

    public static String decryptDES(String decryptString,String decryptKey){

        try {
            //先使用Base64解密
            byte[]byteMi = Base64.decode(decryptString,0);
            //實例化IvParameterSpec對象使用指定的初始化向量
            IvParameterSpec zeroIv=new IvParameterSpec(iv);
            //實例化SecretKeySpec,根據傳入的密鑰得到字節數組來構造SecretKeySpec,
            SecretKeySpec key=new SecretKeySpec(decryptKey.getBytes(),"DES");
            //建立密碼器
            Cipher cipher=Cipher.getInstance("DES/CBC/PKCS5Padding");
            //用密鑰初始化Cipher對象,上面是加密,這是解密模式
            cipher.init(Cipher.DECRYPT_MODE,key,zeroIv);
            //獲取解密後的數據
            byte [] decryptedData=cipher.doFinal(byteMi);
            return new String(decryptedData);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return null;
    }
}

4.2 AES解密和解密【對稱加密】

public class AES {


    private static final String Algorithm = "AES";
    private final static String HEX = "0123456789ABCDEF";

    //加密函數,key爲密鑰
    public static String encrypt(String key, String src) throws Exception {
        byte[] rawKey = getRawKey(key.getBytes());
        byte[] result = encrypt(rawKey, src.getBytes());
        return toHex(result);
    }

    //解密函數。key值必須和加密時的key一致
    public static String decrypt(String key, String encrypted) throws Exception {
        byte[] rawKey = getRawKey(key.getBytes());
        byte[] enc = toByte(encrypted);
        byte[] result = decrypt(rawKey, enc);
        return new String(result);
    }

    private static void appendHex(StringBuffer sb, byte b) {
        sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
    }

    private static byte[] getRawKey(byte[] seed) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance(Algorithm);
        // SHA1PRNG 強隨機種子算法, 要區別Android 4.2.2以上版本的調用方法
        SecureRandom sr = null;
        if (android.os.Build.VERSION.SDK_INT >= 17) {
            sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
        } else {
            sr = SecureRandom.getInstance("SHA1PRNG");
        }
        sr.setSeed(seed);
        kgen.init(256, sr); // 256位或128位或192位
        SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();
        return raw;
    }

    private static byte[] encrypt(byte[] key, byte[] src) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(key, Algorithm);
        Cipher cipher = Cipher.getInstance(Algorithm);
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(src);
        return encrypted;
    }

    private static byte[] decrypt(byte[] key, byte[] encrypted) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(key, Algorithm);
        Cipher cipher = Cipher.getInstance(Algorithm);
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
    }

    private static byte[] toByte(String hexString) {
        int len = hexString.length() / 2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++) {
            result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue();
        }
        return result;
    }

    private static String toHex(byte[] buf) {
        if (buf == null) {
            return "";
        }
        StringBuffer result = new StringBuffer(2 * buf.length);
        for (int i = 0; i < buf.length; i++) {
            appendHex(result, buf[i]);
        }
        return result.toString();
    }

}

5.RSA非對稱加解密

5.1 公鑰加密,私鑰解密

  • 第一步:獲取隨機的公鑰和私鑰

    • 代碼以下所示:
    //祕鑰默認長度
    public static final int DEFAULT_KEY_SIZE = 2048;
    KeyPair keyPair = RSA.generateRSAKeyPair(DEFAULT_KEY_SIZE);
    if (keyPair != null) {
        // 公鑰
        publicKey = (RSAPublicKey) keyPair.getPublic();
        // 私鑰
        privateKey = (RSAPrivateKey) keyPair.getPrivate();
    }
  • 第二步:公鑰加密

    • 代碼以下所示:
    //用公鑰對字符串進行加密
    try {
        bytes = RSA.encryptByPublicKey(DEFAULT_SPLIT, publicKey.getEncoded());
        String s = new String(bytes);
        Log.e("加密和解密", s);
    } catch (Exception e) {
        e.printStackTrace();
    }
  • 第三步:私鑰解密

    //使用私鑰進行解密
    try {
        byte[] bytes = RSA.decryptByPrivateKey(this.bytes, privateKey.getEncoded());
        String s = new String(bytes);
        Log.e("加密和解密", s);
        //解密後獲得的數據:yangchong
    } catch (Exception e) {
        e.printStackTrace();
    }

5.2 私鑰加密,公鑰解密

  • 第一步:獲取隨機的公鑰和私鑰

    • 代碼以下所示:
    //祕鑰默認長度
    public static final int DEFAULT_KEY_SIZE = 2048;
    KeyPair keyPair = RSA.generateRSAKeyPair(DEFAULT_KEY_SIZE);
    if (keyPair != null) {
        // 公鑰
        publicKey = (RSAPublicKey) keyPair.getPublic();
        // 私鑰
        privateKey = (RSAPrivateKey) keyPair.getPrivate();
    }
  • 第二步:私鑰加密

    • 代碼以下所示:
    //使用私鑰加密
    try {
        bytes1 = RSA.encryptByPrivateKey(DEFAULT_SPLIT, privateKey.getEncoded());
        String s = new String(bytes);
        Log.e("加密和解密", s);
    } catch (Exception e) {
        e.printStackTrace();
    }
  • 第三步:公鑰解密

    //使用公鑰解密
    try {
        byte[] bytes = RSA.decryptByPublicKey(this.bytes1, publicKey.getEncoded());
        String s = new String(bytes);
        Log.e("加密和解密", s);
        //解密後獲得的數據:yangchong
    } catch (Exception e) {
        e.printStackTrace();
    }

5.3 完整工具類代碼

  • 代碼以下所示:

    public class RSA {
    
        public static final String RSA = "RSA";// 非對稱加密密鑰算法
        public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";//加密填充方式
    
    
    
        /**
*
     * @param keyLength         密鑰長度,範圍:512~2048
     *                          通常1024
     * @return
     */
    public static KeyPair generateRSAKeyPair(int keyLength) {
        try {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
            kpg.initialize(keyLength);
            return kpg.genKeyPair();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

    /*-------------------------------------------------------------------------------------------------*/


    /**
     * 用公鑰對字符串進行加密
     * @param data                      原文
     * @param publicKey                 密鑰
     * @return                          byte[] 解密數據
     */
    public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
        // 獲得公鑰
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PublicKey keyPublic = kf.generatePublic(keySpec);
        // 加密數據
        Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
        cp.init(Cipher.ENCRYPT_MODE, keyPublic);
        return cp.doFinal(data);
    }

    /**
     * 私鑰加密
     *
     * @param data                      待加密數據
     * @param privateKey                密鑰
     * @return                          byte[] 解密數據
     */
    public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
        // 獲得私鑰
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PrivateKey keyPrivate = kf.generatePrivate(keySpec);
        // 數據加密
        Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
        cipher.init(Cipher.ENCRYPT_MODE, keyPrivate);
        return cipher.doFinal(data);
    }

    /**
     * 公鑰解密
     *
     * @param data                      待解密數據
     * @param publicKey                 密鑰
     * @return                          byte[] 解密數據
     */
    public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
        // 獲得公鑰
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PublicKey keyPublic = kf.generatePublic(keySpec);
        // 數據解密
        Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
        cipher.init(Cipher.DECRYPT_MODE, keyPublic);
        return cipher.doFinal(data);
    }

    /**
     * 使用私鑰進行解密
     * @param encrypted                 待解密數據
     * @param privateKey                密鑰
     * @return                          byte[] 解密數據
     * @throws Exception                異常
     */
    public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception {
        // 獲得私鑰
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PrivateKey keyPrivate = kf.generatePrivate(keySpec);
        // 解密數據
        Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
        cp.init(Cipher.DECRYPT_MODE, keyPrivate);
        byte[] arr = cp.doFinal(encrypted);
        return arr;
    }

}
```

5.4 注意RSA加密填充方式

  • 以前覺得上面操做就能實現rsa加解密,覺得能夠呢,可是遇到Android這邊加密過的數據,服務器端死活解密不了,原來android系統的RSA實現是"RSA/None/NoPadding",而標準JDK實現是"RSA/None/PKCS1Padding",這形成了在android機上加密後沒法在服務器上解密的緣由,因此在實現的時候這個必定要注意這個問題。

5.5 RSA加密內容長度限制問題

  • RSA非對稱加密內容長度有限制,1024位key的最多隻能加密127位數據,不然就會報錯(javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes)
  • RSA 算法規定:待加密的字節數不能超過密鑰的長度值除以 8 再減去 11(即:KeySize / 8 - 11),而加密後獲得密文的字節數,正好是密鑰的長度值除以 8(即:KeySize / 8)。

5.6 加解密效率測試

  • 第一步:獲取隨機的公鑰和私鑰

    • 代碼以下所示:
    //祕鑰默認長度
    public static final int DEFAULT_KEY_SIZE = 2048;
    KeyPair keyPair = RSA.generateRSAKeyPair(DEFAULT_KEY_SIZE);
    if (keyPair != null) {
        // 公鑰
        publicKey = (RSAPublicKey) keyPair.getPublic();
        // 私鑰
        privateKey = (RSAPrivateKey) keyPair.getPrivate();
    }
  • 第二步:用公鑰對對象進行加密

    • 代碼以下所示:
    //用公鑰對對象進行加密
    YC yc = new YC();
    yc.setAge(25);
    yc.setName("楊充");
    StringBuilder stringBuilder = new StringBuilder();
    for(int a=0 ; a<500 ; a++){
        stringBuilder.append("都比小楊"+a);
    }
    yc.setInfo(stringBuilder.toString());
    String string = yc.toString();
    long start = System.currentTimeMillis();
    encryptBytes = new byte[0];
    try {
        encryptBytes = RSA.encryptByPublicKeyForSpilt(string.getBytes(),publicKey.getEncoded());
    } catch (Exception e) {
        e.printStackTrace();
    }
    long end=System.currentTimeMillis();
    Log.e("YC","公鑰加密耗時 cost time---->"+(end-start));
    String encryStr = new String(encryptBytes);
    Log.e("YC","加密前數據長度 --1-->"+string.length());
    Log.e("YC","加密後數據長度 --1-->"+encryStr.length());
  • 第三步:使用私鑰進行解密

    //使用私鑰進行解密
    long start2 = System.currentTimeMillis();
    byte[] decryptBytes= new byte[0];
    try {
        decryptBytes = RSA.decryptByPrivateKeyForSpilt(encryptBytes,privateKey.getEncoded());
    } catch (Exception e) {
        e.printStackTrace();
    }
    String decryStr = new String(decryptBytes);
    long end2 =System.currentTimeMillis();
    Log.e("YC","私鑰解密耗時 cost time---->"+(end2-start2));
    Log.e("YC","解密後數據 --1-->"+decryStr);
  • 第四步:加密和解密效率比較

    • 以下所示
    • 加密後數據大小的變化:數據量差很少是加密前的1.6倍
    • 通過幾回測試可知,解密要比加密費時間多,因此通常建議在服務端作解密的邏輯操做
    • image

5.7 分段加密解密工具類代碼

  • 代碼以下所示

    //祕鑰默認長度
    private static final int DEFAULT_KEY_SIZE = 2048;
    // 當前祕鑰支持加密的最大字節數
    private static final int DEFAULT_BUFFER_SIZE = (DEFAULT_KEY_SIZE / 8) - 11;
    // 當要加密的內容超過bufferSize,則採用partSplit進行分塊加密
    private static final byte[] DEFAULT_SPLIT = "#PART#".getBytes();
    
    /**
     * 用公鑰對字符串進行分段加密
     * @param data                      須要加密數據
     * @param publicKey                 公鑰
     * @return                          byte[] 加密數據
     * @throws Exception                異常
*/
public static byte[] encryptByPublicKeyForSpilt(byte[] data, byte[] publicKey) throws Exception {
    int dataLen = data.length;
    if (dataLen <= DEFAULT_BUFFER_SIZE) {
        return encryptByPublicKey(data, publicKey);
    }
    List<Byte> allBytes = new ArrayList<>(2048);
    int bufIndex = 0;
    int subDataLoop = 0;
    byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
    for (int i = 0; i < dataLen; i++) {
        if (buf != null) {
            buf[bufIndex] = data[i];
        }
        if (++bufIndex == DEFAULT_BUFFER_SIZE || i == dataLen - 1) {
            subDataLoop++;
            if (subDataLoop != 1) {
                for (byte b : DEFAULT_SPLIT) {
                    allBytes.add(b);
                }
            }
            byte[] encryptBytes = encryptByPublicKey(buf, publicKey);
            for (byte b : encryptBytes) {
                allBytes.add(b);
            }
            bufIndex = 0;
            if (i == dataLen - 1) {
                buf = null;
            } else {
                buf = new byte[Math.min(DEFAULT_BUFFER_SIZE, dataLen - i - 1)];
            }
        }
    }
    byte[] bytes = new byte[allBytes.size()];
    int i = 0;
    for (Byte b : allBytes) {
        bytes[i++] = b;
    }
    return bytes;
}

/**
 * 用祕鑰對字符串進行分段加密
 *
 * @param data                      要加密的原始數據
 * @param privateKey                祕鑰
 * @return                          byte[] 加密數據
 * @throws Exception                異常
 *                                  https://github.com/yangchong211
 */
public static byte[] encryptByPrivateKeyForSpilt(byte[] data, byte[] privateKey) throws Exception {
    int dataLen = data.length;
    if (dataLen <= DEFAULT_BUFFER_SIZE) {
        return encryptByPrivateKey(data, privateKey);
    }
    List<Byte> allBytes = new ArrayList<Byte>(2048);
    int bufIndex = 0;
    int subDataLoop = 0;
    byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
    for (int i = 0; i < dataLen; i++) {
        if (buf != null) {
            buf[bufIndex] = data[i];
        }
        if (++bufIndex == DEFAULT_BUFFER_SIZE || i == dataLen - 1) {
            subDataLoop++;
            if (subDataLoop != 1) {
                for (byte b : DEFAULT_SPLIT) {
                    allBytes.add(b);
                }
            }
            byte[] encryptBytes = encryptByPrivateKey(buf, privateKey);
            for (byte b : encryptBytes) {
                allBytes.add(b);
            }
            bufIndex = 0;
            if (i == dataLen - 1) {
                buf = null;
            } else {
                buf = new byte[Math.min(DEFAULT_BUFFER_SIZE, dataLen - i - 1)];
            }
        }
    }
    byte[] bytes = new byte[allBytes.size()];
    int i = 0;
    for (Byte b : allBytes) {
        bytes[i++] = b;
    }
    return bytes;
}

/**
 * 用公鑰分段解密
 *
 * @param encrypted                 待解密數據
 * @param publicKey                 公鑰
 * @return                          byte[] 解密數據
 * @throws Exception                異常
 *                                  https://github.com/yangchong211
 */
public static byte[] decryptByPublicKeyForSpilt(byte[] encrypted, byte[] publicKey) throws Exception {
    int splitLen = DEFAULT_SPLIT.length;
    if (splitLen <= 0) {
        return decryptByPublicKey(encrypted, publicKey);
    }
    int dataLen = encrypted.length;
    List<Byte> allBytes = new ArrayList<Byte>(1024);
    int latestStartIndex = 0;
    for (int i = 0; i < dataLen; i++) {
        byte bt = encrypted[i];
        boolean isMatchSplit = false;
        if (i == dataLen - 1) {
            // 到data的最後了
            byte[] part = new byte[dataLen - latestStartIndex];
            System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
            byte[] decryptPart = decryptByPublicKey(part, publicKey);
            for (byte b : decryptPart) {
                allBytes.add(b);
            }
            latestStartIndex = i + splitLen;
            i = latestStartIndex - 1;
        } else if (bt == DEFAULT_SPLIT[0]) {
            // 這個是以split[0]開頭
            if (splitLen > 1) {
                if (i + splitLen < dataLen) {
                    // 沒有超出data的範圍
                    for (int j = 1; j < splitLen; j++) {
                        if (DEFAULT_SPLIT[j] != encrypted[i + j]) {
                            break;
                        }
                        if (j == splitLen - 1) {
                            // 驗證到split的最後一位,都沒有break,則代表已經確認是split段
                            isMatchSplit = true;
                        }
                    }
                }
            } else {
                // split只有一位,則已經匹配了
                isMatchSplit = true;
            }
        }
        if (isMatchSplit) {
            byte[] part = new byte[i - latestStartIndex];
            System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
            byte[] decryptPart = decryptByPublicKey(part, publicKey);
            for (byte b : decryptPart) {
                allBytes.add(b);
            }
            latestStartIndex = i + splitLen;
            i = latestStartIndex - 1;
        }
    }
    byte[] bytes = new byte[allBytes.size()];
    int i = 0;
    for (Byte b : allBytes) {
        bytes[i++] = b;
    }
    return bytes;
}

/**
 * 使用私鑰分段解密
 *
 * @param encrypted                 待解密數據
 * @param privateKey                私鑰
 * @return                          byte[] 解密數據
 * @throws Exception                異常
 *                                  https://github.com/yangchong211
 */
public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted, byte[] privateKey) throws Exception {
    int splitLen = DEFAULT_SPLIT.length;
    if (splitLen <= 0) {
        return decryptByPrivateKey(encrypted, privateKey);
    }
    int dataLen = encrypted.length;
    List<Byte> allBytes = new ArrayList<Byte>(1024);
    int latestStartIndex = 0;
    for (int i = 0; i < dataLen; i++) {
        byte bt = encrypted[i];
        boolean isMatchSplit = false;
        if (i == dataLen - 1) {
            // 到data的最後了
            byte[] part = new byte[dataLen - latestStartIndex];
            System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
            byte[] decryptPart = decryptByPrivateKey(part, privateKey);
            for (byte b : decryptPart) {
                allBytes.add(b);
            }
            latestStartIndex = i + splitLen;
            i = latestStartIndex - 1;
        } else if (bt == DEFAULT_SPLIT[0]) {
            // 這個是以split[0]開頭
            if (splitLen > 1) {
                if (i + splitLen < dataLen) {
                    // 沒有超出data的範圍
                    for (int j = 1; j < splitLen; j++) {
                        if (DEFAULT_SPLIT[j] != encrypted[i + j]) {
                            break;
                        }
                        if (j == splitLen - 1) {
                            // 驗證到split的最後一位,都沒有break,則代表已經確認是split段
                            isMatchSplit = true;
                        }
                    }
                }
            } else {
                // split只有一位,則已經匹配了
                isMatchSplit = true;
            }
        }
        if (isMatchSplit) {
            byte[] part = new byte[i - latestStartIndex];
            System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
            byte[] decryptPart = decryptByPrivateKey(part, privateKey);
            for (byte b : decryptPart) {
                allBytes.add(b);
            }
            latestStartIndex = i + splitLen;
            i = latestStartIndex - 1;
        }
    }
    byte[] bytes = new byte[allBytes.size()];
    int i = 0;
    for (Byte b : allBytes) {
        bytes[i++] = b;
    }
    return bytes;
}
```

關於其餘內容介紹

01.關於博客彙總連接

02.關於個人博客

相關文章
相關標籤/搜索