加密方式-非对称加密(RSA加密与签名)

上一篇讲到了对称加密,本文主要讲非对称加密。
非对称加密就是指加密解密使用不同的密钥。
经常有人问我公钥私钥到底哪个用来加密哪个用来解密,哪个用来加签,哪个验签。

今天就讲一个比较通俗易懂的方法:
你只要去想:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证

RSA加密解密类静态常量

public static final String KEY_ALGORTHM="RSA";//
public static final String SIGNATURE_ALGORITHM="MD5withRSA";
	
public static final String PUBLIC_KEY = "RSAPublicKey";//公钥
public static final String PRIVATE_KEY = "RSAPrivateKey";//私钥

	/**
	 * BASE64解密
	 * @param key
	 * @return
	 * @throws Exception
	 */
public static byte[] decryptBASE64(String key) throws Exception{
	return (new BASE64Decoder()).decodeBuffer(key);
}
	
	/**
	 * BASE64加密
	 * @param key
	 * @return
	 * @throws Exception
	 */
public static String encryptBASE64(byte[] key)throws Exception{
	return (new BASE64Encoder()).encodeBuffer(key);
}


	/**
	 * 初始化密钥
	 * @return
	 * @throws Exception
	 */
	public static Map<String,Object> initKey()throws Exception{
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM);
		keyPairGenerator.initialize(1024);
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		
		//公钥
		RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
		//私钥
		RSAPrivateKey privateKey =  (RSAPrivateKey) keyPair.getPrivate();
		
		Map<String,Object> keyMap = new HashMap<String, Object>(2);
		keyMap.put(PUBLIC_KEY, publicKey);
		keyMap.put(PRIVATE_KEY, privateKey);
		
		return keyMap;
	}

	/**
	 * 取得公钥,并转化为String类型
	 * @param keyMap
	 * @return
	 * @throws Exception
	 */
	public static String getPublicKey(Map<String, Object> keyMap)throws Exception{
		Key key = (Key) keyMap.get(PUBLIC_KEY);  
		return encryptBASE64(key.getEncoded());     
	}

	/**
	 * 取得私钥,并转化为String类型
	 * @param keyMap
	 * @return
	 * @throws Exception
	 */
	public static String getPrivateKey(Map<String, Object> keyMap) throws Exception{
		Key key = (Key) keyMap.get(PRIVATE_KEY);  
		return encryptBASE64(key.getEncoded());     
	}
	
	
	/**
	 * 用公钥加密
	 * @param data	加密数据
	 * @param key	密钥
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptByPublicKey(byte[] data,String key)throws Exception{
		//对公钥解密
		byte[] keyBytes = decryptBASE64(key);
		//取公钥
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
		Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
		
		//对数据解密
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		
		return cipher.doFinal(data);
	}
	
	
	/**
	 * 用私钥解密 
	 * @param data 	加密数据
	 * @param key	密钥
	 * @return
	 * @throws Exception
	 */
	public static byte[] decryptByPrivateKey(byte[] data,String key)throws Exception{
		//对私钥解密
		byte[] keyBytes = decryptBASE64(key);
		
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
		Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		//对数据解密
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		
		return cipher.doFinal(data);
	}
	
	
	
	/**
	 *	用私钥对信息生成数字签名
	 * @param data	//加密数据
	 * @param privateKey	//私钥
	 * @return
	 * @throws Exception
	 */
	public static String sign(byte[] data,String privateKey)throws Exception{
		//解密私钥
		byte[] keyBytes = decryptBASE64(privateKey);
		//构造PKCS8EncodedKeySpec对象
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
		//指定加密算法
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
		//取私钥匙对象
		PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		//用私钥对信息生成数字签名
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		signature.initSign(privateKey2);
		signature.update(data);
		
		return encryptBASE64(signature.sign());
	}
	
	
	
	/**
	 * 校验数字签名
	 * @param data	加密数据
	 * @param publicKey	公钥
	 * @param sign	数字签名
	 * @return
	 * @throws Exception
	 */
	public static boolean verify(byte[] data,String publicKey,String sign)throws Exception{
		//解密公钥
		byte[] keyBytes = decryptBASE64(publicKey);
		//构造X509EncodedKeySpec对象
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
		//指定加密算法
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
		//取公钥匙对象
		PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec);
		
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		signature.initVerify(publicKey2);
		signature.update(data);
		//验证签名是否正常
		return signature.verify(decryptBASE64(sign));
		
	}

加密解密,加签验签测试


	public static void main(String[] args) {
		String content = "{name:tansen,age:25,sex:man,address:湖南省常德市澧县}";
		
		//1.初始化公钥私钥
		String rsaPublicKey = null;
		String rsaPrivateKey = null;
		try {
			Map<String, Object> map = RSA.initKey();
			rsaPublicKey = getPublicKey(map);
			rsaPrivateKey = getPrivateKey(map);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		//2.使用公钥加密
		try {
			System.out.println("加密前=="+content);
			byte[] result_m = RSA.encryptByPublicKey(content.getBytes(), rsaPublicKey);
			content = encryptBASE64(result_m);
			System.out.println("加密后=="+content);
		} catch (Exception e) {
			e.printStackTrace();
		}
		//3.私钥解密
		try {
			byte[] b1 = decryptBASE64(content);
			byte[] b2 = decryptByPrivateKey(b1, rsaPrivateKey);
			content = new String(b2);
			System.out.println("解密后=="+content);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
		//4.私钥加签
		String sign = null;
		try {
			sign = sign(content.getBytes(), rsaPrivateKey);
			System.out.println("签名=="+sign);
		} catch (Exception e) {
			e.printStackTrace();
		}
		//5.公钥验签
		try {
			boolean flag = verify(content.getBytes(), rsaPublicKey, sign);
			System.out.println("延签结果=="+flag);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	

结果


加密前=={name:tansen,age:25,sex:man,address:湖南省常德市澧县}

加密后==rDed52QWJ3DNZTUAxqLuO5Ok6vTE7RNQwkHk/GJxIN8yXNiB2dE
dqvjMPwzVR97uAx9hjng+QpMRE9JGFRp9YFE+PumA0m+bseLV+x7O2xJ3hGLqGdyQi18zB7eiTmBQoDD2LljMGeMn5EgtXntE9knx1WYPIKS2Uvh17JRQq1c=

解密后=={name:tansen,age:25,sex:man,address:湖南省常德市澧县}

签名==d5CkI95rVRwHxwIilrAj1O2nLq4mLrKwMbGGZojTQdS/jXZJkiB1bS
R7dxCwLX+WqqJnP7soES4octa5TebjcloMRQXrpY3ePKhvAWxBzF60MUlWiPLib8SX0HQzeWxsf9ifi9wASus+ICNqF7udVRKLWZctYqHe3TjCMURV22c=

延签结果==true

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值