我正在使用Starscream套接字库,我正在尝试使用WSS但是我握手失败了。我拿到了自签名证书,我将其转换为.der文件。这是我正在尝试的代码
var socket = WebSocket(url: URL(string: "wss://192.168.1.130:6223")!, protocols: [])
override func viewDidLoad() {
super.viewDidLoad()
do
{
let urlPath = Bundle.main.path(forResource: "my_cert", ofType: "der")
let url = NSURL.fileURL(withPath: urlPath!)
let certificateData = try Data(contentsOf: url)
let certificate: SecCertificate =
SecCertificateCreateWithData(kCFAllocatorDefault, certificateData as CFData)!
var trust: SecTrust?
let policy = SecPolicyCreateBasicX509()
let status = SecTrustCreateWithCertificates(certificate, policy, &trust)
if status == errSecSuccess {
let key = SecTrustCopyPublicKey(trust!)!;
let ssl = SSLCert(key: key)
socket.security = SSLSecurity(certs: [ssl], usePublicKeys: true)
socket.delegate = self
socket.connect()
}
}catch let error as NSError
{
print(error)
}
}
因此,当我尝试连接时,收到以下错误消息
2017-07-07 11:06:26.590 CertificateTesting [5180:81661] CFNetwork SSLHandshake失败(-9807)websocket断开连接:操作 无法完成。 (OSStatus错误-9807。)
证书应该可以正常工作,我的Android同事已经尝试过并且没有任何问题。我可以让它在我身边工作的唯一方法是如果我禁用SSL验证
socket.disableSSLCertValidation = true
有没有人有使用套接字的自签名SSL的经验。任何信息都将非常感激。
编辑:
我调用了verify ssl命令,它返回
➜ CertificateTesting git:(master) ✗ openssl verify -my_cert.der ca-cert.pem server-cert.pem
usage: verify [-verbose] [-CApath path] [-CAfile file] [-purpose purpose] [-crl_check] [-engine e] cert1 cert2 ...
recognized usages:
sslclient SSL client
sslserver SSL server
nssslserver Netscape SSL server
smimesign S/MIME signing
smimeencrypt S/MIME encryption
crlsign CRL signing
any Any Purpose
ocsphelper OCSP helper
看起来没问题吗?
答案 0 :(得分:0)
您可以尝试使用WebSocket中的通用名称而不是IP。
var socket = WebSocket(url: URL(string: "wss://192.168.1.130:6223")!, protocols: [])
您可以使用命令
验证证书中的通用名称。openssl x509 -in <certificate file> -text
使用以下命令验证SSL握手
openssl s_client -host <common name mentioned in the cert> -port <port> -cert <client_cert file> -key <client_key file> -CAfile <ca_cert file>
答案 1 :(得分:0)
在一个旧的swift应用程序中,我使用自签名证书公开的REST API和WS遇到相同的问题。
Websocket协议嵌入在HTTP / S协议中,也是握手协议。
因此生成证书.cert: 回声-n | openssl s_client -connect 您的网址:443 | sed -ne'/ -BEGIN CERTIFICATE-/,/-END CERTIFICATE- / p'> name_youwant .cert
将.cert文件导入将使用该文件的应用程序资产中。
在建立Websocket连接的类中,实现URLSessionDelegate。
然后使用此逻辑来验证自签名证书:
注意: NSBundle.mainBundle()。pathForResource(Config.certificate,ofType:“ .cert”)-> Config.certificate是指示文件名的静态字符串。
// uncomment if self signed certificate is used on the backend
public func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
let serverTrust = challenge.protectionSpace.serverTrust
let certificate = SecTrustGetCertificateAtIndex(serverTrust!, 0)
let certificateData = SecCertificateCopyData(certificate!)
let remoteCertificateData = certificateData as NSData
let cerPath = NSBundle.mainBundle().pathForResource(Config.certificate, ofType: ".cert")
let localCertData = NSData(contentsOfFile: cerPath!)!
if localCertData.isEqualToData(remoteCertificateData) {
completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential,NSURLCredential(forTrust:
challenge.protectionSpace.serverTrust!))
}else{
completionHandler(NSURLSessionAuthChallengeDisposition.CancelAuthenticationChallenge,nil)
}
}
希望这会有所帮助。 问候