Managing TLS Identities

    Description — Couchbase Lite - this content covers how to manage TLS identities using Couchbase Lite
    Related Content — API Reference | Passive Peer | Active Peer

    Description — Couchbase Lite - this content covers how to manage TLS identities using Couchbase Lite
    Related Content — API Reference | Passive Peer | Active Peer

    Overview

    • This describes the configuration and management of TLS identities

    API References

    You can find Swift API References here.

    Creating TLS Identity

    There are couple of options by which TLS Identity is created:

    Use Anonymous Cert

    Anonymous certification uses the self signed certificate auto-generated by Couchbase Lite when TLS is enabled, but no TLSIdentity is provided.

    listenerConfig.disableTLS  = false // Use with anonymous self signed cert
    listenerConfig.tlsIdentity = nil

    Import a Cert

    Use the TLSIdentity class’s importIdentity() method to import a certificate that can be bundled with the app and-or added to the keychain.

    1. First check the keychain to see if the identity already exists

      // USE KEYCHAIN IDENTITY IF EXISTS
      // Check if Id exists in keychain. If so use that Id
      do {
          if let thisIdentity = try TLSIdentity.identity(withLabel: "doco-sync-server") {
              print("An identity with label : doco-sync-server already exists in keychain")
              return thisIdentity
              }
      } catch
        {return nil}
    2. Check for an existing resource bundle

      // CREATE IDENTITY FROM BUNDLED RESOURCE IF FOUND
      
              // Check for a resource bundle with required label to generate identity from
              // return nil identify if not found
              guard let pathToCert = Bundle.main.path(forResource: "doco-sync-server", ofType: "p12"),
                      let thisData = NSData(contentsOfFile: pathToCert)
                  else
                      {return nil}
    3. Import from an existing resource bundle

      // Use SecPKCS12Import to import the contents (identities and certificates)
      // of the required resource bundle (PKCS #12 formatted blob).
      //
      // Set passphrase using kSecImportExportPassphrase.
      // This passphrase should correspond to what was specified when .p12 file was created
      kcStatus = SecPKCS12Import(thisData as CFData, [String(kSecImportExportPassphrase): "couchbase"] as CFDictionary, &items)
          if kcStatus != errSecSuccess {
           print("failed to import data from provided with error :\(kcStatus) ")
           return nil
          }
      let importedItems = items! as NSArray
      let thisItem = importedItems[0] as! [String: Any]
      
      // Get SecIdentityRef representing the item's id
      let thisSecId = thisItem[String(kSecImportItemIdentity)]  as! SecIdentity
      
      // Get Id's Private Key, return nil id if fails
      var thisPrivateKey : SecKey?
      kcStatus = SecIdentityCopyPrivateKey(thisSecId, &thisPrivateKey)
          if kcStatus != errSecSuccess {
              print("failed to import private key from provided with error :\(kcStatus) ")
              return nil
          }
      
      // Get all relevant certs [SecCertificate] from the ID's cert chain using kSecImportItemCertChain
      let thisCertChain = thisItem[String(kSecImportItemCertChain)] as? [SecCertificate]
      
      // Return nil Id if errors in key or cert chain at this stage
      guard let pKey = thisPrivateKey, let pubCerts = thisCertChain else {
          return nil
      }
    4. Store imported identity in keychain

      // STORE THE IDENTITY AND ITS CERT CHAIN IN THE KEYCHAIN
      
              // Store Private Key in Keychain
              let params: [String : Any] = [
                  String(kSecClass):          kSecClassKey,
                  String(kSecAttrKeyType):    kSecAttrKeyTypeRSA,
                  String(kSecAttrKeyClass):   kSecAttrKeyClassPrivate,
                  String(kSecValueRef):       pKey
              ]
              kcStatus = SecItemAdd(params as CFDictionary, nil)
                  if kcStatus != errSecSuccess {
                      print("Unable to store private key")
                      return nil
                  }
             // Store all Certs for Id in Keychain:
             var i = 0;
             for cert in thisCertChain! {
                  let params: [String : Any] = [
                      String(kSecClass):      kSecClassCertificate,
                      String(kSecValueRef):   cert,
                      String(kSecAttrLabel):  "doco-sync-server"
                      ]
                  kcStatus = SecItemAdd(params as CFDictionary, nil)
                      if kcStatus != errSecSuccess {
                          print("Unable to store certs")
                          return nil
                      }
                  i=i+1
              }
    5. Use keychain identity in config

      // RETURN A TLSIDENTITY FROM THE KEYCHAIN FOR USE IN CONFIGURING TLS COMMUNICATION
      do {
          return try TLSIdentity.identity(withIdentity: thisSecId, certs: [pubCerts[0]])
      } catch {
          print("Error while loading self signed cert : \(error)")
          return nil
      }

    Delete TLS Identity

    try TLSIdentity.deleteIdentity(withLabel: serverCertLabel);
    Enterprise Edition only
    This an Enterprise Edition feature. Purchase the Enterprise License, which includes official Couchbase Support, to use it in production (see the license and support https://www.couchbase.com/licensing-and-support-faq).