Java之RSA加解密解析

  说明:在上篇中提到Base64加解密(详细参见上),但Base64自己并非用来作加解密的。虽然能够经过变化的序列来达到加解密目的,但Base64有一个问题那就是不具有验证性,它不验证目标源是否是通过Base64加密过的,是否能解的开;统统来者不拒,解出来的东西有时候莫名其妙,因此通常仍是建议少用Base64去作加解密。   本文提到RSA是一个标准的非对称加解密算法,使用场景:根据RSA的特性,它有公钥和私钥两个密匙,一般能够用在一端加密、另一通须要解密的场景,另一个加密的长度问题在正文中讨论;若是仅仅用来作验签则没有必要用。java

1、什么是非对称算法


  非对称密钥算法是指一个加密算法的加密密钥和解密密钥是不同的,或者说不能由其中一个密钥推导出另外一个密钥。具体实现算法原理可参见官方说明,这里主要基于java的应用级别介绍。算法


2、RSA中的长度问题


一、RSA初始化长度   Java中实现的初始化长度默认是512,因此若是小于512会抛异常,这里的长度是bit数组

在这里插入图片描述
二、目标文本长度
在这里插入图片描述
在这里插入图片描述
  根据上面两个图示,一样的初始化长度,惟一的区别就是第二个图中的目标文本长度是54,致使加解密失败。那目标文本长度与初始化长度有什么关系?在Java对RSA的实现中有一个计算公式,目标文本的长度(字节)<=RSA初化长度-11; 结合公式分析一下上面RSA的字节长度=512/8,即64个字节;64-11=53字节,因此要求目标文本长度必定是小于等于53个字节长度。   这里也能够解决在最开始应用场景中的另一个问题,在使用RSA对文本加解密时必定要考虑目标文本的长度,若是文本较长,能够适当调节初始化长度(建议是8的倍数,缘由不用多说了吧)。   注意: RSA的初始化长度越大,能够加密的目标文本长度越大,加密后的密文越长,但加密时的性能越差,须要综合平衡(若目标文本过长,建议分段加密);另外注意上面长度的单位。


3、RSA为何常和Base64一块儿使用


一、编码一致性,Base64设计最初的目的就是解决网络传速时,编码不一致问题,这个很容易理解。 二、二进制的不可见性 bash

在这里插入图片描述
  RSA中字符串String用来存放明文,Byte数组用来存放加密后的密文;既然是密文天然不想容易被转换;经过上面的小demo能够很清楚的看出,String和Byte数组之间能够很容易转换,因此这也是为何引入Base64的缘由。


4、完整的DEMO


   若是让Base64具备加解密的功能,至少要一部分是变化的;这里能够经过变化标准序列的方式;建议你们用到的时候,能够先看一下第3部分中标出那个类的源码(没几行代码);这个变化的序列能够根据时间、根据UUID、根据一切能够变换的东西来生成,这里是根据UUID来随机生成序列。    一、生成随机序列网络

import java.security.Key;
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.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public final class RSAUtils {
    /**
     * 指定长度来生成RSA公私钥对。
     */
    public static KeyPair generateRSAKeyPair(int bitLength) throws NoSuchAlgorithmException {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        if (bitLength > 0)
            kpg.initialize(bitLength);
        return kpg.generateKeyPair();
    }
    public static String getBase64Key(Key key) {
        byte[] encoded = key.getEncoded();
        return new BASE64Encoder().encode(encoded);
    }
    /**
     * 根据提供的base64编码生成RSA公钥。
     */
    public static PublicKey getPubKey(String base64String) throws Exception {
        X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(new BASE64Decoder().decodeBuffer(base64String)); 
        return KeyFactory.getInstance("RSA").generatePublic(pubSpec);
    }
    /**
     * 根据提供的base64编码生成RSA私钥。
     */
    public static PrivateKey getPriKey(String base64String) throws Exception {
        PKCS8EncodedKeySpec priSpec = new PKCS8EncodedKeySpec(new BASE64Decoder().decodeBuffer(base64String));
        return KeyFactory.getInstance("RSA").generatePrivate(priSpec);
    }
}

复制代码
public static void main(String[] args) throws Exception {
		KeyPair key = RSAUtils.generateRSAKeyPair(960);
		String publicKey = RSAUtils.getBase64Key(key.getPublic());
		String privateKey = RSAUtils.getBase64Key(key.getPrivate());

		System.out.println(publicKey);
		System.out.println(privateKey);

		StringBuilder sb = new StringBuilder();
		sb.append("rank=1&sessionId=")
				.append("0123456789ABCDEF0123456789ABCDEF").append("&ts=")
				.append(System.currentTimeMillis() + 1000000000);

		String en = encode(sb.toString(), key);
		String de = decode(en, key);
		System.out.println("原文:" + sb.toString());
		System.out.println("密文:" + en);
		System.out.println("密文:"+encode(sb.toString(), key));
		System.out.println("解密:" + de);
		
		

	}

	public static String encode(String src, KeyPair key) {
		String hashCode = null;
		try {
			PrivateKey publicKey = (PrivateKey) key.getPrivate();
			Cipher cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.ENCRYPT_MODE, publicKey);
			byte[] output = cipher.doFinal(src.getBytes());

			hashCode = new BASE64Encoder().encode(output);
		} catch (Exception e) {

		}
		return hashCode;
	}

	public static String decode(String src, KeyPair key) {
		String returnRes = null;
		try {
			PublicKey publicKey = (PublicKey) key.getPublic();
			Cipher cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.DECRYPT_MODE, publicKey);
			byte[] output = cipher.doFinal(new BASE64Decoder()
					.decodeBuffer(src));
			returnRes = new String(output);
		} catch (Exception e) {

		}
		return returnRes;
	}
复制代码

持续更新中,能够关注........ session

javaview.jpg
相关文章
相关标签/搜索