最近在研究关于https安全认证的问题,但是资料感觉多(没用的复制的也不少),就写下这篇文章记录一下
注意:iOS 13和macOS 10.15中受信任证书的要求已经发生变化 具体见苹果官网
大致谷歌翻译: 所有TLS服务器证书都必须符合iOS 13和macOS 10.15中的这些新安全要求: TLS服务器证书和使用RSA密钥的颁发CA必须使用大于或等于2048位的密钥大小。使用RSA密钥大小小于2048位的证书不再受TLS信任。 TLS服务器证书和颁发CA的签名算法必须使用
SHA-2系列的哈希算法。不再信任SHA-1签名证书。 TLS服务器证书必须在证书的“使用者备用名称”扩展名中显示服务器的DNS名称。证书的CommonName中的DNS名称不再受信任。 此外,2019年7月1日之后颁发的所有TLS服务器证书(如证书的NotBefore字段中所示)必须遵循以下准则: TLS服务器证书必须包含包含id-kp-serverAuth OID的ExtendedKeyUsage(EKU)扩展。 TLS服务器证书的有效期必须为825天或更短(如证书的NotBefore和NotAfter字段中所示)。 违反这些新要求的TLS服务器连接将失败,并可能导致网络故障,应用程序失败以及网站无法加载到iOS 13和macOS 10.15的Safari中。 ###通过keytool生成服务器端以及客户端证书是一种不错的选择,方便我们进行本地测试,这里我参考的资料使用keytool生成证书,但是注意!里面的一些命令和mac不大一致,另外生成的算法位数也不大对
下面是我的Mac生成证书步骤
1生成服务器证书
keytool -genkey -v -alias tomcat -keyalg RSA -keystore /Users/liguicheng/Desktop/key/tomcat.keystore -keysize 2048 -validity 36500
参数说明:“/Users/liguicheng/Desktop/key”含义是将证书文件的保存路径,证书文件名称是tomcat.keystore; “-validity 36500”含义是证书有效期,36500表示100年,默认值是90天;“tomcat”为自定义证书名称;
-keysize 2048加密算法位数
2生成客户端证书
假设客户端证书密码“123456”,其他随便填
keytool -genkey -v -alias mykey -keyalg RSA -storetype PKCS12 -keystore /Users/liguicheng/Desktop/key/mykey.p12
3让服务器信任客户端证书
服务器要信任客户端证书,必须把客户端证书添加为服务器的信任认证。
1)由于不能直接将PKCS12格式的证书库导入,必须先把客户端证书导出为一个单独的CER文件,使用如下命令:
(下面要用到客户端证书密码“123456”)
keytool -export -alias mykey -keystore /Users/liguicheng/Desktop/key/mykey.p12 -storetype PKCS12 -storepass 123456 -rfc -file /Users/liguicheng/Desktop/key/mykey.cer
2)将该文件导入到服务器的证书库,添加为一个信任证书使用命令如下
keytool -import -v -file /Users/liguicheng/Desktop/key/mykey.cer -keystore /Users/liguicheng/Desktop/key/tomcat.keystore
3)通过 list 命令查看服务器的证书库,可以看到两个证书,一个是服务器证书,一个是受信任的客户端证书:
keytool -list -keystore /Users/liguicheng/Desktop/key/tomcat.keystore
4)让客户端信任服务器证书
keytool -keystore /Users/liguicheng/Desktop/key/tomcat.keystore -export -alias tomcat -file /Users/liguicheng/Desktop/key/tomcat.ce
显示的信息 和我们的文件夹下
接下来修改tomcat配置:(你的tomcat对应的server.xml)
之前的8080重定向为443
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="443" />
找到注释的8443,去掉注释,修改了443 并添加如下,keystoreFile为你的路径哈 密码是你设置的密码
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
SSLEnabled="true" maxThreads="150" scheme="https"
secure="true" clientAuth="false" sslProtocol="TLS"
keystoreFile="/Users/liguicheng/Desktop/key/tomcat.keystore" keystorePass="123456"
truststoreFile="/Users/liguicheng/Desktop/key/tomcat.keystore" truststorePass="123456" sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2" />
最后启动tomcat 浏览器中访问https://localhost:443,在Safari中进去之后显示不安全的我们选择证书,最后的成功后前面是带这小锁🔒的;信任证书浏览器正常访问之后,浏览器和Xcode demo代码如下:
Alamofier 5.0
这里面应该最后的struct不用写,因为最新的Alamofire5.x,已经实现了从Bundle.main中去找这个.cer文件
import UIKit
import Alamofire
class ViewController: UIViewController {
// let evaluators = ["localhost": PinnedCertificatesTrustEvaluator(certificates: [Certificates.stackExchange], acceptSelfSignedCertificates: true, performDefaultValidation: false, validateHost: false)]
let evaluators = ["localhost": PinnedCertificatesTrustEvaluator(certificates: [Certificates.stackExchange], acceptSelfSignedCertificates: true, performDefaultValidation: false, validateHost: false)]
var session: Session!
override func viewDidLoad() {
super.viewDidLoad()
session = Session(serverTrustManager: ServerTrustManager(evaluators: evaluators))
session.request("https://localhost:443/")
.response { (response) in
print(response)
}
}
}
struct Certificates {
static let stackExchange =
Certificates.certificate(filename: "tomcat")
private static func certificate(filename: String) -> SecCertificate {
let filePath = Bundle.main.path(forResource: filename, ofType: "cer")!
let data = try! Data(contentsOf: URL(fileURLWithPath: filePath))
let certificate = SecCertificateCreateWithData(nil, data as CFData)!
print(certificate)
return certificate
}
}
打印提示:
<cert(0x7ffc1bc04eb0) s: localhost i: localhost>
success(Optional(11394 bytes))
另外一种思路来验证关于https认证问题,那就是去腾讯云或者Ali云付费买一个域名,仅仅是为了测试,不需要买.com或者.cn的那种,有.xyz的那种,1元/年,申请成功后的域名,在Ali云上解析成功后,会自动给你生成tomcat,Apache,Nginx和IIS的证书,然后同样的方式配置tomcat后,在腾讯云/Ali云添加的你的域名指向你本地的ip,然后就可以测试https认证了
####腾讯云的大致界面
tomcat配置如下
keystoreFile是下载后的文件路径
keystorePass是密码
<Connector port="443" protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="/Users/liguicheng/Desktop/Tomcat/trump.xyz.jks"
keystorePass="xxxxxxx"
sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_RC4_128_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA,SSL_RSA_WITH_RC4_128_SHA"
/>