How can I test CloudKit User Keychain Reset?

My question

  • Is there a way to perform an iCloud keychain reset in order to be able to test CKErrorUserDidResetEncryptedDataKey ?

I found this section in the CloudKit documentation https://developer.apple.com/documentation/cloudkit/encrypting-user-data#Handle-a-User-Keychain-Reset

I want to be prepared for the zoneNotFound / CKErrorUserDidResetEncryptedDataKey case.

However, I can't find a way to actually reproduce this error with an iCloud (test-) user and can't find any Apple documentation on how to perform sucha "User Keychain Reset".

The only thing that almost looked like it I came across was in the Keychain.app's Settings "Reset Default Keychains…". However, performing this didn't seem to affect the CloudKit data used in our App at all.

I've been trying to do this with an Apple account that has 2FA active and a recovery account assigned.

We're only targetting >= iOS 18, macOS >= 15.

I don't have a testing environment to try for now, but am wondering if you restart the machine after resetting keychains, and also how you verify that the reset doesn't impact the CloudKit data access. Would you mind to share the detailed steps you use for your testing?

Also, did you try to delete the keychains, as described in Delete a keychain in Keychain Access on Mac?

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

The app I'm working on

  • creates a single zone (e.g. CKRecordZone(zoneName: "Documents") in the private database
  • syncs documents as CKRecord to that zone, which have some fields set via encryptedValues[…]
  • When launching the app after clearing local caches, the app fetches all zones and fetches all records from the "Documents" zone if it exists already.
  • in my understanding, the data in CloudKit is encrypted with a key that should be resettable in some way and then would become unreachable afterwards

My setup

  • I tried this with a debug build (icloud development env) and a testflight release (icloud production env) on a separate user on my mac, which was logged in to its own iCloud account.

What did I try?

  • I closed my app, cleared its caches and then
  • ran "Reset Default Keychains…" in the Settings of the Keychain Access app to attempt resetting encrypted data.
  • I relaunched my app

Expected result

  • I expected the "Documents" zone to be gone, and no documents to reappear, technically expecting zoneNotFound+ CKErrorUserDidResetEncryptedDataKey

Actual result

  • All documents were redownloaded from the "Documents" zone. This means the zone still existed with all data accessible.
  • Also, the data was still there when I checked in the CloudKit Console (development and production environment)

I had a look at Delete a keychain in Keychain Access on Mac but I think it doesn't apply because "Delete Keychain iCloud…" is greyed out.

Thanks for sharing the details.

What did I try? I closed my app, cleared its caches and then ran "Reset Default Keychains…" in the Settings of the Keychain Access app to attempt resetting encrypted data. I relaunched my app

Did you try to restart your machine before relaunching your app to see if that changes anything?

I had a look at Delete a keychain in Keychain Access on Mac but I think it doesn't apply because "Delete Keychain iCloud…" is greyed out.

Indeed. Since you have the testing environment, would you mind to try the following?

  1. Launch Settings, go to Settings > Your Apple ID > iCloud > Passwords (Under the Saved to iCloud section), and uncheck the Sync this Mac box. (If you are on a system earlier than macOS 15, the setting may be in a different place.)

  2. Launch Keychain Access.app (or relaunch if you've launched it) and observe that the iCloud keychain (under the Default Keychains section) disappears. You can then quit Keychain Access.app.

  3. Find the login keychain file (~/Library/Keychains/login.keychain-db) and remove it. Be sure that the file is deleted, rather than being moved to the trash bin.

  4. Restart your Mac and try your app to see if there is any difference.

I can't try step 3 on my machine, and so need to rely on you to see what happens. Sorry for that.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Given your questions and suggestions I tried the following steps now

  • Launch Setting’s and go to Settings -> Apple Account -> iCloud -> See All -> iCloud Passwords & Keychain
  • Click the “Sync this Mac” toggle to disable it
  • Actual result: Nothing happens, the toggle remains active
  • Log out the mac user and log back in in the toggle has actually been updated to look disabled
  • The iCloud Keychain is now gone from the Keychain Access app.
  • ❎ The CloudKit app data is still available (All documents were redownloaded from the "Documents" zone. This means the zone still existed with all data accessible.)
  • Fully delete the login keychain at ~/Library/Keychains/login.keychain-db
  • Restart the mac
  • ❎ The CloudKit app data is still available
  • Reactivate Settings / iCloud Passwords & Keychain / “Sync this Mac”
  • The iCloud Keychain is back to the Keychain Access app
  • Keychain App -> Settings -> Reset Default Keychains…
  • Restart the Mac
  • A system alert shows “This Mac can’t connect to iCloud because of a problem with “<email>”, Open Apple Account settings to fix this problem.
  • App shows iCloud as temporarily unavailable and can’t sync
  • Settings app asks for Apple Account password, I enter it
  • App syncs again
  • ❎ The CloudKit app data is still available

It seems that none of these steps reset the key(s) used for encrypting data in CloudKit.

Do you have any other ideas or could you perhaps reach out to find an answer to the question of how the user keychain reset can be triggered?

The iCloud Keychain is now gone from the Keychain Access app. ❎ The CloudKit app data is still available (All documents were redownloaded from the "Documents" zone. This means the zone still existed with all data accessible.) Fully delete the login keychain at ~/Library/Keychains/login.keychain-db Restart the mac ❎ The CloudKit app data is still available

Thanks for your experiments. Given that the iCloud and login keychains are both gone, the above result is a surprise to me...

I'd see if my colleague who focuses on keychain has something to say. At the same time, if you don't mind, please file a feedback report with all the information here and share the report ID, which I would use for our internal communication.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Thanks for reaching out to your colleague(s). Here is the report ID: FB16366133

My CloudKit friend reminded me the following:

  • You need to turn on iCloud Advanced Data Protection (Settings > Apple ID > iCloud > Advanced Data Protection) for the testing. With ADP being on, a deleted key is un-recoverable, and triggers the zone deletion on the server side.

  • The zone deletion is asynchronous, and so it may take some time after ADP is on and the keychain is reset.

So would you mind to check if ADP is on on your testing device, and if it is off, turn it on and try with another test?

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

I've tested with ADP on, and it didn't change the result. The Zone is still available. Could it have anything to do with the zone being a custom zone, and also having at least one record which is using CKShare with hierarchical sharing?

I don't believe so. Did you ever test with the default zone in your private database? I think that will give you the same result.

I still have the feeling though, that just clearing the keychain using Keychain Access app don't really reset the CloudKit encryption key.

I have actually checked with my keychain and security friend and he didn't see anything wrong from the keychain side.

I guess I'll need to set up and test with my own environment before I can say more. Since you've filed the feedback report, I guess you can update it with the result of your latest try, and see if the CloudKit team has any comment.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

How can I test CloudKit User Keychain Reset?
 
 
Q