通过RSA和DES实现网络报文加密加签(实例)

前言:

本实例用到两种加密算法:RSA非对称加密和DES对称加密;

除了RSA的公钥和私钥(公钥加密私钥解密,反之亦然),本实例还有两个秘钥:pingKey加密数据秘钥和workKey签名秘钥;

RSA只对pingKey和workKey加解密,DES通过pingKey对数据加解密;

RSA非对称加密比DES对称加密效率低、但安全性更高,故选用DES分别对多个字段值加密,RSA对pingKey和workKey加密;

开发步骤:

1、通过RsaUtils.genKeyPair()生成公钥和私钥,并将公钥和私钥用base64生成字符串,分配需要接入的下游;

2、公钥加密私钥解密,如果下游只需加密而不需解密,只用分配公钥字符串即可;

3、下游通过EncryptManager encryptManager = new EncryptManager();encryptManager.init();初始化pingKey和workKey随机数,并将两者拼接通过公钥生成monKey,monKey包含在报文中;

4、下游通过生成的pingKey加密数据encryptManager.encryptStr(...),通过生成的workKey加签数据SignUtils.getSign(...);

5、平台接收下游的报文,先用私钥解析monKey得到pingKey和workKey,再通过workKey验签数据,通过pingKey解密数据;

6、如果平台返回下游报文需要加密,流程同上;

该模块有以下几个java:

/RsaAndDesTest/src/com/test/Test.java // 测试类

/RsaAndDesTest/src/com/test/EncryptManager.java // 加解密类

/RsaAndDesTest/src/com/utils/DesUtils.java // des相关处理类

/RsaAndDesTest/src/com/utils/RsaUtils.java // rsa相关处理类

/RsaAndDesTest/src/com/utils/SignUtils.java // 签名相关处理类

引入的jar包:
commons-codec-1.4.jar // base64相关处理
commons-lang3-3.1.jar // 随机数相关处理

项目结构:


package com.test;

import java.util.HashMap;
import java.util.Map;
import com.utils.SignUtils;

/**
 * 报文传输协议:
 * RSA对加密解密秘钥和加签解签秘钥进行加密
 * DES通过秘钥进行数据的加密解密和加签解签
 * RSA通过公钥加密、私钥解密
 * 
 * 加解密秘钥pingKey和加解签秘钥workKey为随机生成的24为字符串
 * mobKey为通过RSA将pingKey和workKey拼接然后加密生成的秘钥串
 * 
 * 步骤:
 * 
 * 1、通过方法RsaUtils.genKeyPair()生成公钥和私钥(也可通过网络工具生成),分配给下游商户
 * 下游:
 * 2、随机生成两个秘钥(加解密pingKey和加解签workKey)
 * 3、通过RsaUtils.encryptByPublicKey()和公钥加密得到mobKey
 * 4、通过DesUtils.encryptByKey()对数据项加密
 * 5、通过DesUtils.encryptByKey()对数据项加签,得到sign
 * 6、将sign、mobKey、加密的数据,组装成报文传输
 * 平台:
 * 7、获取报文中的mobKey、sign
 * 8、通过RsaUtils.decryptByPrivateKey()和私钥解密mobKey,得到两个秘钥(加解密pingKey和加解签workKey)
 * 9、通过DesUtils.decryptByKey()对数据项加签,对比sign值验签
 * 10、通过DesUtils.decryptByKey()对数据项解密,得到明文数据
 * 
 * 返回下游的报文加解密和加解签流程同上
 * 
 * (代码有些判断不严谨,请在实际的代码中进行完善。)
 */

public class Test {
	
	private void sendMessage(Map<String, Object> params){
		
		EncryptManager encryptManager = new EncryptManager();
		encryptManager.init();
		
		params.put("name", encryptManager.encryptStr("周星星")); // 加密
		params.put("sex", "男");
		params.put("age", encryptManager.encryptStr("10"));
		
		params.put("mobKey", encryptManager.getMobKey());
		
		// 签名
		params.put("sign", SignUtils.getSign(params, encryptManager.getWorkKey()));
		
	}
	
	private void receviceMessage(Map<String, Object> params){
		
		// 通过mobKey获取pingKey和workKey
		String mobKey = (String) params.get("mobKey");
		EncryptManager encryptManager = new EncryptManager();
		encryptManager.parseMobKey(mobKey);
		
		// 验签
		if(!SignUtils.verifySign(params, encryptManager.getWorkKey())){
			System.out.println("验签失败");
			return;
		}
		
		params.put("name", encryptManager.decryptStr((String)params.get("name")));
		params.put("age", encryptManager.decryptStr((String)params.get("age")));
	}
	
	public static void main(String[] args) {
		Test test = new Test();
		Map<String, Object> params = new HashMap<String, Object>();
		test.sendMessage(params);
		test.receviceMessage(params);
	}
	
}

package com.test;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.RandomStringUtils;

import com.utils.DesUtils;
import com.utils.RsaUtils;


public class EncryptManager {
	
	private static final String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCS3tyLB+gzLIGdO21Dem4JLp5TZGYWJUQl9vvUcMTbt0u4fjqlQp8musB4uc7EJ/DrBrR+HB2aoq7LknlNtCnfOH1WuMIXfQdfV1oiR0yi+ZCSjZQB+jRCO19NEWqMhUcBeZcx8em/UKXP6CmSINln6ttZGnbl12deOEQ+keoPIwIDAQAB";
	private static final String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJLe3IsH6DMsgZ07bUN6bgkunlNkZhYlRCX2+9RwxNu3S7h+OqVCnya6wHi5zsQn8OsGtH4cHZqirsuSeU20Kd84fVa4whd9B19XWiJHTKL5kJKNlAH6NEI7X00RaoyFRwF5lzHx6b9Qpc/oKZIg2Wfq21kaduXXZ144RD6R6g8jAgMBAAECgYAO8OMItb42boGlCCWeZrcI8hgjLaSA/juHjS+jNfGg1G28kALRSwy7uOXZojVZmSKWFjGIXr3YPFKB3R2//OMBbO5ep5Lu62iBLmXgdYwEXV1o0c1ZYkgDKF9tYN+Yv5nHB5bSZ4QnxpZ3LudvNNuUKqLFlDlHwWO6pKmr5cc7yQJBAPEbrse8d0u8cn5T0Xj+3WQ2kGm92ExyOn5sHLlnKPL4IKz3xbbLZWS3O8s1UhB4csPrcc2yEbc6hs5sHO1nFKUCQQCb8SCNUWeUpo8LhBMpIqd28vDaTDrRh5whwsdGbYkn2TPDc4i1lkHbGrTt5IqLh5XNKi79QHiiv5kAZBv7GCInAkA2LDcgD5tqO+QpuCF3oyQRMSVPbOVdf8jewOHPUntj5BZLZrxYruiQMY9QwCE5LCb1GECQq/LJDXBejvIM8T01AkASK/4kGaldXC9tIx3sfDpRlSvV9G4iPpBGKuF35onGF/x9OThkGLdh5fHRiwFOEyW0u8awAlRMetFEh2XvU7efAkA9CUF86C6OhlfAof15UienWPOtds2I4xr68Foh0xhZAf9sJoYIX1gKuCg87V1Sxsp2O/lfKWwaYpNlZncjzyYV";
	
	private String pingKey = null;
	private String workKey = null;
	private String mobKey = null;
	
	public String getPingKey() {
		return pingKey;
	}

	public void setPingKey(String pingKey) {
		this.pingKey = pingKey;
	}

	public String getWorkKey() {
		return workKey;
	}

	public void setWorkKey(String workKey) {
		this.workKey = workKey;
	}

	public String getMobKey() {
		return mobKey;
	}

	public void setMobKey(String mobKey) {
		this.mobKey = mobKey;
	}

	private void assambleMobKey() {
		String mobKeyStr = this.getPingKey()+this.getWorkKey();
		String mob = null;
		try {
			mob = Base64.encodeBase64String(RsaUtils.encryptByPublicKey(mobKeyStr.getBytes(), publicKey));
		} catch (Exception e) {
			e.printStackTrace();
		}
		this.setMobKey(mob);;
	}

	public EncryptManager(){
		
	}

	public void init(){
		this.setPingKey(RandomStringUtils.random(24, "1234567890"));
		this.setWorkKey(RandomStringUtils.random(24, "1234567890"));
		this.assambleMobKey();
		System.out.println("pingKey:"+this.getPingKey());
		System.out.println("workKey:"+this.getWorkKey());
		System.out.println("mobKey:"+this.getMobKey());
	}
	
	/**
	 * 加密数据
	 * @param data
	 * @return
	 */
	public String encryptStr(String data){
		if(data==null || "".equals(data.trim())){
			return null;
		}
		try {
			byte[] result = DesUtils.encryptByKey(data.getBytes(), this.getPingKey());
			return Base64.encodeBase64String(result);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * 解密数据
	 * @param data
	 * @return
	 */
	public String decryptStr(String data){
		if(data==null || "".equals(data.trim())){
			return null;
		}
		try {
			byte[] resultByte = DesUtils.decryptByKey(Base64.decodeBase64(data), this.getPingKey());
			String result = new String(resultByte);
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * 通过mobKey获取pingKey和workKey
	 * @param mobKey
	 */
	public void parseMobKey(String mobKey){
		if(mobKey==null || "".equals(mobKey.trim())){
			return;
		}
		try {
			byte[] mobKeyByte = Base64.decodeBase64(mobKey);
			byte[] resultByte = RsaUtils.decryptByPrivateKey(mobKeyByte, privateKey);
			String result = new String(resultByte);
			String pingKey = result.substring(0,24);
			String workKey = result.substring(24,48);
			this.setPingKey(pingKey);
			this.setWorkKey(workKey);
			System.out.println("pingKey:"+pingKey);
			System.out.println("workKey:"+workKey);
			System.out.println("mobKey:"+mobKey);
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}
	}

	public static void main(String[] args) {
		EncryptManager encryptManager = new EncryptManager();
		encryptManager.init();
	}

}

package com.utils;

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.codec.binary.Base64;

public class DesUtils {
	
	/**
	 * DES加密
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptByKey(byte[] data, String key) throws Exception{
		// 可信任的随机数
		SecureRandom secureRandom = new SecureRandom();
		DESKeySpec keySpec = new DESKeySpec(key.getBytes());
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		SecretKey secretKey = keyFactory.generateSecret(keySpec);
		Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.ENCRYPT_MODE, secretKey, secureRandom);
		return cipher.doFinal(data);
	}
	
	public static byte[] decryptByKey(byte[] data, String key) throws Exception{
		// 可信任的随机数
		SecureRandom secureRandom = new SecureRandom();
		DESKeySpec keySpec = new DESKeySpec(key.getBytes());
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		SecretKey secretKey = keyFactory.generateSecret(keySpec);
		Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.DECRYPT_MODE, secretKey, secureRandom);
		return cipher.doFinal(data);
	}
	
	public static void main(String[] args) throws Exception {
		String sourceStr = "月光宝盒";
		String key = "1234567890";
		System.out.println("待加密:"+sourceStr);
		byte[] encryptByte = DesUtils.encryptByKey(sourceStr.getBytes(), key);
		String encryptStr = Base64.encodeBase64String(encryptByte);
		System.out.println("加密后:"+encryptStr);
		byte[] decryptByte = DesUtils.decryptByKey(Base64.decodeBase64(encryptStr), key);
		String decryptStr = new String(decryptByte);
		System.out.println("解密后:"+decryptStr);
	}
	
}

package com.utils;

import java.io.ByteArrayOutputStream;
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.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;

public class RsaUtils {
	
	private static final String ALGORITHM = "RSA";
	private static final String PUBLICK_EY = "PUBLICK_EY";
	private static final String PRIVATE_KEY = "PRIVATE_KEY";
	/**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;
	
	/**
	 * 生成秘钥对,公钥和私钥
	 * @return
	 * @throws NoSuchAlgorithmException 
	 */
	public static Map<String, Object> genKeyPair() throws NoSuchAlgorithmException{
		Map<String, Object> keyMap = new HashMap<String, Object>(); 
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
		keyPairGenerator.initialize(1024); // 秘钥字节数
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		PublicKey publicKey = keyPair.getPublic();
		PrivateKey privateKey = keyPair.getPrivate();
		keyMap.put(PUBLICK_EY, publicKey);
		keyMap.put(PRIVATE_KEY, privateKey);
		return keyMap;
	}
	
	/**
	 * 公钥加密
	 * @param data
	 * @param publicKey
	 * @return
	 * @throws InvalidKeySpecException 
	 */
	public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception{
		// 得到公钥
		byte[] keyBytes = Base64.decodeBase64(publicKey);
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
		Key key = keyFactory.generatePublic(x509EncodedKeySpec);
		// 加密数据,分段加密
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.ENCRYPT_MODE, key);
		int inputLength = data.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offset = 0;
		byte[] cache;
		int i = 0;
		while(inputLength-offset>0){
			if(inputLength-offset>MAX_ENCRYPT_BLOCK){
				cache = cipher.doFinal(data, offset, MAX_ENCRYPT_BLOCK);
			}else{
				cache = cipher.doFinal(data, offset, inputLength-offset);
			}
			out.write(cache, 0, cache.length);
			i++;
			offset = i * MAX_ENCRYPT_BLOCK;
		}
		byte[] encryptedData = out.toByteArray();
		out.close();
		return encryptedData;
	}
	
	/**
	 * 私钥解密
	 * @param encryptedData
	 * @param privateKey
	 * @return
	 * @throws Exception 
	 */
	public static byte[] decryptByPrivateKey(byte[] data, String privateKey) throws Exception{
		// 得到私钥
		byte[] keyBytes = Base64.decodeBase64(privateKey);
		PKCS8EncodedKeySpec pKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
		Key key = keyFactory.generatePrivate(pKCS8EncodedKeySpec);
		// 解密数据,分段解密
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.DECRYPT_MODE, key);
		int inputLength = data.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offset = 0;
		byte[] cache;
		int i = 0;
		while(inputLength-offset>0){
			if(inputLength-offset>MAX_DECRYPT_BLOCK){
				cache = cipher.doFinal(data, offset, MAX_DECRYPT_BLOCK);
			}else{
				cache = cipher.doFinal(data, offset, inputLength-offset);
			}
			out.write(cache, 0, cache.length);
			i++;
			offset = i*MAX_DECRYPT_BLOCK;
		}
		byte[] decryptedData = out.toByteArray();
		out.close();
		return decryptedData;
	}
	
	/**
	 * 获取公钥
	 * @param keyMap
	 * @return
	 */
	public static String getPublicKey(Map<String, Object> keyMap){
		Key key = (Key) keyMap.get(PUBLICK_EY);
		return Base64.encodeBase64String(key.getEncoded());
	}
	
	/**
	 * 获取私钥
	 * @param keyMap
	 * @return
	 */
	public static String getPrivateKey(Map<String, Object> keyMap){
		Key key = (Key) keyMap.get(PRIVATE_KEY);
		return Base64.encodeBase64String(key.getEncoded());
	}
	
	public static void main(String[] args) throws Exception {
//		Map<String, Object> keyMap = RsaUtils.genKeyPair();
//		String publicKey = RsaUtils.getPublicKey(keyMap);
//		String privateKey = RsaUtils.getPrivateKey(keyMap);
		String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCS3tyLB+gzLIGdO21Dem4JLp5TZGYWJUQl9vvUcMTbt0u4fjqlQp8musB4uc7EJ/DrBrR+HB2aoq7LknlNtCnfOH1WuMIXfQdfV1oiR0yi+ZCSjZQB+jRCO19NEWqMhUcBeZcx8em/UKXP6CmSINln6ttZGnbl12deOEQ+keoPIwIDAQAB";
		String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJLe3IsH6DMsgZ07bUN6bgkunlNkZhYlRCX2+9RwxNu3S7h+OqVCnya6wHi5zsQn8OsGtH4cHZqirsuSeU20Kd84fVa4whd9B19XWiJHTKL5kJKNlAH6NEI7X00RaoyFRwF5lzHx6b9Qpc/oKZIg2Wfq21kaduXXZ144RD6R6g8jAgMBAAECgYAO8OMItb42boGlCCWeZrcI8hgjLaSA/juHjS+jNfGg1G28kALRSwy7uOXZojVZmSKWFjGIXr3YPFKB3R2//OMBbO5ep5Lu62iBLmXgdYwEXV1o0c1ZYkgDKF9tYN+Yv5nHB5bSZ4QnxpZ3LudvNNuUKqLFlDlHwWO6pKmr5cc7yQJBAPEbrse8d0u8cn5T0Xj+3WQ2kGm92ExyOn5sHLlnKPL4IKz3xbbLZWS3O8s1UhB4csPrcc2yEbc6hs5sHO1nFKUCQQCb8SCNUWeUpo8LhBMpIqd28vDaTDrRh5whwsdGbYkn2TPDc4i1lkHbGrTt5IqLh5XNKi79QHiiv5kAZBv7GCInAkA2LDcgD5tqO+QpuCF3oyQRMSVPbOVdf8jewOHPUntj5BZLZrxYruiQMY9QwCE5LCb1GECQq/LJDXBejvIM8T01AkASK/4kGaldXC9tIx3sfDpRlSvV9G4iPpBGKuF35onGF/x9OThkGLdh5fHRiwFOEyW0u8awAlRMetFEh2XvU7efAkA9CUF86C6OhlfAof15UienWPOtds2I4xr68Foh0xhZAf9sJoYIX1gKuCg87V1Sxsp2O/lfKWwaYpNlZncjzyYV";
		System.out.println("公钥:"+publicKey);
		System.out.println("私钥:"+privateKey);
		// 公钥加密
		String sourceStr = "我是谁?";
		System.out.println("加密前:"+sourceStr);
		byte[] encryptStrByte = RsaUtils.encryptByPublicKey(sourceStr.getBytes(), publicKey);
		String encryptStr = Base64.encodeBase64String(encryptStrByte);
		System.out.println("加密后:"+encryptStr);
		System.out.println("长度:"+encryptStr.length());
		// 私钥解密
		byte[] decryptStrByte = RsaUtils.decryptByPrivateKey(Base64.decodeBase64(encryptStr), privateKey);
		String sourceStr_1 = new String(decryptStrByte);
		System.out.println("解密后:"+sourceStr_1);
		/**
		 * 加密源数据通过getBytes()方法转换成字节数组进行加密
		 * 解密后的字节数组通过new String()方法转换成源字符串
		 * 明文显示加解密过程的字节数组,例如公私钥,用Base64转换成可见字符
		 */
	}
	
}

package com.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;

public class SignUtils {
	
	
	/**
	 * 生成签名
	 * @param params
	 * @param workKey
	 * @return
	 */
	public static String getSign(Map<String, Object> params, String workKey){
		
		if(params==null){
			return null;
		}
		params.remove("sign");
		List<String> keys = new ArrayList<String>(params.keySet());
		Collections.sort(keys);
		StringBuffer sb = new StringBuffer();
		for(String key : keys){
			String value = (String) params.get(key);
			if(value!=null && !"".equals(value.trim())){
				sb.append(value);
			}
		}
		
		try {
			byte[] signByte = DesUtils.encryptByKey(sb.toString().getBytes(), workKey);
			return Base64.encodeBase64String(signByte);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
	}
	
	/**
	 * 验签
	 * @param params
	 * @return
	 */
	public static boolean verifySign(Map<String, Object> params, String workKey){
		
		String sign = (String) params.get("sign");
				
		return sign.equals(SignUtils.getSign(params, workKey));
	}
}


  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Firechou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值