Java实现RSA算法

来源:互联网 发布:胡夏 知乎 编辑:程序博客网 时间:2024/05/24 06:02

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 functiongenKeyPair();if(null != this.keyPair){writeObjectToFile(file, this.keyPair);}}else{//if file is exist,read object from fileObject 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 0
原创粉丝点击