zoukankan      html  css  js  c++  java
  • 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',
                  })
                }
              })
            })
          }
    

    本文来自博客园,作者:huhy,转载请注明原文链接:https://www.cnblogs.com/huhongy/p/15047595.html

  • 相关阅读:
    php获取OS信息
    坑爹的IE quirk模式
    [转]mysql privileges
    [转]VSFTPD的设置选项
    php性能分析工具xhprof
    php扩展安装
    又是万恶的IE....6
    ASP.NET操作文件(文件夹)简单生成html操作示例
    asp.net文件操作类
    c++/clr与c#的性能比较
  • 原文地址:https://www.cnblogs.com/huhongy/p/15047595.html
Copyright © 2011-2022 走看看