2 Replies
      Latest reply on Dec 3, 2019 5:18 AM by reto
      reto Level 1 Level 1 (0 points)

        In my app i use the iOS keychain to store a private key (ec-256) for message signature.

        The code is working since iOS 11, but I can experience with iOS 13, that the TouchID popup when accessing the private key in the keychain is missing the custom text. It only shows one line: TouchID for "<APP NAME>", the custom text is not displayed. Using iOS 11 and iOS 12, there is a second line in the TouchID popup below that line.


        Code to generate/store the key in the keychain:

        let access: SecAccessControl
        if #available(iOS 11.3, *) {
          access = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, [.privateKeyUsage, .biometryCurrentSet], nil)!
        } else {
          access = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, [.privateKeyUsage, .touchIDCurrentSet], nil)!
        let attributes = [
          kSecAttrKeyClass: kSecAttrKeyClassPrivate,
          kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
          kSecAttrKeySizeInBits: 256,
          kSecAttrTokenID: kSecAttrTokenIDSecureEnclave,
          kSecPrivateKeyAttrs: [
          kSecAttrIsPermanent: true,
          kSecAttrApplicationTag: keyTag,
          kSecAttrAccessControl: access
          ]  as [String: Any]
        ] as [String: Any]
        var error: Unmanaged<CFError>?
        guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
          throw error!.takeRetainedValue() as Error

        Code to retrieve the private key to sign a message:

        let authenticationText = NSLocalizedString("BIOMETRICS_LOGIN__FINGERPRINT_REQUEST_MESSAGE", comment: "")
        let query = [
          kSecClass: kSecClassKey,
          kSecAttrKeyClass: kSecAttrKeyClassPrivate,
          kSecUseOperationPrompt: "\(authenticationText) \(accountId)",
          kSecAttrApplicationTag: keyTag,
          kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
          kSecReturnRef: true
        ] as [String: Any]
        var item: CFTypeRef?
        let status = SecItemCopyMatching(query as CFDictionary, &item)
        guard status == errSecSuccess else {
          throw AccountStorageError.privateKeyNotFound        
        let privateKey = item as! SecKey


        The above code works in all supported iOS versions (11, 12, 13 up to 13.2.3), private keys can be stored and retrieved, but only on iOS 13 devices, the text specified in kSecUseOperationPrompt is not displayed in the TouchID popup.


        Is there something wrong or is this a known issue in iOS 13?