加密和解密

加密和解密

目录介绍

  • 1.加密和解密
    • 1.1 问答环节
    • 1.2 加解密概况
  • 2.对称加密和非对称加密
    • 2.1 什么是对称加密
    • 2.2 什么是非对称加密
    • 2.3 常见对称加密有什么
    • 2.4 常见非对称加密有什么
    • 2.5 非对称加密用途
  • 3.关于单向加密
    • 3.1 MD加密
    • 3.2 什么叫做加盐
  • 4.加密和解密代码展示
    • 4.1 DES加密和解密
    • 4.2 AES解密和解密
  • 5.RSA非对称加解密
    • 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/yangchong211/YCBlogs

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
  • 陌生人通信
    • 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";//加密填充方式
    
    
    
        /**
         * 随机生成RSA密钥对
         *
         * @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                异常
    *                                  https://github.com/yangchong211
    */
    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.关于我的博客

转载于:https://my.oschina.net/zbj1618/blog/2231535

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/101386.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • websocket深入浅出

    websocket深入浅出websocket简介websocket是什么答:它是一种网络通信协议,是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。为什么需要websocket?疑问?我们已经有了HTTP协议,为什么还需要另一个协议?它能带来什么好处?答:因为HTTP协议有一个缺陷:通信只能由客户端发起我们都知道轮询的效率低,非常浪费资源(因为必须不停连接,或者HTTP…

  • nacivat错误生成激活码_最新在线免费激活

    (nacivat错误生成激活码)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.html1S…

  • 微信开放平台扫码登陆

    微信开放平台扫码登陆微信授权扫码登陆微信开放平台提供了两种登陆方式,一种是会跳转到一个很丑很丑,只有一个二维码的界面里;另一种则是可以自己定制化的(二维码内嵌到自己网站内的方式)第一种方式的完成非常简单,但是第二种方式,就需要前后台都做一些调整了微信扫码登陆的准备工作这是在开始做相关业务开发之前的一些东西去微信开放平台中注册一个账号,并完成自己的开发者资质认证(这个链接应该点不过去,他们token是明…

  • dell服务器显示器fre,戴尔全新 Freesync 显示器,专门针对游戏玩家[通俗易懂]

    dell服务器显示器fre,戴尔全新 Freesync 显示器,专门针对游戏玩家[通俗易懂]戴尔拥有一对全新的Ultrasharp显示器,专门针对游戏玩家,对于那些重视整体速度和响应能力的人来说,它们可能是不久的将来理想的升级途径。运动刷新率高达155Hz,分辨率高达1440P,以及24英寸和27英寸面板的选项,有很多值得关注的新的,配备Freesync的显示器。但这会是如今最好的游戏显示器吗?戴尔2719DGF是一款27英寸TN面板显示器,其机箱外观干净,专…

  • Linux 硬盘分区生效命令partprobe[通俗易懂]

    Linux 硬盘分区生效命令partprobe[通俗易懂]在Linux中使用fdisk命令进行分区时,有时会遇到“WARNING:Re-readingthepartitiontablefailedwitherror16:Deviceorresourcebusy.Thekernelstillusestheoldtable.Thenewtablewillbeusedatthenextreboot.”这种告…

    2022年10月21日
  • 史上最简单的带流控功能的http server

    史上最简单的带流控功能的http server

    2021年11月29日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号