Keychain 中同一个 kSecAttrAccount 的两个不同值

Two different values from the same kSecAttrAccount in Keychain

对此我真的很纳闷

我有一个 class 初始化如下:

class MyClass {
  let storage = Storage.sharedService

  static let sharedInstance = MyClass()
  fileprivate init() {
    storage.dumpKeychain()
    v1 = storage.loadNonimportantValue()
    print("V1: \(v1 ?? "nil")")
    v2 = storage.loadImportantValue()
    print("V2: \(v2 ?? "nil")")
  }
}

storage.dumpKeychain() 是打印我的应用程序可访问的钥匙串内容的函数(取自互联网)

func dumpKeychain() {
  let query: [String: Any] = [
    kSecClass as String : kSecClassGenericPassword,
    kSecReturnData as String  : kCFBooleanFalse!,
    kSecReturnAttributes as String : kCFBooleanTrue!,
    kSecReturnRef as String : kCFBooleanTrue!,
    kSecMatchLimit as String: kSecMatchLimitAll
  ]

  var result: AnyObject?

  let lastResultCode = withUnsafeMutablePointer(to: &result) {
    SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer([=11=]))
  }

  var values = [String:String]()
  if lastResultCode == noErr {
    let array = result as? Array<Dictionary<String, Any>>
    for item in array! {
      if let key = item[kSecAttrAccount as String] as? String, let value = item[kSecValueData as String] as? Data {
        values[key] = String(data: value, encoding:.utf8)
      }
    }
  }
  print(values)
}

而 storage.loadImportantValue() 是从给定的 kSecAttrAccount(“重要”)加载值的函数

fileprivate func loadImportantValue() -> String? {

  var readQuery : [String : Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrAccount as String: "Important",
    kSecReturnData as String: kCFBooleanTrue!
  ]

  var storedData : AnyObject?
  _ = SecItemCopyMatching(readQuery as CFDictionary, &storedData);

  return String(data: storedData as? Data, encoding: String.Encoding.utf8)
}

我在日志中看到的是 dumpKeychain returns:

[..., "Nonimportant": "correct value", "Important": "correct value", ...]

MyClass 初始化程序中的 print(value) 行打印:

V1: "correct value"
V2: "incorrect value"

这两个调用怎么可能几乎一个接一个 return V2 钥匙串中同一位置的两个不同值,同时 V1 没问题?

谢谢

好的,我找到问题了。 确实有两个不同的数据值。

这个 class 是更新后执行此操作的框架的一部分。因此,以前版本的框架使用另一个框架来管理钥匙串,并且该框架存储的数据具有比我的新版本更多的属性。我认为替换数据实际上是添加属性较少的新条目。

所以在 运行 遗留代码之后的最后,然后用新版本更新它,在“相同”键处有两个数据条目。