7 Replies
      Latest reply: Dec 9, 2016 1:00 AM by Honda_MW RSS
      Honda_MW Level 1 Level 1 (0 points)

        My code is here.

         

        
            class func sslCertificate() -> SecCertificateRef? {
              
                if let path = NSBundle.mainBundle().pathForResource('CERTIFICATE_NAME', ofType: "der") {
                    if let data = NSData(contentsOfFile: path) {
                        let cfData = CFDataCreate(kCFAllocatorDefault, UnsafePointer<UInt8>(data.bytes), data.length)
                      
                        let cert:SecCertificateRef? = SecCertificateCreateWithData(kCFAllocatorDefault, cfData)
                        return cert
                    }
                }
              
                return nil
            }
        

         

        SecCertificateCreateWithData is always return nil.

        What kind of problems can be considered?

        • Re: Why SecCertificateCreateWithData is always return nil?
          eskimo Apple Staff Apple Staff (7,025 points)

          Three things…


          What version of Swift are you using here?  Judging by your use of NSBundle (rather than Bundle) I presume you’re using Swift 2 of some form.  Is that right?


          You don’t need to create your own CFData here; Swift will automatically go from NSData to CFData like this:

          let cert = SecCertificateCreateWithData(nil, data)
          

          If you’re using Data (in Swift 3) you’ll need to bounce to NSData.

          let cert = SecCertificateCreateWithData(nil, data as NSData)
          

          The most common reason for SecCertificateCreateWithData to return nil is that the data isn’t a valid certificate.  A common problem is that folks try to pass in a PEM format certificate, whereas SecCertificateCreateWithData requires DER.  If you open the certificate with a text editor, do you see Base64?  Or do you see binary goo?  If you see Base64, you’ll need to convert the certificate to binary (DER) form before passing to to SecCertificateCreateWithData.  For a single certificate that you include in your bundle, you can just pre-convert it using Keychain Access on the Mac.

          OTOH, if it’s already in binary form, there’s something broken within the certificate itself.  If you post a hex dump of that binary data I can take a look.

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

            • Re: Why SecCertificateCreateWithData is always return nil?
              Honda_MW Level 1 Level 1 (0 points)

              I using Swift2.

               

              I checked my certificate.That's seem Base64 encoded.But extension is DER.

              00000000  42 61 67 20 41 74 74 72  69 62 75 74 65 73 0a 20  |Bag Attributes. |
              00000010  20 20 20 6c 6f 63 61 6c  4b 65 79 49 44 3a 20 30  |   localKeyID: 0|
              00000020  31 20 30 30 20 30 30 20  30 30 20 0a 73 75 62 6a  |1 00 00 00 .subj|
              00000030  65 63 74 3d 2f 43 3d 5c  78 45 36 5c 78 39 37 5c  |ect=/C=\xE6\x97\|
              00000040  78 41 35 5c 78 45 36 5c  78 39 43 5c 78 41 43 2f  |xA5\xE6\x9C\xAC/|
              00000050  53 54 3d 5c 78 45 36 5c  78 39 44 5c 78 42 31 5c  |ST=\xE6\x9D\xB1\|
              00000060  78 45 34 5c 78 42 41 5c  78 41 43 5c 78 45 39 5c  |xE4\xBA\xAC\xE9\|
              00000070  78 38 33 5c 78 42 44 2f  4f 3d 5c 78 45 36 5c 78  |x83\xBD/O=\xE6\x|
              00000080
              

              At first I converted p12 format to DER with openssl. Is this not okay?

                • Re: Why SecCertificateCreateWithData is always return nil?
                  eskimo Apple Staff Apple Staff (7,025 points)

                  I checked my certificate.That's seem Base64 encoded.But extension is DER.

                  Yeah, that’s a problem.  This sort of textual representation is indicative of PEM.  SecCertificateCreateWithData can’t deal with PEM.  You have two choices:

                  • If you’re working with a certificate hard-wired into your app, you can just use some tool (like Keychain Utility or the x509 subcommand of openssl) to convert the certificate to DER and add that to your app.

                  • If you have to handle arbitrary certificates at runtime, you’ll need to undo the Base64 encoding.

                  Share and Enjoy

                  Quinn “The Eskimo!”
                  Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                  let myEmail = "eskimo" + "1" + "@apple.com"

                    • Re: Why SecCertificateCreateWithData is always return nil?
                      Honda_MW Level 1 Level 1 (0 points)

                      Thanks a lot.I solved problem.

                      But I got new problem.

                       

                      When I checked SecTrustResultType.hashValue,that's value was kSecTrustResultRecoverableTrustFailure.

                      When installing a certificate in General, it was possible to communicate normally.

                      So I think that there is probably no problem with the certificate.

                       

                      What kind of problems can be considered?

                        • Re: Why SecCertificateCreateWithData is always return nil?
                          eskimo Apple Staff Apple Staff (7,025 points)

                          First up, I moved your thread to Core OS > Security because there’s nothing particularly Swift-specific here.

                          Secondly, you wrote:

                          When installing a certificate in General, it was possible to communicate normally.

                          You mean in Settings > General, right?

                          Please explain more about what you’re trying to do here.  This is the first time you’ve mentioned communication — so far this thread has been about importing a certificate — so it’s hard to understand what’s going on without more context.

                          Also, are you using TLS?  If so, you might want to read my TLS for App Developers post, which provides a bunch of background on that subject.


                          ps With regards this:

                          When I checked SecTrustResultType.hashValue,that's value was kSecTrustResultRecoverableTrustFailure.

                          if you want to get the numeric representation of an enum like SecTrustResultType, you should use the rawValue property.  The hashValue property gives you a hash, which in this case just happens to match up but is not guaranteed to do so.

                          Share and Enjoy

                          Quinn “The Eskimo!”
                          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                          let myEmail = "eskimo" + "1" + "@apple.com"

                            • Re: Why SecCertificateCreateWithData is always return nil?
                              Honda_MW Level 1 Level 1 (0 points)

                              Sorry.I explain what I want to do in the first place.

                               

                              I connect to server from my application then needs TLS/SSL.

                              Server certificate is self-signed certificate.

                              I prepared rootCA certificate and client certificate for TLS/SSL connection.

                              When I want to got these certificate the first problem occured.

                               

                              In addition, the following settings are made.

                              When connecting to the server, it is connected with a port other than 443.

                              ATS is disabled.

                              I'm using own wrapper class that was  subclass of NSURLConnection.

                               

                              My code is here.

                                  func connection(connection: NSURLConnection, willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge) {
                                      if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
                                          print(challenge.protectionSpace.host)
                                          print(ConstStruct.HOST)
                                          if challenge.protectionSpace.host == ConstStruct.HOST.stringByReplacingOccurrencesOfString(":PortNo", withString: "") && NSString(string:ConstStruct.HOST).rangeOfString(":PortNo").location != NSNotFound {
                                           
                                              let protectionSpace = challenge.protectionSpace
                                              let trust = protectionSpace.serverTrust
                                           
                                              let certs: [CFTypeRef] = [HttpPostHelper.sslCertificate() as! CFTypeRef]
                                              let certArrayRef : CFArrayRef = CFBridgingRetain(certs as NSArray) as! CFArrayRef
                                           
                                              var status = SecTrustSetAnchorCertificates(trust!, certArrayRef)
                                              if status != errSecSuccess {
                                                  print("SecTrustSetAnchorCertificates")
                                                  connection.cancel()
                                                  return
                                              }
                              /
                                              let rootCa = "ROOTCA_FILENAME"
                                              if let rootCaPath = NSBundle.mainBundle().pathForResource(rootCa, ofType: "der") {
                                                  if let rootCaData = NSData(contentsOfFile: rootCaPath) {
                                                      if let rootCert = SecCertificateCreateWithData(nil, rootCaData) {
                                                          SecTrustSetAnchorCertificates(trust!, CFBridgingRetain([rootCert,HttpPostHelper.sslCertificate() as! CFTypeRef] as NSArray) as! CFArrayRef)
                                                          SecTrustSetAnchorCertificatesOnly(trust!, false) // also allow regular CAs.
                                                      }
                                                  }
                                              }
                              */             
                                              var trustResult:SecTrustResultType = SecTrustResultType(kSecTrustResultInvalid)
                                              status = SecTrustEvaluate(trust!, &trustResult)
                                           
                                              if status != errSecSuccess {
                                                  print("SecTrustEvaluate")
                                                  print("trustResult")
                                                  connection.cancel()
                                                  return
                                              }
                                           
                                              switch trustResult.hashValue {
                                              case kSecTrustResultProceed,kSecTrustResultUnspecified:
                                                  challenge.sender?.useCredential(NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!), forAuthenticationChallenge: challenge)
                                                  return
                                              case kSecTrustResultRecoverableTrustFailure:
                                                  challenge.sender?.cancelAuthenticationChallenge(challenge)
                                                  connection.cancel()
                                                  break
                                              default:
                                                  challenge.sender?.cancelAuthenticationChallenge(challenge)
                                                  connection.cancel()
                                                  break
                                              }
                                           
                                              challenge.sender?.useCredential(NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!), forAuthenticationChallenge: challenge)
                                              challenge.sender?.continueWithoutCredentialForAuthenticationChallenge(challenge)
                                          }
                                      }
                                  }
                              

                              Running comment lines 19 to 29 did not change the result.

                               

                              Are there causes in this?

                              • Re: Why SecCertificateCreateWithData is always return nil?
                                Honda_MW Level 1 Level 1 (0 points)

                                Hi,eskimo.I rewritten my wrapper class with NSURLSession.But that problem was not solved.

                                I read other articles, but I think whether specifying direct connection by IP address is not good.Is that right?

                                My test server does'nt have domain name.How do I test it?