iOS-公钥锁定TrustKit

1. SSL简介

证书锁定(SSL/TLS Pinning)顾名思义,将服务器提供的SSL/TLS证书内置到移动端开发的APP客户端中,当客户端发起请求时,通过比对内置的证书和服务器端证书的内容,以确定这个连接的合法性。

2. 证书锁定原理

证书锁定(SSL/TLS Pinning)提供了两种锁定方式: Certificate Pinning 和 Public Key Pinning,文头和概述描述的实际上是Certificate Pinning(证书锁定)。

1.1 证书锁定
我们需要将APP代码内置仅接受指定域名的证书,而不接受操作系统或浏览器内置的CA根证书对应的任何证书,通过这种授权方式,保障了APP与服务端通信的唯一性和安全性,因此我们移动端APP与服务端(例如API网关)之间的通信是可以保证绝对安全。但是CA签发证书都存在有效期问题,所以缺点是在证书续期后需要将证书重新内置到APP中

1.2 公钥锁定
公钥锁定则是提取证书中的公钥并内置到移动端APP中,通过与服务器对比公钥值来验证连接的合法性,我们在制作证书密钥时,公钥在证书的续期前后都可以保持不变(即密钥对不变),所以可以避免证书有效期问题。

所以我们最终选择使用公钥锁定,为避免证书过期需要客户端更新的问题

1.3 客户端获取公钥
这里采用公钥锁定的方式,则需要获取证书公钥的摘要hash,该值由服务器端提供,提取证书的摘要hash并查看base64的格式,示例:bAExy9pPp0EnzjAlYn1bsSEGvqYi1shl1OOshfH3XDA=,这就是我们将要进行证书锁定的指纹(Hash)信息

1.4 客户端使用SSL锁定选择
1、网络框架是Alamofire,其实该SDK本身支持SSL证书锁定,但是只支持证书锁定,需要将证书放在项目,读取证书的内容进行锁定
2、常用的第三方SDK TrustKit,提供了使用公钥锁定,只需设置域名和对应的Hash值,然后处理网络系统回调方法:

    func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping @Sendable (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

    }

选择使用TrustKit来进行公钥锁定

1.5 项目支持SSL证书锁定
1、podFile引入TrustKit框架,github源码
2、初始化TrustKit,在AppDelegate应用程序启动的方法中添加以下代码:

let trustKitConfig: [String: Any] = [
	kTSKSwizzleNetworkDelegates: false,
	kTSKPinnedDomains: [
		"oversea-sit.yolanda.hk": [
			kTSKIncludeSubdomains: true,
			kTSKEnforcePinning: true,
			kTSKPublicKeyHashes: [
				"rseBZG6ykune+DEw3uysPJokdBusGMtrTeJlHd7bHLA=",
				"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
			]
		]
]]
TrustKit.initSharedInstance(withConfiguration: trustKitConfig)

3、实现自定义代理方法:

class CustomSessionDelegate: SessionDelegate {
    override func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        print("testLog: didReceive challenge")
        if TrustKit.sharedInstance().pinningValidator.handle(challenge, completionHandler: completionHandler) == false {
            // TrustKit did not handle this challenge: perhaps it was not for server trust
            // or the domain was not pinned. Fall back to the default behavior
            completionHandler(.performDefaultHandling, nil)
        }
    }
}

4、修改网络的初始化方法,设置自定义代码类

let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = 10
configuration.timeoutIntervalForResource = 10
self.session = Session(configuration: configuration, delegate: CustomSessionDelegate())

5、测试验证
使用Charles设置网络抓包,网络请求接口响应错误提示:


Charles上的表现截图:


修改前在Charles上的截图:


原文链接:https://blog.csdn.net/weixin_44836266/article/details/138607973

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值