content: package com.liyi.sutils.utils.encrypt;
  
  import java.security.InvalidKeyException;
  import java.security.KeyFactory;
  import java.security.KeyPair;
  import java.security.KeyPairGenerator;
  import java.security.NoSuchAlgorithmException;
  import java.security.PrivateKey;
  import java.security.PublicKey;
  import java.security.spec.InvalidKeySpecException;
  import java.security.spec.PKCS8EncodedKeySpec;
  import java.security.spec.X509EncodedKeySpec;
  import java.util.ArrayList;
  import java.util.List;
  
  import javax.crypto.BadPaddingException;
  import javax.crypto.Cipher;
  import javax.crypto.IllegalBlockSizeException;
  import javax.crypto.NoSuchPaddingException;
  
  /**
   * RSA 加密工具类（非对称加密）
   * <p>
   * 参考链接：http://www.cnblogs.com/whoislcj/p/5470095.html
   */
  public final class RsaUtil {
      /* 非对称加密密钥算法 */
      private static final String RSA = "RSA";
      /* 加密填充方式 */
      private static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";
      /* 秘钥默认长度 */
      private static final int DEFAULT_KEY_SIZE = 2048;
      /* 当要加密的内容超过 bufferSize，则采用 partSplit 进行分块加密 */
      private static final byte[] DEFAULT_SPLIT = "#PART#".getBytes();
      /* 当前秘钥支持加密的最大字节数 */
      private static final int DEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE / 8) - 11;
  
      private RsaUtil() {
          throw new UnsupportedOperationException("cannot be instantiated");
      }
  
      /**
       * 随机生成 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
       */
      public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) {
          try {
              // 得到公钥
              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);
          } catch (NoSuchAlgorithmException e) {
              e.printStackTrace();
          } catch (InvalidKeyException e) {
              e.printStackTrace();
          } catch (NoSuchPaddingException e) {
              e.printStackTrace();
          } catch (BadPaddingException e) {
              e.printStackTrace();
          } catch (InvalidKeySpecException e) {
              e.printStackTrace();
          } catch (IllegalBlockSizeException e) {
              e.printStackTrace();
          }
          return null;
      }
  
  
      /**
       * 私钥加密
       *
       * @param data       待加密数据
       * @param privateKey 密钥
       * @return byte[] 加密数据
       */
      public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) {
          try {
              // 得到私钥
              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);
          } catch (NoSuchAlgorithmException e) {
              e.printStackTrace();
          } catch (InvalidKeyException e) {
              e.printStackTrace();
          } catch (NoSuchPaddingException e) {
              e.printStackTrace();
          } catch (BadPaddingException e) {
              e.printStackTrace();
          } catch (InvalidKeySpecException e) {
              e.printStackTrace();
          } catch (IllegalBlockSizeException e) {
              e.printStackTrace();
          }
          return null;
      }
  
  
      /**
       * 公钥解密
       *
       * @param data      待解密数据
       * @param publicKey 公钥
       * @return byte[] 解密数据
       */
      public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) {
          try {
              // 得到公钥
              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);
          } catch (InvalidKeyException e) {
              e.printStackTrace();
          } catch (NoSuchAlgorithmException e) {
              e.printStackTrace();
          } catch (NoSuchPaddingException e) {
              e.printStackTrace();
          } catch (BadPaddingException e) {
              e.printStackTrace();
          } catch (InvalidKeySpecException e) {
              e.printStackTrace();
          } catch (IllegalBlockSizeException e) {
              e.printStackTrace();
          }
          return null;
      }
  
  
      /**
       * 使用私钥进行解密
       *
       * @param encrypted  待解密数据
       * @param privateKey 私钥
       * @return 解密后的数据
       */
      public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) {
          try {
              // 得到私钥
              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);
              return cp.doFinal(encrypted);
          } catch (InvalidKeyException e) {
              e.printStackTrace();
          } catch (NoSuchAlgorithmException e) {
              e.printStackTrace();
          } catch (NoSuchPaddingException e) {
              e.printStackTrace();
          } catch (BadPaddingException e) {
              e.printStackTrace();
          } catch (InvalidKeySpecException e) {
              e.printStackTrace();
          } catch (IllegalBlockSizeException e) {
              e.printStackTrace();
          }
          return null;
      }
  
  
      /**
       * 用公钥对字符串进行分段加密
       * <p>
       * RSA 非对称加密内容长度有限制，1024 位 key 的最多只能加密 127 位数据，
       * 否则就会报错(javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes)
       *
       * @param data      待加密数据
       * @param publicKey 公钥
       * @return 加密后的数据
       */
      public static byte[] encryptByPublicKeyForSpilt(byte[] data, byte[] publicKey) {
          int dataLen = data.length;
          if (dataLen <= DEFAULT_BUFFERSIZE) {
              return encryptByPublicKey(data, publicKey);
          }
          List<Byte> allBytes = new ArrayList<Byte>(2048);
          int bufIndex = 0;
          int subDataLoop = 0;
          byte[] buf = new byte[DEFAULT_BUFFERSIZE];
          for (int i = 0; i < dataLen; i++) {
              buf[bufIndex] = data[i];
              if (++bufIndex == DEFAULT_BUFFERSIZE || 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_BUFFERSIZE, dataLen - i - 1)];
                  }
              }
          }
          byte[] bytes = new byte[allBytes.size()];
          {
              int i = 0;
              for (Byte b : allBytes) {
                  bytes[i++] = b.byteValue();
              }
          }
          return bytes;
      }
  
  
      /**
       * 私钥分段加密
       *
       * @param data       要加密的原始数据
       * @param privateKey 密钥
       * @return 加密后的数据
       */
      public static byte[] encryptByPrivateKeyForSpilt(byte[] data, byte[] privateKey) {
          int dataLen = data.length;
          if (dataLen <= DEFAULT_BUFFERSIZE) {
              return encryptByPrivateKey(data, privateKey);
          }
          List<Byte> allBytes = new ArrayList<Byte>(2048);
          int bufIndex = 0;
          int subDataLoop = 0;
          byte[] buf = new byte[DEFAULT_BUFFERSIZE];
          for (int i = 0; i < dataLen; i++) {
              buf[bufIndex] = data[i];
              if (++bufIndex == DEFAULT_BUFFERSIZE || 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_BUFFERSIZE, dataLen - i - 1)];
                  }
              }
          }
          byte[] bytes = new byte[allBytes.size()];
          {
              int i = 0;
              for (Byte b : allBytes) {
                  bytes[i++] = b.byteValue();
              }
          }
          return bytes;
      }
  
  
      /**
       * 公钥分段解密
       *
       * @param encrypted 待解密数据
       * @param publicKey 密钥
       * @return 解密后的数据
       */
      public static byte[] decryptByPublicKeyForSpilt(byte[] encrypted, byte[] publicKey) {
          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.byteValue();
              }
          }
          return bytes;
      }
  
  
      /**
       * 使用私钥分段解密
       *
       * @param encrypted  待加密数据
       * @param privateKey 私钥
       * @return 加密后的数据
       */
      public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted, byte[] privateKey) {
          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.byteValue();
              }
          }
          return bytes;
      }
  }
  