前言
支付类app为了安全起见,除了使用【防代理分析请求数据】,还可采用签名的方式进一步进行限制防止请求和返回报文被修改。
iOS请求安全防护【1、 防代理分析请求数据 2、SSL证书认证3、采用签名禁止修改报文4、不在本地缓存网络请求报文5、利用NSURLProtocol 拦截请求修改HTTPHeaderField】 1、iOS网络请求安全优化:2、不走全局proxy的方案;3、允许不验证SSL证书;4、拦截请求;5、DoH &DoT 1、iOS安全【 SSL证书验证, 让Charles再也无法抓你的请求数据】2、iOS逆向:【绕过证书校验】 文章地址: https://blog.csdn.net/z929118967/article/details/102511852
- 应用场景:防止请求参数被恶意修改
在对接第三方支付的时候,第三方会要求参数按照ASCII码从小到大排序。 1、银联的退款接口签名:https://kunnan.blog.csdn.net/article/details/115084885 ◆ key:签名时用机构对应的密钥key ◆签名算法:MD5,后续会兼容SHA1、SHA256、HMAC等 2、微信支付接口签名:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=4_3 ◆ key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 ◆注:HMAC-SHA256签名方式,部分语言的hmac方法生成结果二进制结果,需要调对应函数转化为十六进制字符串 ◆生成随机数算法:调用随机数函数生成,将得到的值转换为字符串。 ◆使用openssl命令来自己导出pem证书(p12 to pem):openssl pkcs12 -clcerts -nokeys -in apiclient_cert.p12 -out apiclient_cert.pem ◆ 微信支付接口签名校验工具 :https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=20_1
- 原文
https://blog.csdn.net/z929118967/article/details/108195721
从CSDN下载demo地址:https://download.csdn.net/download/u011018979/15483107
1、demo 数组用[]表示,对象(字典)用{} 表示进行排序拼接。 2、数组排序可选,数组内部,只对字符串元素进行排序,并不与字典key参与排序。 (字典和数组独立排序)
- 参数
NSDictionary *params = @{@"sid" : @"iOS逆向",
@"certificateInfoList" : @"https://kunnan.blog.csdn.net/article/details/108195721" ,
@"storePicsList" : @"https://kunnan.blog.csdn.net" ,
};
- 效果
2021-02-26 15:43:42.208991 0800 SignatureGenerator[16231:1928569] 按照参数名ASCII码从小到大排序:《certificateInfoList=https://kunnan.blog.csdn.net/article/details/108195721&sid=iOS逆向&storePicsList=https://kunnan.blog.csdn.net》
2021-02-26 15:43:42.209280 0800 SignatureGenerator[16231:1928569] sign:195b9caecc41681ebd1b74261f858052
I、实现步骤
为了保证数据传输过程中的数据真实性和完整性,我们需要对数据进行数字签名,在接收签名数据之后进行签名校验。
数字签名有两个步骤:
1、先按一定规则拼接要签名的原始串, 2、再选择具体的算法和密钥计算出签名结果(注意:签名时将字符串转化成字节流时指定的编码字符集应与参数charset一致。)
- 签名原始串
代码语言:javascript复制所有参数按照字段名的ascii码从小到大排序后使用QueryString(
URL键值对
)的格式(即key1=value1&key2=value2…)拼接而成,空值不传递,不参与签名组串。
<xml>
<body><![CDATA[测试支付]]></body>
<mch_create_ip><![CDATA[127.0.0.1]]></mch_create_ip>
<mch_id><![CDATA[7551000001]]></mch_id>
<nonce_str><![CDATA[1409196838]]></nonce_str>
<out_trade_no><![CDATA[141903606228]]></out_trade_no>
<service><![CDATA[unified.trade.micropay]]></service>
<sign><![CDATA[52836FAD27E0813DAA4072A4BDA9F654]]></sign>
<total_fee><![CDATA[1]]></total_fee>
</xml>
代码语言:javascript复制body=测试支付&mch_create_ip=127.0.0.1&mch_id=7551000001&nonce_str=1409196838&out_trade_no=
141903606228&service=unified.trade.micropay&total_fee=1
1.1 签名原始串:按照参数名ASCII码从小到大排序并拼接
[递归的方式进行实现]
设所有发送或者接收到的数据为集合M,将集合M内的参数和参数值按照参数名ASCII码从小到大排序(字典序),使用QueryString的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
代码语言:javascript复制1、demo 数组用[]表示,对象(字典)用{} 表示进行排序拼接。 2、数组排序可选,数组内部,只对字符串元素进行排序,并不与字典key参与排序。 字典和数组独立排序
isPreAuth=false&isWipeZero=true&needTrade=falsetotalAmount=22
- 处理key对应的Value是字典的情况
/**
递归
- 处理key对应的Value是字典的情况
request body参数名ASCII码从小到大排序(字典序),
使用URL键值对的格式拼接成字符串 (key1=value1&key2=value2…)
*/
(NSString *)sortedDictionary:(NSMutableDictionary *)originParam {
NSDictionary *dict = originParam;
NSMutableString *contentString =[NSMutableString string];
NSArray *keys = [dict allKeys];
//按字母顺序排序
NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
//拼接字符串
for (NSString *categoryId in sortedArray) {
#pragma mark - ******** todo value区分数组[,]、字符串、字段对象{}
id categoryIdV = [dict objectForKey:categoryId];
//
if( [categoryIdV isKindOfClass:NSString.class]){
}
else if( [categoryIdV isKindOfClass:NSDictionary.class]){
categoryIdV = [self sortedDictionary:categoryIdV];
categoryIdV = [NSString stringWithFormat:@"%@%@%@",@"{",categoryIdV,@"}"];
}
// 数组就[]
else if( [categoryIdV isKindOfClass:NSArray.class]){
categoryIdV = [self sortedDictionaryArr:categoryIdV];
}
if ([contentString length] <= 0) {
//第一个参数
}else{
[contentString appendString:@"&"];
}
[contentString appendFormat:@"%@=%@", categoryId,categoryIdV ];
}
NSLog(@"%@",contentString);
return contentString;
}
- 处理key对应的Value是数组的情况
签名数组ASCII码排序的地方
相关问题解答:https://kunnan.blog.csdn.net/article/details/115355062 新增集合元素排序【可选】:对于数组排序,先按照数组元素的class类型进行分组,其中的子数组是字符串类型的话,就对其进行排序之后再重新组合到新的数组中。然后再进行遍历递归拼接