数据加密

1:加密的目的

保密性:防止用户隐私信息或重要业务数据被读取。

数据完整性:防止数据被网络中的第三方截取和篡改。

身份验证:确保数据访问接口调用方拥有相匹配权限。

2: 

加密所需数据

名称

类型

说明

示例

appId

应用id

String

由银行网关颁发

gw001

appSecret

应用密码

String

由银行网关颁发

77459071-3b14-4a39-8960-be9cdb23009f

rsaPublicKey

Rsa公钥

String

由银行网关颁发

MIGfMA0GCSqGSIb3DQEBAQUAA4GNxxx



入参格式:

Key

名称

类型

说明

是否必须

示例

appId

应用id

String

网关颁发

 

signature

签名

String

Base64编码的签名

 

ak

加密的aes秘钥

String

Base64编码后的加密的AES秘钥

 

message

业务参数

String

Aes秘钥加密的业务入参

 

serviceId

接口id

String

网关接口id

 


加密规则

参数加密通过AES方式,AES密钥由调用端生成。

网关需要维护各appId对应的RSA私钥,客户端使用RSA公钥对AES秘钥做加密,服务端使用私钥进行解密,通过AES秘钥对请求数据做解密处理。

加签通过SHA256方式对(加密后的参数+ appSecret)采用MD5算法生成摘要.

 

加密代码

import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

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


/**
 * 测试环境请求数据加密使用类
 *
 */
public class RequestParamsEncryptionTest {
	
	private static final String DEFAULT_URL_ENCODING = "UTF-8";
	
	/**
	 * 
	 * @param message 业务参数
	 * @param rsaPublicKey rsa公钥
	 * @param secret  应用密码
	 * @return 返回{message: "", signature: "", ak : ""}的map数据
	 * @throws Exception
	 */
	public static Map<String, String> encryption(String message, String rsaPublicKey, String secret) throws Exception{
		
		// 1 生成AES秘钥
		KeyGenerator kg = KeyGenerator.getInstance("AES");    
        kg.init(128);
        SecretKey sk = kg.generateKey();    
        byte[] aesKeyBytes = sk.getEncoded();   
		
        
        // 2 将业务参数用AES秘钥加密
        byte[] encryMessage = encryptAES(message, aesKeyBytes);
        
        
        // 3 将base64编码后的AES秘钥用RSA公钥加密 生成AK
        String encodeAesKey = encodeBase64(aesKeyBytes);
        byte[] akbytes = encryptRSA(loadPublicKeyByStr(rsaPublicKey), encodeAesKey.getBytes());
        String akStr = encodeBase64(akbytes);
        
        // 4  将加密后的业务参数和网关颁发的secret做sha256摘要生成签名
        String encryBase64Message = encodeBase64(encryMessage);
        String signature = encodeBase64(digest((encryBase64Message + secret).getBytes(), "SHA-256", null, 1));
        
        Map<String, String> reData = new HashMap<>();
        reData.put("message", encryBase64Message);
        reData.put("signature", signature);
        reData.put("ak", akStr);
        return reData;
	}
	
	
	/**
	 * 字符串转换为Base64编码字符串.
	 * @throws UnsupportedEncodingException 
	 */
	private static String encodeBase64(byte[] input) throws UnsupportedEncodingException {
		return new String(Base64.encodeBase64(input), DEFAULT_URL_ENCODING);
	}
	
	/**
	 * @param input Base64字符串
	 * @return  解码Base64字符串,返回字节数组.
	 * @throws UnsupportedEncodingException
	 */
	private static byte[] decodeBase64(String input) throws UnsupportedEncodingException {
		return Base64.decodeBase64(input.getBytes(DEFAULT_URL_ENCODING));
	}
	
	/**
	 * AES加密,先加密内容,然后再用Base64编码,返回Base64编码后的结果
	 * 
	 * @param content
	 *            待加密字符串
	 * @param key
	 *            AES秘钥
	 * @return Base64编码的加密内容
	 */
	private static byte[] encryptAES(String content, byte[] raw) throws Exception {
		SecretKey aesKey = new SecretKeySpec(raw, "AES");
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.ENCRYPT_MODE, aesKey);
		byte[] originalBytes = content.getBytes("utf-8");
		byte[] encodedBytes = cipher.doFinal(originalBytes);
		return encodedBytes;
	}
	
	/**
	 * 从字符串中加载公钥
	 * 
	 * @param publicKeyStr
	 *            公钥数据字符串
	 * @throws Exception
	 *             加载公钥时产生的异常
	 */
	private static RSAPublicKey loadPublicKeyByStr(String publicKeyStr) throws Exception {
		byte[] buffer = decodeBase64(publicKeyStr);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
		return (RSAPublicKey) keyFactory.generatePublic(keySpec);
	}
	
	/**
	 * rsa公钥加密过程
	 * 
	 * @param publicKey
	 *            公钥
	 * @param plainTextData
	 *            明文数据
	 * @return
	 * @throws Exception
	 *             加密过程中的异常信息
	 */
	private static byte[] encryptRSA(RSAPublicKey publicKey, byte[] plainTextData) throws Exception {
		if (publicKey == null) {
			throw new Exception("加密公钥为空, 请设置");
		}
		Cipher cipher = null;
		// 使用默认RSA
		cipher = Cipher.getInstance("RSA");
		// cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		byte[] output = cipher.doFinal(plainTextData);
		return output;
	}
	
	
	/**
	 * 对字符串进行散列, 支持md5与sha1、sha256算法.
	 * @param input  输入byte
	 * @param algorithm  算法名称
	 * @param salt  加盐
	 * @param iterations 迭代次数
	 * @return
	 */
	private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
		try {
			MessageDigest digest = MessageDigest.getInstance(algorithm);

			if (salt != null) {
				digest.update(salt);
			}

			byte[] result = digest.digest(input);

			for (int i = 1; i < iterations; i++) {
				digest.reset();
				result = digest.digest(result);
			}
			return result;
		} catch (GeneralSecurityException e) {
			
		}
		return salt;
	}

}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值