rsa加解密代码实现

rsa加解密

package com.aab.common.utils.ssoutils;


import com.aab.pojo.PayDO;
import com.alibaba.fastjson.JSON;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * RSA 工具类。提供加密,解密,生成密钥对等方法。
 * 需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。
 *
 */
@Component
public class RSAUtil {


	private String RSAKeyStore = "src/RSA/text.txt";
	private HashMap<String, KeyPair> keyMap = new HashMap<String, KeyPair>(50);
	private static BouncyCastleProvider bouncyCastleProvider=null;


	private static String algorithm = "RSA"; //$NON-NLS-1$
	private static final int MAX_ENCRYPT_BLOCK = 117;
	private static final int MAX_DECRYPT_BLOCK = 128;

	/**
	 * * 生成密钥对 *
	 *
	 * @return KeyPair *
	 * @throws EncryptException
	 */
	public String generateKeyPair() throws Exception {
		try {
			KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",
					getInstanceprovider());
			final int KEY_SIZE = 512;// 没什么好说的了,这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低
			keyPairGen.initialize(KEY_SIZE, new SecureRandom());
			KeyPair keyPair = keyPairGen.generateKeyPair();
			RSAPublicKey rsap = (RSAPublicKey) keyPair.getPublic();
			// saveKeyPair(keyPair);
			keyMap.put(rsap.getModulus().toString(16), keyPair);
			// System.out.println(rsap.getPublicExponent().toString(16));
			return rsap.getModulus().toString(16);
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}
	}

	/**
	 * 获取私钥
	 *
	 * @return
	 * @throws Exception
	 */
	public KeyPair getKeyPair() throws Exception {
		FileInputStream fis = new FileInputStream(RSAKeyStore);
		ObjectInputStream oos = new ObjectInputStream(fis);
		KeyPair kp = (KeyPair) oos.readObject();
		oos.close();
		fis.close();
		return kp;
	}

	/**
	 * 保存私钥
	 *
	 * @param KeyPair
	 *            *
	 * @author yuhaitao
	 * */
	public void saveKeyPair(KeyPair kp) throws Exception {

		FileOutputStream fos = new FileOutputStream(RSAKeyStore);
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		// 生成密钥
		oos.writeObject(kp);
		oos.close();
		fos.close();
	}

	/**
	 * * 生成公钥 *
	 *
	 * @param modulus
	 *            *
	 * @param publicExponent
	 *            *
	 * @return RSAPublicKey *
	 * @throws Exception
	 */
	public RSAPublicKey generateRSAPublicKey(byte[] modulus,
											 byte[] publicExponent) throws Exception {
		KeyFactory keyFac = null;
		try {
			keyFac = KeyFactory.getInstance("RSA",
					getInstanceprovider());
		} catch (NoSuchAlgorithmException ex) {
			throw new Exception(ex.getMessage());
		}

		RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(
				modulus), new BigInteger(publicExponent));
		try {
			return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
		} catch (InvalidKeySpecException ex) {
			throw new Exception(ex.getMessage());
		}
	}

	/**
	 * * 生成私钥 *
	 *
	 * @param modulus
	 *            *
	 * @param privateExponent
	 *            *
	 * @return RSAPrivateKey *
	 * @throws Exception
	 */
	public RSAPrivateKey generateRSAPrivateKey(byte[] modulus,
											   byte[] privateExponent) throws Exception {
		KeyFactory keyFac = null;
		try {
			keyFac = KeyFactory.getInstance("RSA",
					getInstanceprovider());
		} catch (NoSuchAlgorithmException ex) {
			throw new Exception(ex.getMessage());
		}

		RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(
				modulus), new BigInteger(privateExponent));
		try {
			return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
		} catch (InvalidKeySpecException ex) {
			throw new Exception(ex.getMessage());
		}
	}

	/**
	 * * 加密 *
	 *
	 * @param key
	 *            加密的密钥 *
	 * @param data
	 *            待加密的明文数据 *
	 * @return 加密后的数据 *
	 * @throws Exception
	 */
	public byte[] encrypt(PublicKey pk, byte[] data) throws Exception {
		try {
			Cipher cipher = Cipher.getInstance("RSA",
					getInstanceprovider());
			cipher.init(Cipher.ENCRYPT_MODE, pk);
			int blockSize = cipher.getBlockSize();// 获得加密块大小,如:加密前数据为128个byte,而key_size=1024
			// 加密块大小为127
			// byte,加密后为128个byte;因此共有2个加密块,第一个127
			// byte第二个为1个byte
			int outputSize = cipher.getOutputSize(data.length);// 获得加密块加密后块大小
			int leavedSize = data.length % blockSize;
			int blocksSize = leavedSize != 0 ? data.length / blockSize + 1
					: data.length / blockSize;
			byte[] raw = new byte[outputSize * blocksSize];
			int i = 0;
			while (data.length - i * blockSize > 0) {
				if (data.length - i * blockSize > blockSize)
					cipher.doFinal(data, i * blockSize, blockSize, raw, i
							* outputSize);
				else
					cipher.doFinal(data, i * blockSize, data.length - i
							* blockSize, raw, i * outputSize);
				// 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到
				// ByteArrayOutputStream中,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了
				// OutputSize所以只好用dofinal方法。

				i++;
			}
			return raw;
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}
	}

	/**
	 * * 加密 *
	 *
	 * @param key
	 *            加密的密钥 *
	 * @param data
	 *            待加密的明文数据 *
	 * @return 加密后的数据 *
	 * @throws Exception
	 */
	public byte[] encrypt(PrivateKey pk, byte[] data) throws Exception {
		try {
			Cipher cipher = Cipher.getInstance("RSA",
					getInstanceprovider());
			cipher.init(Cipher.ENCRYPT_MODE, pk);
			int blockSize = cipher.getBlockSize();// 获得加密块大小,如:加密前数据为128个byte,而key_size=1024
			// 加密块大小为127
			// byte,加密后为128个byte;因此共有2个加密块,第一个127
			// byte第二个为1个byte
			int outputSize = cipher.getOutputSize(data.length);// 获得加密块加密后块大小
			int leavedSize = data.length % blockSize;
			int blocksSize = leavedSize != 0 ? data.length / blockSize + 1
					: data.length / blockSize;
			byte[] raw = new byte[outputSize * blocksSize];
			int i = 0;
			while (data.length - i * blockSize > 0) {
				if (data.length - i * blockSize > blockSize)
					cipher.doFinal(data, i * blockSize, blockSize, raw, i
							* outputSize);
				else
					cipher.doFinal(data, i * blockSize, data.length - i
							* blockSize, raw, i * outputSize);
				// 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到
				// ByteArrayOutputStream中,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了
				// OutputSize所以只好用dofinal方法。

				i++;
			}
			return raw;
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}
	}


	/**
	 *
	 * @param pk
	 *            公钥
	 * @param pw
	 *            密码
	 * @return 解密后的密码
	 * @throws Exception
	 * @author yuhaitao
	 */
	public String decryptString(String pk, String word) throws Exception {
		KeyPair privateKey = keyMap.get(pk);
		if (privateKey == null || StringUtils.isBlank(word)) {
			return null;
		}
		byte[] en_data = Hex.decodeHex(word.toCharArray());
		byte[] data = decrypt(privateKey.getPrivate(), en_data);
		StringBuffer sb = new StringBuffer();
		sb.append(new String(data));
		return sb.reverse().toString();
	}

	public void deletekeyPair(String pk) {
		if (keyMap.containsKey(pk)) {
			keyMap.remove(pk);
		}
	}

	/**
	 * * 解密 *
	 *
	 * @param key
	 *            解密的密钥 *
	 * @param raw
	 *            已经加密的数据 *
	 * @return 解密后的明文 *
	 * @throws Exception
	 */
	public byte[] decrypt(PublicKey publickey, byte[] raw) throws Exception {
		Cipher ci = Cipher.getInstance("RSA", getInstanceprovider());
		ci.init(Cipher.DECRYPT_MODE, publickey);
		return ci.doFinal(raw);
	}

	/**
	 * * 解密 *
	 *
	 * @param key
	 *            解密的密钥 *
	 * @param raw
	 *            已经加密的数据 *
	 * @return 解密后的明文 *
	 * @throws Exception
	 */
	public byte[] decrypt(PrivateKey privateKey, byte[] raw) throws Exception {
		Cipher ci = Cipher.getInstance("RSA", getInstanceprovider());
		ci.init(Cipher.DECRYPT_MODE, privateKey);
		return ci.doFinal(raw);
	}

	/**
	 * 生成公钥和私钥
	 * @throws NoSuchAlgorithmException
	 * by wuym 20161014
	 */
	public static HashMap<String, String> getKeys() throws NoSuchAlgorithmException{
		HashMap<String, String> map = new HashMap<String, String>();
		KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
		keyPairGen.initialize(512);
		KeyPair keyPair = keyPairGen.generateKeyPair();
		RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
		RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
		String modulus = publicKey.getModulus().toString(16);
		String publicexponent = publicKey.getPublicExponent().toString(16);
		String privateexponent = privateKey.getPrivateExponent().toString(16);
		map.put("publicexponent", publicexponent);
		map.put("privateexponent", privateexponent);
		map.put("modulus", modulus);
		return map;
	}

	/**
	 * 使用模和指数生成RSA公钥
	 * 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
	 * /None/NoPadding】
	 * @param modulus  模
	 * @param exponent  指数
	 * @return
	 * by wuym 20161014
	 */
	public static RSAPublicKey getPublicKey(String modulus, String exponent) {
		try {
			BigInteger b1 = new BigInteger(modulus,16);
			BigInteger b2 = new BigInteger(exponent,16);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
			return (RSAPublicKey) keyFactory.generatePublic(keySpec);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 使用模和指数生成RSA私钥
	 * 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
	 * /None/NoPadding】
	 * @param modulus 模
	 * @param exponent 指数
	 * @return
	 * by wuym 20161014
	 */
	public static RSAPrivateKey getPrivateKey(String modulus, String exponent) {
		try {
			BigInteger b1 = new BigInteger(modulus,16);
			BigInteger b2 = new BigInteger(exponent,16);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2);
			return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public static synchronized BouncyCastleProvider getInstanceprovider() {
        if (bouncyCastleProvider == null) {  
            bouncyCastleProvider = new BouncyCastleProvider();
        }  
        return bouncyCastleProvider;  
    }

	/**
	 * 随机生成密钥对
	 * @throws NoSuchAlgorithmException
	 */
	public static Map<String, String> genKeyPair() throws NoSuchAlgorithmException {
		Map<String, String> keyMap = new HashMap<String, String>();
		// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
		KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
		// 初始化密钥对生成器,密钥大小为96-1024位
		keyPairGen.initialize(1024,new SecureRandom());
		// 生成一个密钥对,保存在keyPair中
		KeyPair keyPair = keyPairGen.generateKeyPair();
		RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();   // 得到私钥
		RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 得到公钥
		String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
		// 得到私钥字符串
		String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
		// 将公钥和私钥保存到Map
		keyMap.put("puk",publicKeyString);  //puk表示公钥
		keyMap.put("prk",privateKeyString);  //prk表示私钥
		return keyMap;
	}
	/**
	 * RSA公钥加密
	 *
	 * @param str
	 *            加密字符串
	 * @param publicKey
	 *            公钥
	 * @return 密文
	 * @throws Exception
	 *             加密过程中的异常信息
	 */
	public static String encrypt( String str, String publicKey ) throws Exception{
		//base64编码的公钥
		byte[] decoded = Base64.decodeBase64(publicKey);
		RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
		//RSA加密
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.ENCRYPT_MODE, pubKey);
		String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
		return outStr;
	}

	/**
	 * RSA私钥解密
	 *
	 * @param str
	 *            加密字符串
	 * @param privateKey
	 *            私钥
	 * @return 铭文
	 * @throws Exception
	 *             解密过程中的异常信息
	 */
	public static String decrypt(String str, String privateKey) throws Exception{
		//64位解码加密后的字符串
		byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
		//base64编码的私钥
		byte[] decoded = Base64.decodeBase64(privateKey);
		RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
		//RSA解密
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, priKey);
		String outStr = new String(cipher.doFinal(inputByte));
		return outStr;
	}
	

	public static void main(String[] args) throws Exception {
		Map<String, String> keyMap = genKeyPair();
		/**
		 *
		 * 参数
		 *   diningroomid   餐厅id
		 *   amount			金额
		 */
		PayDO payDO = new PayDO();
		payDO.setDiningroomid("123");
		payDO.setAmount("10");
		//先作为一个对象json 化  再使用公钥加密
		String messageEn = encrypt(JSON.toJSONString(payDO),keyMap.get("puk"));
		System.out.println(messageEn);
		String messageDe = decrypt(messageEn,keyMap.get("prk"));
		PayDO aDo = JSON.parseObject(messageDe, PayDO.class);
		System.out.println(aDo.getAmount());
		System.out.println(aDo.getDiningroomid());

		String m1 = testEncrypt(JSON.toJSONString(payDO),keyMap.get("prk"));
		System.out.println(m1);
		String m2 = testDecrypt(m1,keyMap.get("puk"));
		System.out.println(m2);

	}
}
@Autowired
    private RedisUtil redisUtil;
    /**
     * 免密支付
     *
     **/
    @GetMapping("payfor")
    @ApiOperation("工行调用支付")
    public ResponseContent icbcPay(@RequestParam("pukData") @NotNull String pukData) throws Exception {

        log.info(" 加密数据 -------> " + pukData);
        //获取当前用户的私钥
        CurrentUser currentUser = SysUserContext.getCurrentSysUser();
        String decrypt = RSAUtil.decrypt(pukData, redisUtil.get(currentUser.getUserId()));
        log.info(" 解密数据 -------> " + decrypt);
        // 数据转换
        PayDO aDo = JSON.parseObject(decrypt, PayDO.class);
        redisUtil.delete(currentUser.getUserId());
        //return setSuccessResult(aDo.toString());
        Boolean payBusiness = icbcPayBusinessService.icbcPayBusiness(aDo.getDiningroomid(), aDo.getAmount());
        if (payBusiness){
            return setSuccessResult("支付操作成功"+aDo.toString());
        }else {
            return setErrorResult("支付操作失败");
        }
    }

    /**
     *  获取公钥  保存私钥
     * @return
     * @throws Exception
     */
    @GetMapping("getPublicKey")
    @ApiOperation("获取共钥")
    public String getPublicKey() throws Exception {
        Map<String, String> keyMap = RSAUtil.genKeyPair();
        CurrentUser currentUser = SysUserContext.getCurrentSysUser();
        redisUtil.set(currentUser.getUserId(),keyMap.get("prk"));
        log.info("puk --->" + keyMap.get("puk"));
        log.info("prk --->" + keyMap.get("prk"));
        return keyMap.get("puk");
    }
引入js: jsencrypt.js   https://blog-static.cnblogs.com/files/huhongy/jsencrypt.js

confirmMoney() {
        console.log('金额', this.money);
        if (+this.money<0) {
          wx.showToast({
            title:'输入金额不能小于等于零',
            icon:'none',
          })
          return
        }
        let pubKey = ''
        get(Service.getRSAPublicKey, {}, res=>{
          console.log('公钥', res)
          pubKey = res
          jsEncrypt.setPublicKey(pubKey)

          let params = {
            amount:this.money,
            diningroomid:this.shopId
          }
          get(Service.withoutCodePay, {
            pukData: jsEncrypt.encrypt(JSON.stringify(params))
          }, res => {
            console.log('免密支付', res)
            if(res.code == 0){
              wx.redirectTo({
                url:'/pages/my/hint/main?money=' + this.money
              })
            }else{
              wx.showToast({
                title:res.message,
                icon:'none',
              })
            }
          })
        })
      }
posted @ 2021-07-23 10:09  陽66  阅读(291)  评论(0编辑  收藏  举报