4 Replies
      Latest reply on Aug 5, 2019 3:32 AM by eskimo
      JLJohnson Level 1 Level 1 (0 points)

        The Keychain item attribute key kSecAttrIsInvisible is described as:

        A key whose value is a Boolean indicating the item's visibility.

        This has been available in the iOS SDK since iOS 2.0+.

         

        I assume that this may hide the Keychain item from appearing on a macOS system where the user can view the Keychain items via the Keychain Access app.

         

        My question is, what does enabling this attribute key do on an iOS device, if anything?

        • Re: Relevance of kSecAttrIsInvisible in iOS
          eskimo Apple Staff Apple Staff (11,805 points)

          I assume that this may hide the Keychain item from appearing on a macOS system where the user can view the Keychain items via the Keychain Access app.

          Correct.

          My question is, what does enabling this attribute key do on an iOS device, if anything?

          Not much.  Given that iOS does not have a general-purpose way to view keychain items, the only specific effect I can think of relates to iCloud Keychain.  If the item gets sync’d over to a Mac via iCloud Keychain, you might want to make it invisible there.

          Share and Enjoy

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

          • Re: Relevance of kSecAttrIsInvisible in iOS
            Max_B Level 1 Level 1 (5 points)

            BEWARE anyway :

             

            I recently added this attribute to hide some items from my iOS application when the iCloud keychain is active and can be seen on a Mac, also because the MacOS version of our app is now almost ready.

             

            And we faced critical situation where iOS users where unable to store their purchases in the Keychain because of this obscure and undocumented behaviour :

            • If you setup a dictionary to delete and rewrite an item in the KC, adding the kSecAttrIsInvisible attribute, then the delete will FAIL if the previous write was done without the invisible attribute. The error is errSecItemNotFound. Because the item is not deleted, it can't be stored again.
            • On the contrary, an item stored with the invisible attribute can be deleted with a query dictionary including or not including the attribute.

             

            So to correctly migrate to using this attribute one should :

            1. Delete an item with a query without the kSecAttrIsInvisible attribute.
            2. If the delete fails, redo the delete with the attribute. We did not see that situation but it should be planned in the code.
            3. Then write the item with the attribute.

             

            Future delete can succeed with the attribute, but the previous steps work with only one attempt to delete in any case we tested.

              • Re: Relevance of kSecAttrIsInvisible in iOS
                eskimo Apple Staff Apple Staff (11,805 points)

                If you setup a dictionary to delete and rewrite an item in the KC, adding the kSecAttrIsInvisible attribute, then the delete will FAIL if the previous write was done without the invisible attribute.

                Right.  This is expected behaviour.  Remember that the dictionary you pass to SecItemDelete is a query dictionary: It’s used to match the items to delete.  If you supply a specific attribute value, the query will on match items with that value, meaning it’ll fail to match:

                • Items with a different value

                • Items with no value

                My preferred approach for dealing with the keychain is to carefully limit the contents of my query dictionary to those attributes that participate in uniqueness.  There’s a list of such attributes in the docs for errSecDuplicateItem.

                Share and Enjoy

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