支付系统中如何应用加密方式的
加密方式分为 对称加密 和非对称加密。支付系统中主要使用 非对称加密。
非对称加密在支付系统中的具体应用是 消息的加解密(公钥加密,私钥解密), 消息 签名 和验签(私钥 加签名,公钥 验证签名)。当然 消息并不一定非要是加密的。
关于加密算法的具体原理,大家可以参见这篇文章。
再来看看支付宝中 加密的具体实现
// 只有新接口和设置密钥才能支持加密,我们按到只有我们设置了请求参数中要求加密才会加密
if (request.isNeedEncrypt()) {
if (StringUtils.isEmpty(appParams.get(AlipayConstants.BIZ_CONTENT_KEY))) {
throw new AlipayApiException(AlipayApiErrorEnum.ENCRYPT_IS_NEED_ERROR);
}
// 需要加密必须设置密钥和加密算法
if (StringUtils.isEmpty(this.encryptType) || getEncryptor() == null) {
throw new AlipayApiException(AlipayApiErrorEnum.ENCRYPT_EMPTY_ERROR);
}
String encryptContent = getEncryptor().encrypt(
appParams.get(AlipayConstants.BIZ_CONTENT_KEY), this.encryptType, this.charset);
//将加密的信息填充到内容体重,而且只是最BIZ_CONTENT 做加密哦
appParams.put(AlipayConstants.BIZ_CONTENT_KEY, encryptContent);
}
加签原理和支付宝的实现
- 获取所有支付宝开放平台的 post 内容,不包括字节类型参数,如文件、字节流,剔除 sign 字段,剔除值为空的参数;
- 按照第一个字符的键值 ASCII 码递增排序(字母升序排序),如果遇到相同字符则按照第二个字符的键值 ASCII 码递增排序,以此类推;
- 将排序后的参数与其对应值,组合成 参数=参数值 的格式,并且把这些参数用
&
字符连接起来,此时生成的字符串为待签名字符串。
if (!StringUtils.isEmpty(this.signType)) {
//之后进行 签名
String signContent = AlipaySignature.getSignatureContent(requestHolder);
protocalMustParams.put(AlipayConstants.SIGN,
getSigner().sign(signContent, this.signType, charset));
}
public static String getSignatureContent(RequestParametersHolder requestHolder) {
return getSignContent(getSortedMap(requestHolder));
}
public static Map<String, String> getSortedMap(RequestParametersHolder requestHolder) {
Map<String, String> sortedParams = new TreeMap<String, String>();
AlipayHashMap appParams = requestHolder.getApplicationParams();
if (appParams != null && appParams.size() > 0) {
sortedParams.putAll(appParams);
}
AlipayHashMap protocalMustParams = requestHolder.getProtocalMustParams();
if (protocalMustParams != null && protocalMustParams.size() > 0) {
sortedParams.putAll(protocalMustParams);
}
AlipayHashMap protocalOptParams = requestHolder.getProtocalOptParams();
if (protocalOptParams != null && protocalOptParams.size() > 0) {
sortedParams.putAll(protocalOptParams);
}
return sortedParams;
}
public static String getSignContent(Map<String, String> sortedParams) {
StringBuilder content = new StringBuilder();
List<String> keys = new ArrayList<String>(sortedParams.keySet());
Collections.sort(keys);
int index = 0;
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = sortedParams.get(key);
if (StringUtils.areNotEmpty(key, value)) {
content.append(index == 0 ? "" : "&").append(key).append("=").append(value);
index++;
}
}
return content.toString();
}