记一次RSA加密解密方法

这是同事写的一个方法,我整理出来,并记录下来,方便下次开发使用。

只有两个类,一个是RSA方法类,一个是测试类。


import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;

import org.bouncycastle.jce.provider.BouncyCastleProvider;


/**
 * RSA加密工具类
 */

public class RSAUtils {

  /** 
   * 加密算法RSA 
   */
  public static final String KEY_ALGORITHM = "RSA";


  public static final String RSA_ALGORITHM = "RSA/None/PKCS1Padding";

  /** 
   * 签名算法 
   */
  public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

  /** 
   * 获取公钥的key 
   */
  private static final String PUBLIC_KEY = "RSAPublicKey";

  /** 
   * 获取私钥的key 
   */
  private static final String PRIVATE_KEY = "RSAPrivateKey";

  /**
   * RSA最大加密明文大小
   */
  private static final int MAX_ENCRYPT_BLOCK = 64;

  /** 
   * RSA最大解密密文大小 
   */
  private static final int MAX_DECRYPT_BLOCK = 75;

  /**
   * RSA密钥长度
   */
  private static final int INITIAL_KEY_SIZE = 600;

  static {
    Security.addProvider(new BouncyCastleProvider());
  }

  /**
   * <p> 
   * 生成密钥对(公钥和私钥) 
   * </p> 
   *  
   * @return 
   * @throws Exception 
   */
  public static Map<String, Object> genKeyPair() throws Exception {
    KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM, new BouncyCastleProvider());
    keyPairGen.initialize(INITIAL_KEY_SIZE);
    KeyPair keyPair = keyPairGen.generateKeyPair();
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    Map<String, Object> keyMap = new HashMap<String, Object>(2);
    keyMap.put(PUBLIC_KEY, publicKey);
    keyMap.put(PRIVATE_KEY, privateKey);
    return keyMap;
  }

  /**
   * <p> 
   * 用私钥对信息生成数字签名 
   * </p> 
   *  
   * @param data 已加密数据 
   * @param privateKey 私钥(BASE64编码) 
   *  
   * @return 
   * @throws Exception 
   */
  public static String sign(byte[] data, String privateKey) throws Exception {
    byte[] keyBytes = Base64.getDecoder().decode(privateKey);
    PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
    Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
    signature.initSign(privateK);
    signature.update(data);
    return new String(Base64.getEncoder().encode(signature.sign()));
  }

  /**  
   * <p> 
   * 校验数字签名 
   * </p> 
   *  
   * @param data 已加密数据 
   * @param publicKey 公钥(BASE64编码) 
   * @param sign 数字签名 
   *  
   * @return 
   * @throws Exception 
   *  
   */
  public static boolean verify(byte[] data, String publicKey, String sign)
      throws Exception {
    byte[] keyBytes = Base64.getDecoder().decode(publicKey);
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    PublicKey publicK = keyFactory.generatePublic(keySpec);
    Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
    signature.initVerify(publicK);
    signature.update(data);
    return signature.verify(Base64.getDecoder().decode(sign));
  }

  /**
   * <P> 
   * 私钥解密 
   * </p> 
   *  
   * @param encryptedData 已加密数据 
   * @param privateKey 私钥(BASE64编码) 
   * @return 
   * @throws Exception 
   */
  public static String decryptByPrivateKey(String encrypted, String privateKey)
      throws Exception {
    byte[] encryptedData = Base64.getDecoder().decode(encrypted);
    byte[] keyBytes = Base64.getDecoder().decode(privateKey);
    PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM, "BC");
    Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
    Cipher cipher = Cipher.getInstance(RSA_ALGORITHM, "BC");
    cipher.init(Cipher.DECRYPT_MODE, privateK);
    int inputLen = encryptedData.length;
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    int offSet = 0;
    byte[] cache;
    int i = 0;
    /** 对数据分段解密 */
    while (inputLen - offSet > 0) {
      if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
        cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
      } else {
        cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
      }
      out.write(cache, 0, cache.length);
      i++;
      offSet = i * MAX_DECRYPT_BLOCK;
    }
    byte[] decryptedData = out.toByteArray();
    out.close();
    return new String(decryptedData, "UTF-8");
  }

  /**
   * <p> 
   * 公钥解密 
   * </p> 
   *  
   * @param encrypted 已加密数据 
   * @param publicKey 公钥(BASE64编码) 
   * @return 
   * @throws Exception 
   */
  public static String decryptByPublicKey(String encrypted, String publicKey)
      throws Exception {
    byte[] encryptedData = Base64.getDecoder().decode(encrypted);
    byte[] keyBytes = Base64.getDecoder().decode(publicKey);
    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM, "BC");
    Key publicK = keyFactory.generatePublic(x509KeySpec);
    Cipher cipher = Cipher.getInstance(RSA_ALGORITHM, "BC");
    cipher.init(Cipher.DECRYPT_MODE, publicK);
    int inputLen = encryptedData.length;
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    int offSet = 0;
    byte[] cache;
    int i = 0;
    /** 对数据分段解密 */
    while (inputLen - offSet > 0) {
      if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
        cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
      } else {
        cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
      }
      out.write(cache, 0, cache.length);
      i++;
      offSet = i * MAX_DECRYPT_BLOCK;
    }
    byte[] decryptedData = out.toByteArray();
    out.close();
    return new String(decryptedData, "UTF-8");
  }

  /**
   * <p> 
   * 公钥加密 
   * </p> 
   *  
   * @param source 源数据(已通过MD5加密) 
   * @param publicKey 公钥(BASE64编码) 
   * @return 
   * @throws Exception 
   */
  public static String encryptByPublicKey(String source, String publicKey)
      throws Exception {
    byte[] data = source.getBytes();
    byte[] keyBytes = Base64.getDecoder().decode(publicKey);
    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM, "BC");
    Key publicK = keyFactory.generatePublic(x509KeySpec);
    /** 对数据加密 */
    Cipher cipher = Cipher.getInstance(RSA_ALGORITHM, "BC");
    cipher.init(Cipher.ENCRYPT_MODE, publicK);
    int inputLen = data.length;
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    int offSet = 0;
    byte[] cache;
    int i = 0;
    /** 对数据分段加密 */
    while (inputLen - offSet > 0) {
      if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
        cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
      } else {
        cache = cipher.doFinal(data, offSet, inputLen - offSet);
      }
      out.write(cache, 0, cache.length);
      i++;
      offSet = i * MAX_ENCRYPT_BLOCK;
    }
    byte[] encryptedData = out.toByteArray();
    out.close();
    return new String(Base64.getEncoder().encode(encryptedData));
  }

  /** 
   * <p> 
   * 私钥加密 
   * </p> 
   *  
   * @param source 源数据(已通过MD5加密) 
   * @param privateKey 私钥(BASE64编码) 
   * @return 
   * @throws Exception 
   */
  public static String encryptByPrivateKey(String source, String privateKey)
      throws Exception {
    byte[] data = source.getBytes();
    byte[] keyBytes = Base64.getDecoder().decode(privateKey);
    PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM, "BC");
    Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
    Cipher cipher = Cipher.getInstance(RSA_ALGORITHM, "BC");
    cipher.init(Cipher.ENCRYPT_MODE, privateK);
    int inputLen = data.length;
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    int offSet = 0;
    byte[] cache;
    int i = 0;
    /** 对数据分段加密 */
    while (inputLen - offSet > 0) {
      if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
        cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
      } else {
        cache = cipher.doFinal(data, offSet, inputLen - offSet);
      }
      out.write(cache, 0, cache.length);
      i++;
      offSet = i * MAX_ENCRYPT_BLOCK;
    }
    byte[] encryptedData = out.toByteArray();
    out.close();
    return new String(Base64.getEncoder().encode(encryptedData));
  }

  /**
   * <p> 
   * 获取私钥 
   * </p> 
   *  
   * @param keyMap 密钥对 
   * @return 
   * @throws Exception 
   */
  public static String getPrivateKey(Map<String, Object> keyMap)
      throws Exception {
    Key key = (Key) keyMap.get(PRIVATE_KEY);
    return new String(Base64.getEncoder().encode(key.getEncoded()));
  }

  /**
   * <p> 
   * 获取公钥 
   * </p> 
   *  
   * @param keyMap 密钥对 
   * @return 
   * @throws Exception 
   */
  public static String getPublicKey(Map<String, Object> keyMap)
      throws Exception {
    Key key = (Key) keyMap.get(PUBLIC_KEY);
    return new String(Base64.getEncoder().encode(key.getEncoded()));
  }
}

import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * RSA数字签名测试类
 * 
 */

public class RSASignEngine {

  private static RSASignEngine instance;

  private RSASignEngine() {
  }

  public static RSASignEngine getSingleton() {
    if (instance == null) {
      synchronized (RSASignEngine.class) {
        if (instance == null) {
          instance = new RSASignEngine();
        }
      }
    }
    return instance;
  }

  public String generateSign(Map<String, String> params, String publicKey) throws Exception {
    /** 1、生成MD5字符串 */
    String md5Str = RSAMD5Util.generate(params, null);

    /** 2、使用公钥生成数字签名 */
    return RSAUtils.encryptByPublicKey(md5Str, publicKey);
  }

  public static void main(String[] args) throws Exception {
    String publicKey =      "公钥";
    String privateKey =     "私钥";

    /** 生成数字签名字符串 */

    //需要加密的字符串
    Map<String, String> paramMap = new HashMap<String, String>();
    paramMap.put("APPID_KEY", "1");
    paramMap.put("CONTENT", "{\"userName\":\"zhangsan\"}");
    String encodedData = RSASignEngine.getSingleton().generateSign(paramMap, publicKey);
    System.out.println("公钥加密后:" + encodedData);


    /** 验证数字签名字符串 */
    /** 1、使用私钥对数字签名进行解密,确定MD5字符串是否一致 */
    String dencodedData = RSAUtils.decryptByPrivateKey(encodedData, privateKey);
    System.out.println("私钥解密后:" + dencodedData);
    /** 2、使用私钥对接受到的签名字符串生成数字签名 */
    String sign = RSAUtils.sign(Base64.getDecoder().decode(encodedData), privateKey);
    System.out.println("私钥加密后:" + sign);
    /** 3、验证数字签名是否一致 */
    boolean status = RSAUtils.verify(Base64.getDecoder().decode(encodedData), publicKey, sign);
    System.out.println("签名是否一致:" + status);
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值