【问题标题】:using public key encryption in swift快速使用公钥加密
【发布时间】:2015-11-30 09:09:27
【问题描述】:

我正在尝试使用 Web 服务开发人员提供给我的公钥来安全地传输数据。我已经很努力了,但我找不到任何使用最新 swift 版本的工作示例。我的编码如下(在here的帮助下:

func connection(connection: NSURLConnection, willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge){
    if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
        var localTrust: UnsafeMutablePointer<SecTrust?>
        let serverTrust = challenge.protectionSpace.serverTrust!
        let serverPublicKey = SecTrustCopyPublicKey(serverTrust)
        let certificateData = NSData(contentsOfFile: NSBundle.mainBundle().pathForResource("pinning-certificate", ofType: "der")!)
        let localCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, certificateData!)
        let policy = SecPolicyCreateBasicX509()

        if SecTrustCreateWithCertificates(localCertificate!, policy, localTrust) == errSecSuccess {
            let localTrustRef = localTrust
            let localPublicKey = SecTrustCopyPublicKey(localTrustRef)!
            if (localPublicKey as AnyObject).isEqual(serverPublicKey as! AnyObject) {
                print("trusted")
                return challenge.sender!.performDefaultHandlingForAuthenticationChallenge!(challenge)
            }
        }
    }
    print("not trusted")
    return challenge.sender!.cancelAuthenticationChallenge(challenge)
   }

但是在 SecTrustCreateWithCertificates() 和 SecTrustCopyPublicKey() 中编译期间出现以下错误: 无法转换“UnsafeMutablePointer”类型的值?到预期的参数类型“UnsafeMutablePointer”(又名“UnsafeMutablePointer>”)

编辑 1: 我已将代码更改为以下,现在我的代码已执行,但服务器未收到任何请求:

func extractIdentity(certData:NSData) -> IdentityAndTrust {
    var identityAndTrust:IdentityAndTrust!
    var securityError:OSStatus = errSecSuccess

    let path: String = NSBundle.mainBundle().pathForResource("MobileAppClient", ofType: "pfx")!
    let PKCS12Data = NSData(contentsOfFile:path)!
    let key : NSString = kSecImportExportPassphrase as NSString
    let options : NSDictionary = [key : "client"]

    //create variable for holding security information
    //var privateKeyRef: SecKeyRef? = nil

    var items : CFArray?
    securityError = SecPKCS12Import(PKCS12Data, options, &items)

        if securityError == errSecSuccess {
        let certItems:CFArray = items as CFArray!;
        let certItemsArray:Array = certItems as Array
        let dict:AnyObject? = certItemsArray.first;
        if let certEntry:Dictionary = dict as? Dictionary<String, AnyObject> {

            // grab the identity
            let identityPointer:AnyObject? = certEntry["identity"];
            let secIdentityRef:SecIdentityRef = identityPointer as! SecIdentityRef!;
            print("\(identityPointer)  :::: \(secIdentityRef)")
            // grab the trust
            let trustPointer:AnyObject? = certEntry["trust"];
            let trustRef:SecTrustRef = trustPointer as! SecTrustRef;
            print("\(trustPointer)  :::: \(trustRef)")
            // grab the cert
            let chainPointer:AnyObject? = certEntry["chain"];
            identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef, certArray:  chainPointer! as! NSArray);
        }
    }
    return identityAndTrust;
}
func connection(connection: NSURLConnection, willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge){

    if challenge.protectionSpace.authenticationMethod == (NSURLAuthenticationMethodServerTrust) {

        let serverTrust:SecTrustRef = challenge.protectionSpace.serverTrust!
        let certificate: SecCertificateRef = SecTrustGetCertificateAtIndex(serverTrust, 0)!
        let remoteCertificateData = CFBridgingRetain(SecCertificateCopyData(certificate))!
        let cerPath: String = NSBundle.mainBundle().pathForResource("Certificates", ofType: "cer")!
        let localCertificateData = NSData(contentsOfFile:cerPath)!

        challenge.sender?.useCredential(credential, forAuthenticationChallenge: challenge)

                    if (remoteCertificateData.isEqualToData(localCertificateData) == true) {
            let credential:NSURLCredential = NSURLCredential(forTrust: serverTrust)

            challenge.sender?.useCredential(credential, forAuthenticationChallenge: challenge)

        } else {
            SVProgressHUD.dismiss()
            return challenge.sender!.performDefaultHandlingForAuthenticationChallenge!(challenge)
        }

    }
    else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate
    {

        let path: String = NSBundle.mainBundle().pathForResource("Certificates", ofType: "p12")!
        let PKCS12Data = NSData(contentsOfFile:path)!


        let identityAndTrust:IdentityAndTrust = self.extractIdentity(PKCS12Data);



        let urlCredential:NSURLCredential = NSURLCredential(
            identity: identityAndTrust.identityRef,
            certificates: identityAndTrust.certArray as? [AnyObject],
            persistence: NSURLCredentialPersistence.ForSession);
        challenge.sender?.useCredential(urlCredential, forAuthenticationChallenge: challenge)


    }

}

【问题讨论】:

    标签: ios swift ssl-certificate public-key-encryption


    【解决方案1】:

    请在下面找到答案:

     func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
    
       if challenge.protectionSpace.authenticationMethod == (NSURLAuthenticationMethodServerTrust) {
    
    
        let serverTrust:SecTrustRef = challenge.protectionSpace.serverTrust!
        let certificate: SecCertificateRef = SecTrustGetCertificateAtIndex(serverTrust, 0)!
        let remoteCertificateData = CFBridgingRetain(SecCertificateCopyData(certificate))!
        let cerPath: String = NSBundle.mainBundle().pathForResource("xyz.com", ofType: "cer")!
        let localCertificateData = NSData(contentsOfFile:cerPath)!
    
    
            if (remoteCertificateData.isEqualToData(localCertificateData) == true) {
                let credential:NSURLCredential = NSURLCredential(forTrust: serverTrust)
    
                challenge.sender?.useCredential(credential, forAuthenticationChallenge: challenge)
    
    
                completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!))
    
            } else {
    
                completionHandler(NSURLSessionAuthChallengeDisposition.CancelAuthenticationChallenge, nil)
            }
        }
        else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate
        {
    
            let path: String = NSBundle.mainBundle().pathForResource("client", ofType: "p12")!
            let PKCS12Data = NSData(contentsOfFile:path)!
    
    
            let identityAndTrust:IdentityAndTrust = self.extractIdentity(PKCS12Data);
    
    
    
                let urlCredential:NSURLCredential = NSURLCredential(
                    identity: identityAndTrust.identityRef,
                    certificates: identityAndTrust.certArray as? [AnyObject],
                    persistence: NSURLCredentialPersistence.ForSession);
    
                completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, urlCredential);
    
    
    
    
        }
        else
        {
            completionHandler(NSURLSessionAuthChallengeDisposition.CancelAuthenticationChallenge, nil);
        }
      }
    

    添加以下代码

     struct IdentityAndTrust {
    
        var identityRef:SecIdentityRef
        var trust:SecTrustRef
        var certArray:AnyObject
    }
    
    func extractIdentity(certData:NSData) -> IdentityAndTrust {
        var identityAndTrust:IdentityAndTrust!
        var securityError:OSStatus = errSecSuccess
    
        let path: String = NSBundle.mainBundle().pathForResource("client", ofType: "p12")!
        let PKCS12Data = NSData(contentsOfFile:path)!
        let key : NSString = kSecImportExportPassphrase as NSString
        let options : NSDictionary = [key : "xyz"]
        //create variable for holding security information
        //var privateKeyRef: SecKeyRef? = nil
    
        var items : CFArray?
    
         securityError = SecPKCS12Import(PKCS12Data, options, &items)
    
        if securityError == errSecSuccess {
            let certItems:CFArray = items as CFArray!;
            let certItemsArray:Array = certItems as Array
            let dict:AnyObject? = certItemsArray.first;
            if let certEntry:Dictionary = dict as? Dictionary<String, AnyObject> {
    
                // grab the identity
                let identityPointer:AnyObject? = certEntry["identity"];
                let secIdentityRef:SecIdentityRef = identityPointer as! SecIdentityRef!;
                print("\(identityPointer)  :::: \(secIdentityRef)")
                // grab the trust
                let trustPointer:AnyObject? = certEntry["trust"];
                let trustRef:SecTrustRef = trustPointer as! SecTrustRef;
                print("\(trustPointer)  :::: \(trustRef)")
                // grab the cert
                let chainPointer:AnyObject? = certEntry["chain"];
                identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef, certArray:  chainPointer!);
            }
        }
        return identityAndTrust;
    }
    

    【讨论】:

    • 嗨 Karlos,我在以下行中遇到错误:let serverTrust:SecTrustRef = challenge.protectionSpace.serverTrust!我收到致命错误:在展开可选值时意外发现 nil
    • 很抱歉这么多天才回复,但是客户端证书之前没有安装在服务器上,昨天才配置好
    • 我认为后端服务器没有在挑战中发送服务器信任或其他原因可能是因为密码套装。另请检查您的后端服务器是否支持 Apple 支持的以下密码套件:developer.apple.com/library/ios/documentation/General/Reference/… 在此链接中搜索“使用 ATS 连接的要求”
    • 同时检查 info.plist 中的设置,如以下链接stackoverflow.com/questions/34073822/…的答案中给出的那样
    • ATS 在我之前使用服务时为我工作,现在服务器人员添加了基于证书的身份验证并给了我访问密钥
    【解决方案2】:

    我认为有2个问题:

    1) 要转换 UnsafeMutablePointer 你应该调用 localTrust.memory 但它会给你下一个错误 2)下一个错误会给你那个未初始化的指针,我想你可以使用这样的代码:

    func connection(connection: NSURLConnection, willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge){
        if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
            var localTrust: UnsafeMutablePointer<SecTrust?> = nil
            let serverTrust = challenge.protectionSpace.serverTrust!
            let serverPublicKey = SecTrustCopyPublicKey(serverTrust)
            let certificateData = NSData(contentsOfFile: NSBundle.mainBundle().pathForResource("pinning-certificate", ofType: "der")!)
            let localCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, certificateData!)
            let policy = SecPolicyCreateBasicX509()
    
            if SecTrustCreateWithCertificates(localCertificate!, policy, localTrust) == errSecSuccess {
                let localTrustRef = localTrust
                let localPublicKey = SecTrustCopyPublicKey(localTrustRef.memory!)!
                if (localPublicKey as AnyObject).isEqual(serverPublicKey as! AnyObject) {
                    print("trusted")
                    return challenge.sender!.performDefaultHandlingForAuthenticationChallenge!(challenge)
                }
            }
        }
        print("not trusted")
        return challenge.sender!.cancelAuthenticationChallenge(challenge)
    }
    

    附:强制发送optional 是不安全的。请考虑使用if let 声明

    【讨论】:

    • 感谢您的回复,我使用了您的代码,在编译过程中没有收到任何错误,但在运行时在线时出现 Bad Access 错误:let localPublicKey = SecTrustCopyPublicKey(localTrustRef.memory!)!跨度>
    猜你喜欢
    • 2018-11-04
    • 2022-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-17
    • 2014-06-23
    相关资源
    最近更新 更多