Swift中的iOS SSL连接

Swift中的iOS SSL连接,第1张

概述我正在尝试从我的iOS应用程序到我的后端服务器(Node.js)建立一个简单的套接字连接(无HTTP).已使用我自己创建的自定义CA创建并签署了服务器证书.我相信,为了让iOS信任我的服务器,我必须以某种方式将这个自定义CA证书添加到可信证书列表中,这些证书用于确定Java / Android中的TrustStore如何工作的信任类型. 我尝试使用下面的代码进行连接,但没有错误,但write()函 @H_403_0@ 我正在尝试从我的iOS应用程序到我的后端服务器(Node.Js)建立一个简单的套接字连接(无http).已使用我自己创建的自定义CA创建并签署了服务器证书.我相信,为了让iOS信任我的服务器,我必须以某种方式将这个自定义CA证书添加到可信证书列表中,这些证书用于确定Java / AndroID中的TrustStore如何工作的信任类型.

我尝试使用下面的代码进行连接,但没有错误,但write()函数似乎没有成功.

主视图控制器:

overrIDe func vIEwDIDLoad() {    super.vIEwDIDLoad()    // Do any additional setup after loading the vIEw,typically from a nib.    let API: apiclient = apiclient()    API.initialiseSSL("10.13.37.200",port: 8080)    API.write("Hello")    API.deinitialise()    print("Done")}

apiclient类

class apiclient: NSObject,NsstreamDelegate {var readStream: Unmanaged<CFReadStreamRef>?var writeStream: Unmanaged<CFWriteStreamRef>?var inputStream: NSinputStream?var outputStream: NSOutputStream?func initialiseSSL(host: String,port: UInt32) {    CFStreamCreatePairWithSocketToHost(kcfAllocatorDefault,host,port,&readStream,&writeStream)    inputStream = readStream!.takeRetainedValue()    outputStream = writeStream!.takeRetainedValue()    inputStream?.delegate = self    outputStream?.delegate = self    inputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(),forMode: NSDefaultRunLoopMode)    outputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(),forMode: NSDefaultRunLoopMode)    let cert: SecCertificateRef? = CreateCertificateFromfile("ca",ext: "der")    if cert != nil {        print("GOT CERTIFICATE")    }    let certs: NSArray = NSArray(objects: cert!)    let sslSettings = [        Nsstring(format: kcfStreamSsllevel): kcfStreamSocketSecurityLevelNegotiatedSSL,Nsstring(format: kcfStreamSSLValIDatesCertificateChain): kcfBooleanFalse,Nsstring(format: kcfStreamSSLPeername): kcfNull,Nsstring(format: kcfStreamSSLCertificates): certs,Nsstring(format: kcfStreamSSlisServer): kcfBooleanFalse    ]    CFReadStreamSetProperty(inputStream,kcfStreamPropertySSLSettings,sslSettings)    CFWriteStreamSetProperty(outputStream,sslSettings)    inputStream!.open()    outputStream!.open()}func write(text: String) {    let data = [UInt8](text.utf8)    outputStream?.write(data,maxLength: data.count)}func CreateCertificateFromfile(filename: String,ext: String) -> SecCertificateRef? {    var cert: SecCertificateRef!    if let path = NSBundle.mainBundle().pathForResource(filename,ofType: ext) {        let data = NSData(contentsOffile: path)!        cert = SecCertificateCreateWithData(kcfAllocatorDefault,data)!    }    else {    }    return cert}func deinitialise() {    inputStream?.close()    outputStream?.close()}

}

我理解SSL / TLS是如何工作的,因为我在同一个应用程序的AndroID版本中完成了这一切.我只是对SSL的iOS实现感到困惑.

我来自Java背景,已经解决了这个问题3周.任何帮助,将不胜感激.

喜欢Swift代码中的答案,而不是目标C,但如果你只有Obj C那也可以:)

好吧,我在这个问题上花了8个星期:(但我终于设法组建了一个有效的解决方案.我必须说iOS上的SSL / TLS是一个笑话.Java AndroID上的Java让它死了.这是完全荒谬的,为了评估自签名证书的信任,您必须完全禁用证书链验证并自行完成.完全荒谬.无论如何,这是使用自签名服务器证书连接到远程套接字服务器(无http)的完全可用的解决方案.编辑这个答案以提供更好的答案,因为我还没有更改添加发送和接收数据的代码:)
//  SecureSocket////  Created by snapper26 on 2/9/16.//  copyright © 2016 snapper26. All rights reserved.//import Foundationclass ProXimityapiclient: NSObject,StreamDelegate {    // input and output streams for socket    var inputStream: inputStream?    var outputStream: OutputStream?    // Secondary delegate reference to prevent ARC deallocating the NsstreamDelegate    var inputDelegate: StreamDelegate?    var outputDelegate: StreamDelegate?    // Add a trusted root CA to out SecTrust object    func addAnchorToTrust(trust: SecTrust,certificate: SecCertificate) -> SecTrust {        let array: NSMutableArray = NSMutableArray()        array.add(certificate)        SecTrustSetAnchorCertificates(trust,array)        return trust    }    // Create a SecCertificate object from a DER formatted certificate file    func createCertificateFromfile(filename: String,ext: String) -> SecCertificate {        let rootCertPath = Bundle.main.path(forResource:filename,ofType: ext)        let rootCertData = NSData(contentsOffile: rootCertPath!)        return SecCertificateCreateWithData(kcfAllocatorDefault,rootCertData!)!    }    // Connect to remote host/server    func connect(host: String,port: Int) {        // Specify host and port number. Get reference to newly created socket streams both in and out        Stream.getStreamsToHost(withname:host,port: port,inputStream: &inputStream,outputStream: &outputStream)        // Create strong delegate reference to stop ARC deallocating the object        inputDelegate = self        outputDelegate = self        // Now that we have a strong reference,assign the object to the stream delegates        inputStream!.delegate = inputDelegate        outputStream!.delegate = outputDelegate        // This doesn't work because of arc memory management. Thats why another strong reference above is needed.        //inputStream!.delegate = self        //outputStream!.delegate = self        // Schedule our run loops. This is needed so that we can receive StreamEvents        inputStream!.schedule(in:RunLoop.main,forMode: RunLoopMode.defaultRunLoopMode)        outputStream!.schedule(in:RunLoop.main,forMode: RunLoopMode.defaultRunLoopMode)        // Enable SSL/TLS on the streams        inputStream!.setProperty(kcfStreamSocketSecurityLevelNegotiatedSSL,forKey:  Stream.PropertyKey.socketSecurityLevelKey)        outputStream!.setProperty(kcfStreamSocketSecurityLevelNegotiatedSSL,forKey: Stream.PropertyKey.socketSecurityLevelKey)        // Defin custom SSL/TLS settings        let sslSettings : [Nsstring: Any] = [            // Nsstream @R_502_6843@matically sets up the socket,the streams and creates a trust object and evaulates it before you even get a chance to check the trust yourself. Only proper SSL certificates will work with this method. If you have a self signed certificate like I do,you need to disable the trust check here and evaulate the trust against your custom root CA yourself.            Nsstring(format: kcfStreamSSLValIDatesCertificateChain): kcfBooleanFalse,//            Nsstring(format: kcfStreamSSLPeername): kcfNull,// We are an SSL/TLS clIEnt,not a server            Nsstring(format: kcfStreamSSlisServer): kcfBooleanFalse        ]        // Set the SSL/TLS settingson the streams        inputStream!.setProperty(sslSettings,forKey:  kcfStreamPropertySSLSettings as Stream.PropertyKey)        outputStream!.setProperty(sslSettings,forKey: kcfStreamPropertySSLSettings as Stream.PropertyKey)        // Open the streams        inputStream!.open()        outputStream!.open()    }    // This is where we get all our events (haven't finished writing this class)   func stream(_ aStream: Stream,handle eventCode: Stream.Event) {        switch eventCode {        case Stream.Event.endEncountered:            print("End Encountered")            break        case Stream.Event.openCompleted:            print("Open Completed")            break        case Stream.Event.hasspaceAvailable:            print("Has Space Available")            // If you try and obtain the trust object (aka kcfStreamPropertySSLPeerTrust) before the stream is available for writing I found that the oject is always nil!            var sslTrustinput: SecTrust? =  inputStream! .property(forKey:kcfStreamPropertySSLPeerTrust as Stream.PropertyKey) as! SecTrust?            var sslTrustOutput: SecTrust? = outputStream!.property(forKey:kcfStreamPropertySSLPeerTrust as Stream.PropertyKey) as! SecTrust?            if (sslTrustinput == nil) {                print("input TRUST NIL")            }            else {                print("input TRUST NOT NIL")            }            if (sslTrustOutput == nil) {                print("OUTPUT TRUST NIL")            }            else {                print("OUTPUT TRUST NOT NIL")            }            // Get our certificate reference. Make sure to add your root certificate file into your project.            let rootCert: SecCertificate? = createCertificateFromfile(filename: "ca",ext: "der")            // Todo: Don't want to keep adding the certificate every time???            // Make sure to add your trusted root CA to the List of trusted anchors otherwise trust evaulation will fail            sslTrustinput  = addAnchorToTrust(trust: sslTrustinput!,certificate: rootCert!)            sslTrustOutput = addAnchorToTrust(trust: sslTrustOutput!,certificate: rootCert!)            // convert kSecTrustResultUnspecifIEd type to SecTrustResultType for comparison            var result: SecTrustResultType = SecTrustResultType.unspecifIEd            // This is it! Evaulate the trust.            let error: Osstatus = SecTrustEvaluate(sslTrustinput!,&result)            // An error occured evaluating the trust check the Osstatus codes for Apple at osstatus.com            if (error != noErr) {                print("Evaluation Failed")            }            if (result != SecTrustResultType.proceed && result != SecTrustResultType.unspecifIEd) {                // Trust Failed. This will happen if you faile to add the trusted anchor as mentioned above                print("Peer is not trusted :(")            }            else {                // Peer certificate is trusted. Now we can send data. Woohoo!                print("Peer is trusted :)")            }            break        case Stream.Event.hasBytesAvailable:            print("Has Bytes Available")            break        case Stream.Event.errorOccurred:            print("Error Occured")            break        default:            print("Default")            break        }    }}
总结

以上是内存溢出为你收集整理的Swift中的iOS SSL连接全部内容,希望文章能够帮你解决Swift中的iOS SSL连接所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1048381.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存