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

xiaoxiao2021-02-28  116

前言:

本实例用到两种加密算法: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)); } }

转载请注明原文地址: https://www.6miu.com/read-48340.html

最新回复(0)