RSA加密解密

参考了网上的一些资料:

http://blog.sina.com.cn/s/blog_76550fd7010147tp.html 

http://blog.csdn.net/centralperk/article/details/8538697

http://dustin.iteye.com/blog/763931

RSA算法密钥长度的选择是安全性和程序性能平衡的结果,密钥长度越长,安全性越好,加密解密所需时间越长。

1. 非对称加密算法中1024 bit密钥的强度相当于对称加密算法80bit密钥的强度。有资料上说以当前的软硬件水平,破解1024bit的RSA加密密文,需要一套10亿美金的系统使用若干十年的时间,所以2015年前,1024bit的还无需太担心暴力破解的危险。

2. 密钥长度增长一倍,公钥操作所需时间增加约4倍,私钥操作所需时间增加约8倍,公私钥生成时间约增长16倍。

3. 一次能加密的密文长度与密钥长度成正比, len_in_byte(raw_data) = len_in_bit(key)/8 -11,如1024bit的密钥,一次能加密的内容长度为 1024/8 -11 = 117 byte。所以非对称加密一般都用于加密对称加密算法的密钥,而不是直接加密内容。

4. 加密后密文的长度为密钥的长度,如密钥长度为1024b(128Byte),最后生成的密文固定为 1024b(128Byte)

现整理如下:

import java.io.*;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

public class RSAUtil{

    private  static final String KEY_ALGORITHM = "RSA";//签名算法 
	
    /**
     * RSA解密要求密文最大长度为128字节,加密明文最大长度117字节  
     * 如果加密数据过大需要在加密和解密的过程中需要分块进行
     * 块数=(明文长度(bytes)/(密钥长度(需要将bit转换为bytes)-11))向上取整,就是不满一片的按一片算
     * 所以密文的长度设置直接影响块数的大小,可以根据项目需要灵活分配分块的个数
     * RSA最大密文长度 单位:byte
     */
    private  static final int DECRYPT_LENGTH = 128;
    /**
     * RSA最大明文长度 单位:byte
     */
    private  static final int ENCRYPT_LENGTH = DECRYPT_LENGTH - 11;
    /**
	 *密钥长度 单位:bit  1byte=8bit 
	 *加密n byte的明文,需要至少(n+11)bytes的密钥
	 *因为该单位是bit 所以换算成bit就要乘以8
	 */
    private  static final int ENCRYTLENGTH = (ENCRYPT_LENGTH + 11) * 8;
    /**
     * 注意下面两个路径必须存在,否则在初始化过程中会发生异常
     */
    private  static final String PUBLICKEYPATH = "/home/key/public.key";
    private  static final String PRIVATEKEYPATH = "/home/key/private.key";
    private  static RSAPublicKey publicKey;
    private  static RSAPrivateKey privateKey;
    public enum KeyType{ PUBLIC,PRIVATE; }

    static{
        try {
            initKey(true);
        } catch (Exception e) {
        	e.printStackTrace();
            throw new RuntimeException("初始化key异常!!");
        }
    }
    
    public static void main(String[] args) throws Exception {
        String data = "hello world";
        File publickeyFile = new File(PUBLICKEYPATH);
        File privatekeyFile = new File(PRIVATEKEYPATH);
        byte[] encryptData,decryptData;
        if(publickeyFile.exists() && privatekeyFile.exists()){
        	Key publickey = getKey(publickeyFile, KeyType.PUBLIC);
        	Key privatekey = getKey(privatekeyFile, KeyType.PRIVATE);
        	encryptData = encrypt(data.getBytes(), publickey);
        	decryptData = decrypt(encryptData, privatekey);
        	System.out.println("用文件路径方式的key进行加密!!!");
        }else{
        	encryptData = encrypt(data.getBytes());
        	decryptData = decrypt(encryptData);
        	System.out.println("用系统初始化的key进行加密!!!");
        }
        System.out.println("加密后:" + new String(encryptData, "UTF-8"));
    	System.out.println(new String(decryptData));
        
    }
    /**
     * @param isSaveKey //初始化是否将key保存为文件 true是 false不是
     * @throws Exception
     */
    private static void initKey(boolean isSaveKey) throws Exception {
        KeyPairGenerator kg = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        kg.initialize(ENCRYTLENGTH);
        KeyPair keypair = kg.generateKeyPair();
        //得到公钥和私钥
        publicKey = (RSAPublicKey) keypair.getPublic();
        privateKey = (RSAPrivateKey) keypair.getPrivate();
        if(isSaveKey){
        	File publicKeyFile = new File(PUBLICKEYPATH);
        	File privateKeyFile = new File(PRIVATEKEYPATH);
        	if(publicKeyFile.exists() && privateKeyFile.exists()){
        		generateKeyToFile(publicKey,  publicKeyFile);
        		generateKeyToFile(privateKey, privateKeyFile);
        	}else{
        		throw new RuntimeException("生成key文件的路径错误!!!");
        	}
        }
    }
    /**
     * 将key生成到文件
     * @param key
     * @param file
     * @return
     * @throws IOException
     */
    private static boolean generateKeyToFile(Key key,File file) throws IOException {
        boolean flag = false;
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        try {
            fos = new FileOutputStream(file);
            oos = new ObjectOutputStream(fos);
            //公钥默认使用的是X.509编码,私钥默认采用的是PKCS8编码
            byte [] encode = key.getEncoded();
            //注意,此处采用writeObject方法,读取时也要采用readObject方法
            oos.writeObject(encode);
            flag = true;
        } catch (IOException e) {
            throw e;
        } finally {
            if(fos != null) fos.close();
            if(oos != null) oos.close();
        }
        return flag;
    }
    /**
     * @param keybyte
     * @param type
     * @return
     * @throws Exception
     */
    private static Key getKey( byte[] keybyte, KeyType type) throws Exception {
    	KeyFactory keyfactory = KeyFactory.getInstance(KEY_ALGORITHM);
        if (type == KeyType.PUBLIC) {
            X509EncodedKeySpec x509eks = new X509EncodedKeySpec(keybyte);
            RSAPublicKey publicKey = (RSAPublicKey) keyfactory.generatePublic(x509eks);
            return publicKey;
        } else if (type == KeyType.PRIVATE) {
            PKCS8EncodedKeySpec pkcs8eks = new PKCS8EncodedKeySpec(keybyte);
            RSAPrivateKey privateKey = (RSAPrivateKey) keyfactory.generatePrivate(pkcs8eks);
            return privateKey;
        }
        return null;
    }
    /**
     * @param keyFile
     * @param type
     * @return
     * @throws Exception
     */
    private static Key getKey(File keyFile, KeyType type) throws Exception {
        FileInputStream fis = new FileInputStream(keyFile);
        ObjectInputStream ois = new ObjectInputStream(fis);
        byte[] keybyte = (byte[]) ois.readObject();
        ois.close();
        return getKey(keybyte,type);
    }

    /**
     * @param type
     * @return
     * @throws Exception
     */
    private static Key getKey(KeyType type) throws Exception {
        if (type == KeyType.PUBLIC) {
           return publicKey;
        } else if (type == KeyType.PRIVATE) {
            return privateKey;
        }
        return null;
    }

    /**
     * @param data
     * @param publicKey
     * @return
     * @throws Exception
     */
    private static byte[] encrypt(byte[] data, Key publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > ENCRYPT_LENGTH) {
                cache = cipher.doFinal(data, offSet, ENCRYPT_LENGTH);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * ENCRYPT_LENGTH;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return encryptedData;
    }
    
    /**
     * @param data
     * @param keyFile
     * @return
     * @throws Exception
     */
    public static byte[] encrypt(byte[] data,File keyFile) throws Exception {
    	 Key publicKey = getKey(keyFile, KeyType.PUBLIC);
    	 return encrypt(data,publicKey);
    }
    /**
     * @param data
     * @param keyByte
     * @return
     * @throws Exception
     */
    public static byte[] encrypt(byte[] data,byte[] keyByte) throws Exception {
    	Key publicKey = getKey(keyByte,KeyType.PUBLIC);
        return encrypt(data,publicKey);
    }
    /**
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encrypt(byte[] data) throws Exception {
    	return encrypt(data,publicKey);
    }
    /**
     *
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     */
    private static byte[] decrypt(byte[] data, Key privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
       // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > DECRYPT_LENGTH) {
                cache = cipher.doFinal(data, offSet, DECRYPT_LENGTH);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * DECRYPT_LENGTH;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return decryptedData;
    }
    /**
     * @param data
     * @param privateKeyBytes
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, byte[] privateKeyBytes) throws Exception {
        Key privateKey = getKey(privateKeyBytes,KeyType.PRIVATE);
        return decrypt(data,privateKey);
    }
    /**
     * @param data
     * @param keyFile
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data,File keyFile) throws Exception {
   	 Key privateKey = getKey(keyFile, KeyType.PRIVATE);
   	 return decrypt(data,privateKey);
   }

    /**
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data) throws Exception {
        return decrypt(data,privateKey);
    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值