RSA分块加密实现

import java.io.ByteArrayOutputStream;
import java.io.IOException;
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.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

/**
 * @author zhang.xiaoming
 * @ClassName RsaUtil
 * @Description Rsa分段加密实现
 * @date 2018年3月13日 下午6:56:30
 * 
 */
public class RsaUtil {
	private static final String CHARSET = "UTF-8";
	private static final String RSA_ALGORITHM = "RSA";
	/** 针对 keysize = 1024 RSA最大加密明文大小 117 */
	private static final int MAX_ENCRYPT_BLOCK = 117;
	/**  针对 keysize = 1024  RSA最大解密密文大小  128*/
	private static final int MAX_DECRYPT_BLOCK = 128;

	/**
	 * keysize 1024
	 * @return
	 * @throws NoSuchAlgorithmException
	 */
	public static KeyPair createKey() throws NoSuchAlgorithmException {
		KeyPairGenerator generator = KeyPairGenerator.getInstance(RSA_ALGORITHM);
		generator.initialize(1024);
		KeyPair keyPair = generator.generateKeyPair();
		return keyPair;
	}

	/**
	 * 得到公钥
	 * @param publicKey
	 *            密钥字符串(经过base64编码)
	 * @throws InvalidKeySpecException
	 * @throws NoSuchAlgorithmException
	 * @throws Exception
	 */
	public static RSAPublicKey getPublicKey(String publicKey) throws InvalidKeySpecException, NoSuchAlgorithmException {
		KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
		RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
		return key;
	}

	/**
	 * 得到私钥
	 * 
	 * @param privateKey
	 *            密钥字符串(经过base64编码)
	 * @throws InvalidKeySpecException
	 * @throws NoSuchAlgorithmException
	 * @throws Exception
	 */
	public static RSAPrivateKey getPrivateKey(String privateKey) throws InvalidKeySpecException, NoSuchAlgorithmException {
		KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));
		RSAPrivateKey key = (RSAPrivateKey)keyFactory.generatePrivate(pkcs8KeySpec);
		return key;
	}

	/**
	 * 公钥加密
	 * 
	 * @param data
	 *            数据
	 * @param publicKey
	 *            公钥
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchPaddingException
	 * @throws InvalidKeyException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 * @throws IOException
	 * @throws InvalidKeySpecException 
	 */
	public static String publicEncrypt(String data, String publicKey) throws NoSuchAlgorithmException,
			NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, IOException, InvalidKeySpecException {
		Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
		PublicKey pk = getPublicKey(publicKey);
		cipher.init(Cipher.ENCRYPT_MODE, pk);
		byte[] dataByte = data.getBytes(CHARSET), cache;
		int dataLength = dataByte.length, offSet = 0, i = 0;
		try (ByteArrayOutputStream out = new ByteArrayOutputStream();) {
			// 数据分段加密
			while (dataLength - offSet > 0) {
				if (dataLength - offSet > MAX_ENCRYPT_BLOCK) {
					cache = cipher.doFinal(dataByte, offSet, MAX_ENCRYPT_BLOCK);
				} else {
					cache = cipher.doFinal(dataByte, offSet, dataLength - offSet);
				}
				out.write(cache, 0, cache.length);
				i++;
				offSet = i * MAX_ENCRYPT_BLOCK;
			}
			byte[] encryptData = out.toByteArray();
			return Base64.getEncoder().encodeToString(encryptData);
		}
	}

	/**
	 * 私钥解密
	 * 
	 * 解码关键(因为原始数据先geyBytes后再做Base64编码,此处getBytes后再还原回方可解密)
	 * 
	 * @param data
	 *            字符串
	 * @param privateKey
	 *            私钥
	 * @return
	 * @throws InvalidKeySpecException
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchPaddingException
	 * @throws InvalidKeyException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 * @throws IOException
	 */
	public static String privateDecrypt(String data, String privateKey)
			throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
			IllegalBlockSizeException, BadPaddingException, IOException {
		PrivateKey pbk = getPrivateKey(privateKey);
		Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
		cipher.init(Cipher.DECRYPT_MODE, pbk);
		//Base64做对称解码(一定要先把数据还原,否则解密失败---因为原始数据先geyBytes后再做Base64编码,此处getBytes后再还原回去)
		byte[] dataByte = Base64.getDecoder().decode(data.getBytes()), cache;
		int dataLength = dataByte.length, offSet = 0, i = 0;
		try (ByteArrayOutputStream out = new ByteArrayOutputStream();) {
			// 数据分段解密
			while (dataLength - offSet > 0) {
				if (dataLength - offSet > MAX_DECRYPT_BLOCK) {
					cache = cipher.doFinal(dataByte, offSet, MAX_DECRYPT_BLOCK);
				} else {
					cache = cipher.doFinal(dataByte, offSet, dataLength - offSet);
				}
				out.write(cache, 0, cache.length);
				i++;
				offSet = i * MAX_DECRYPT_BLOCK;
			}
			byte[] decryptedData = out.toByteArray();
			return new String(decryptedData, CHARSET);
		}
	}

	/**
	 * 私钥加密
	 * 
	 * @param data
	 *            数据
	 * @param privateKey
	 *            私钥
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchPaddingException
	 * @throws InvalidKeyException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 * @throws InvalidKeySpecException
	 * @throws IOException
	 */
	public static String privateEncrypt(String data, String privateKey)
			throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException,
			BadPaddingException, InvalidKeySpecException, IOException {
		Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
		PrivateKey pk = getPrivateKey(privateKey);
		cipher.init(Cipher.ENCRYPT_MODE, pk);
		byte[] dataByte = data.getBytes(CHARSET), cache;
		int dataLength = dataByte.length, offSet = 0, i = 0;
		try (ByteArrayOutputStream out = new ByteArrayOutputStream();) {
			// 数据分段加密
			while (dataLength - offSet > 0) {
				if (dataLength - offSet > MAX_ENCRYPT_BLOCK) {
					cache = cipher.doFinal(dataByte, offSet, MAX_ENCRYPT_BLOCK);
				} else {
					cache = cipher.doFinal(dataByte, offSet, dataLength - offSet);
				}
				out.write(cache, 0, cache.length);
				i++;
				offSet = i * MAX_ENCRYPT_BLOCK;
			}
			byte[] encryptedData = out.toByteArray();
			return Base64.getEncoder().encodeToString(encryptedData);
		}
	}

	/**
	 * 公钥解密
	 * 
	 * 解码关键(因为原始数据先geyBytes后再做Base64编码,此处getBytes后再还原回方可解密)
	 * 
	 * @param data
	 *            数据
	 * @param publicKey
	 *            公钥
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchPaddingException
	 * @throws InvalidKeyException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 * @throws InvalidKeySpecException
	 * @throws IOException
	 */
	public static String publicDecrypt(String data, String publicKey)
			throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException,
			BadPaddingException, InvalidKeySpecException, IOException {
		Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
		RSAPublicKey rsaPublicKey = getPublicKey(publicKey);
		cipher.init(Cipher.DECRYPT_MODE, rsaPublicKey);
		//Base64做对称解码
		byte[] dataByte = Base64.getDecoder().decode(data.getBytes()), cache;
		int dataLength = dataByte.length, offSet = 0, i = 0;
		try (ByteArrayOutputStream out = new ByteArrayOutputStream();) {
			 while (dataLength - offSet > 0) {  
		            if (dataLength - offSet > MAX_DECRYPT_BLOCK) {  
		                cache = cipher.doFinal(dataByte, offSet, MAX_DECRYPT_BLOCK);  
		            } else {  
		                cache = cipher.doFinal(dataByte, offSet, dataLength - offSet);  
		            }  
		            out.write(cache, 0, cache.length);  
		            i++;  
		            offSet = i * MAX_DECRYPT_BLOCK;  
		        }  
		        byte[] decryptedData = out.toByteArray();  
			return new String(decryptedData, CHARSET);
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值