Java实现RSA算法

RSA是一种非对称加密技术,可以用公钥加密再用私钥解密,反之亦然。RSAUtils只实现了公钥加密和私钥解密。实现的过程中踩了几个坑,不过还是不太理解为什么用RSA加解密之后还要用Base64进行加解码。

package com.yy.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.sun.org.apache.xml.internal.security.utils.Base64;
/**
 * @Description: A  encode and decode Utils class, based RSA algorithm.
 * @author: leijing
 * @date: 2016年11月10日 上午11:35:25
 */
public class RSAUtils {
	private static Logger logger = Logger.getLogger(RSAUtils.class);
	/* 指定加密算法为DESede */
	private static final String ALGORITHM = "RSA";

	/* 指定key的大小 */
	private static final int KEYSIZE = 1024;

	private KeyPair keyPair = null;

	private String id = "";

	private static final String BASE_FILE_PATH = Thread.currentThread().getContextClassLoader().getResource("").getPath();

	private static final String  FILE_SUFFIX = ".txt";

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

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

	/**	
	 * @Description:  create a RSAUtils object
	 * @param id
	 * @return: RSAUtils	
	 * @author: leijing	
	 * @date: 2016年11月10日 上午11:37:13
	 */
	public static RSAUtils newInstance(String id){
		RSAUtils rsaUtils = new RSAUtils();
		rsaUtils.id = id;
		rsaUtils.init();
		return rsaUtils;
	}

	/**
	
	 * @Description: init KeyPair object	
	 * @return: void	
	 * @author: leijing	
	 * @date: 2016年11月10日 上午11:36:26
	 */
	private  void init(){	
		try{
			File file = genFile();
			if(!file.exists()){//if file isn't exist, execute genKeyPair function			
				genKeyPair();
				if(null != this.keyPair){					
					writeObjectToFile(file, this.keyPair);
				}

			}else{//if file is exist,read object from file	
				Object obj = readObjectFromFile(file);
				if(null != obj){
					this.keyPair = (KeyPair)obj;
				}

			}

		}catch(Exception e){
			logger.error("genKeyPair error:",e);
		}
	}

	/**
	 * @Description: read KeyPair object from file	
	 * @param file
	 * @throws Exception	
	 * @return: Object	
	 * @author: leijing	
	 * @date: 2016年11月10日 上午11:39:32
	 */
	public Object readObjectFromFile(File file) throws Exception{
		ObjectInputStream  ois = null;
		Object obj = null;
		try {
			if(!file.exists()){
				logger.error("file not found!");				
			}
			ois = new ObjectInputStream(new FileInputStream(file));
			obj = ois.readObject();


		} catch (Exception e) {
			logger.error("readFromFile erroe:",e);
		}finally{
			if (null != ois) {
				ois.close();
			}
		}

		return obj;
	}

	/**
	 * @Description: generate a KeyPair object	
	 * @return: void	
	 * @author: leijing 	
	 * @date: 2016年11月10日 上午11:40:30
	 */
	private void genKeyPair(){
		try{		
			/*创建一个KeyPairGenerator对象 */
			KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);			
			kpg.initialize(KEYSIZE);
			/*生成密匙对 */
			this.keyPair = kpg.generateKeyPair();	
		}catch(Exception e){
			logger.error("genKeyPair error:",e);
		}		
	}
	
	/**
	 * @Description: get a File object	
	 * @return: File	
	 * @author: leijing 	
	 * @date: 2016年11月10日 上午11:41:20
	 */
	private File genFile(){
		String filePath = genFilePath();
		File file = new File(filePath);
		return file;
	}
	/**
	 * @Description: get file path
	 * @return: String	
	 * @author: leijing 	
	 * @date: 2016年11月10日 上午11:41:10
	 */
	private String genFilePath(){

		if(StringUtils.isNotBlank(id)){
			return BASE_FILE_PATH.concat(id).concat(FILE_SUFFIX);
		}else{
			return "";
		}
	}
	/**
	 * @Description: get publickey	
	 * @return: String	
	 * @author: leijing 	
	 * @date: 2016年11月10日 上午11:41:50
	 */
	private String getPublicKey(){
		return Base64Utils.encode(this.keyPair.getPublic().getEncoded());
	}
	/**
	 * @Description: get privateKey
	 * @return: String	
	 * @author: leijing 	
	 * @date: 2016年11月10日 上午11:42:30
	 */
	private String getPrivateKey(){
		return Base64Utils.encode(this.keyPair.getPrivate().getEncoded());
	}
	/**
	 * @Description: decode by privatekey	
	 * @param cryptograph
	 * @return: String
	 * @author: leijing  
	 * @date: 2016年11月10日 上午11:43:29
	 */
	public String decode(byte[] cryptograph){
		ByteArrayOutputStream out = new ByteArrayOutputStream();  
		try{
			if(null == keyPair || null == keyPair.getPrivate()){
				logger.info("decode skipped!Because keyPair is null!");
				return "";
			}			

//			String key = getPrivateKey();
//			byte[] keyBytes = Base64Utils.decode(key);
//			PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);  
//			KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
//			Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);  
//			Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
			Key privateKey = keyPair.getPrivate();
			Cipher cipher = Cipher.getInstance(ALGORITHM);
			cipher.init(Cipher.DECRYPT_MODE, privateKey);
			if(cryptograph.length <= MAX_DECRYPT_BLOCK){//不大于128字节的一次性解密
				byte[] bytes = cipher.doFinal(cryptograph);
				out.write(bytes ,0,bytes.length);
			}else{//大于128字节就要分段解密
				for(int i = 0 ; i < cryptograph.length; i+= MAX_DECRYPT_BLOCK){
					int inputLength = (cryptograph.length - i >= MAX_DECRYPT_BLOCK )?MAX_DECRYPT_BLOCK: (cryptograph.length - i);
					byte[] bytes = cipher.doFinal(cryptograph, i, inputLength);
					out.write(bytes ,0,bytes.length);
				}
			}

		}
		catch(Exception e){
			logger.error("decode error:",e);
		}finally{
			try {
				out.close();
			} catch (IOException e) {
				logger.error("close ByteArrayOutputStream error:",e);
			}
		}	
		return new String(out.toByteArray());
	}
	/**
	 * @Description: encode by publickey	
	 * @param source
	 * @return: String
	 * @author: leijing  
	 * @date: 2016年11月10日 上午11:45:29
	 */
	public String encode(byte[] source){
		ByteArrayOutputStream out = new ByteArrayOutputStream();  
		try{
			
			if(null == keyPair || null == keyPair.getPublic()){
				logger.info("encode skipped!Because keyPair is null!");
				return "";
			}
			
//			String key = getPublicKey();
//			byte[] keyBytes = Base64Utils.decode(key);
//			X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);  
//			KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
//			Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);  
//			Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
			Key publicKey = keyPair.getPublic();
			Cipher cipher = Cipher.getInstance(ALGORITHM);
			cipher.init(Cipher.ENCRYPT_MODE, publicKey);

			if(source.length <= MAX_ENCRYPT_BLOCK){//不大于117字节的一次性加密
				byte[] bytes = cipher.doFinal(source);	
				out.write(bytes ,0,bytes.length);
			}else{//大于117字节分段加密
				for(int i = 0 ; i < source.length; i+= MAX_ENCRYPT_BLOCK){
					int inputLength = (source.length - i >= MAX_ENCRYPT_BLOCK )?MAX_ENCRYPT_BLOCK: (source.length - i);
					byte[] bytes = cipher.doFinal(source, i, inputLength);
					out.write(bytes ,0,bytes.length);
				}
			}

		}catch(Exception e){
			logger.error("encode error:",e);
		}finally{
			try {
				out.close();
			} catch (IOException e) {
				logger.error("close ByteArrayOutputStream error:",e);
			}
		}
		return Base64.encode(out.toByteArray());
	}
	/**
	 * @Description: write Object to File
	 * @param file
	 * @param obj	
	 * @return: void	
	 * @author: leijing	
	 * @date: 2016年11月10日 上午11:54:40
	 */
	private void writeObjectToFile(File file , Object obj) {
		long start = System.currentTimeMillis();		
		ObjectOutputStream oos = null;
		try{
			if(!file.exists()){
				file.createNewFile();
			}

			oos = new ObjectOutputStream(new FileOutputStream(file));
			oos.writeObject(obj);
			oos.flush();

		}catch(Exception e){
			logger.error("writeTofile error:",e);
		}finally{
			if(null != oos){
				try {
					oos.close();
				} catch (IOException e) {
					logger.error("file close error:",e);
				}
			}
		}
		logger.info("write object to file successful! Spent "+(System.currentTimeMillis() - start) +"ms.");
	}
	
	public static void main(String[] args) {
		try{
			RSAUtils rsaUtils = RSAUtils.newInstance("leijing");
			String source = "Welcome to YY Inc!";
			logger.info("source:"+source);
			String cryptograph = rsaUtils.encode(source.getBytes());
			logger.info("cryptograph:"+cryptograph);
			byte[] decodedData = Base64Utils.decode(cryptograph);			
			String sourceStr = rsaUtils.decode(decodedData);
			logger.info("sourceStr:"+sourceStr);
		}catch(Exception e){
			logger.error("main error:",e);
		}
	}

}

运行结果:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值