很多 V 站网友应该都知道,有些 iOS APP 会通过在 iOS 的 keychain 里留下隐藏记录的方式来锁定和追踪用户身份。 典型的比如 uber ,如果只是删除 APP 再安装,即使换一个 ID 登录,uber 还是可以通过 keychain 记录的方式把用户的不同 ID 关联起来。 我一直不清楚这种情况下,app 的隐藏记录会不会通过 keychain 同步的方式跑到同一个 apple id 的其它登录设备上。
然后前一阵打算把一个长期怎么用的 apple ID 登入到一台闲置的 mac 的某个账户上,结果在登录 icloud 时,要求我输入这个 apple id 之前登录并开启过 keychain 同步的 ipad 的锁屏 code 。这是 icloud 登录过程中验证 keychain 同步的一个步骤。ok 这没有问题,结果我输入 ok 以后,它又继续要我输入这个 apple id 之前登录过的一台更旧的 MAC 上的账户密码,这个我就完全想不起来了。结果输入不正确,它就不让我整个 icloud 登录过程完成。我完全没办法绕过,而且即使 icloud 登录完成,我也没打算开启 keychain 同步,它竟然也没办法让我在登录前就选择不同步 keychain 。 结果就因为多个旧设备其中一个设备的 passcode 想不起来导致 apple id 的登录无法完成。
假设有已经登入同一 apple id 并开启 icloud keychain sync 的旧设备 B 和 C ,以及准备新登入此 apple id 并开启 icloud keychain sync 的新设备 A
以下情形里,背后实际发生的流程是否如我理解?
官方原始文档(中文) https://support.apple.com/zh-cn/guide/security/sec0a319b35f/web
(一) 按文档: “钥匙串安全同步 当用户首次启用 iCloud 钥匙串时,设备将建立信任圈并为自己创建同步身份。同步身份包括私钥和公钥,且储存在设备的钥匙串中。同步身份的公钥放置在信任圈中,该信任圈已签名两次:第一次由同步身份的私钥签署,第⼆次由来自用户 iCloud 帐户密码的非对称椭圆密钥(使用 P-256 )签署。随信任圈一起储存的还有参数(随机盐和迭代次数),用于创建基于用户 iCloud 密码的密钥。 对于双重认证的帐户,还会额外创建一个相似的同步信任圈并存储在 CloudKit 中。此系统中的设备身份由两对非对称椭圆密钥(使用 P-384 )组成,且储存在钥匙串中。每台设备均维护本机信任的身份列表,且使用其中一个身份密钥为此列表签名。”
我理解是: 1.也就是说在 icloud 里同步的信任圈(syncing circle)包括多台设备的同步身份(syncing identity)的公钥,是一个全体设备的同步身份(syncing identity)公钥的集合。当某个设备(假如是 C )关闭 keychain sync 后,这设备(这里是 C )的同步身份( syncing identity )是不是就是会退出信任圈了。 2.双重认证的账户,额外存一个同步信任圈在 CloudKit ,而代表设备身份的两对密钥存在钥匙串中,每个设备都有存在本机的信任设备身份列表,这个列表应该是选择钥匙串中有列的全部或部分设备身份密钥,组成一个 lists 。也就是每台设备都选择在钥匙串中登记过的设备身份清单,组成本机信任的 lists,并用本设备的一个身份密钥为此 Lists 列表签名,确保是认证不可篡改的本机信任 lists 。
(二) “iCloud 储存同步信任圈 已签名的同步信任圈储存在用户的 iCloud 键值存储区域。如果不知道用户的 iCloud 密码,就无法对其进行读取;如果没有信任圈成员同步身份的私钥,就无法对其进行有效地修改。 对于双重认证的帐户,每台设备的同步列表会存储在 CloudKit 中。如果不知道用户的 iCloud 密码,就无法读取列表;如果没有已拥有设备的私钥,就无法修改私钥。” "For two-factor authentication accounts, each device’s syncing list is stored in CloudKit. The lists can’t be read without knowing the user’s iCloud password, and they can’t be modified without having the private keys of the owning device."
我理解是: 中文翻译有误,应该是说:对于双重认证的帐户,没有对应已拥有的设备(如旧设备 B,C)的私钥,就无法修改对应的 lists(大概是通过签名验证有效性的验证方式来限制生效)。我理解大概的过程是读取每个旧设备对应的 syncing lists,比如 B 设备的 lists ,然后想把新设备 A 加入这个 lists ,以后就能和 B 点对点 sync 了。这样就需要调用 B 设备对应的私钥给加了 A 的新 lists 签名,才会真正有效并被 B 设备接纳。
(三) 按文档: “用户的其他设备如何添加到同步信任圈 新设备登录 iCloud 时,可通过这两种方式之一加入 iCloud 钥匙串同步信任圈:与现有的 iCloud 钥匙串设备配对并获得其担保,或者使用 iCloud 钥匙串恢复。
在配对流程中,申请设备为同步信任圈和同步列表(针对双重认证帐户)新建同步身份,并将其出示给担保设备。担保设备将新成员的公钥添加至同步信任圈,并且使用其同步身份和派生自用户 iCloud 密码的密钥再次签名。新的同步信任圈放置在 iCloud 中,该信任圈的新成员也是在此处对其进行签名。在双重认证帐户中,担保设备还为加入设备提供使用其身份密钥签名的凭证,表明申请设备应被信任。然后,它会更新其受信任同步身份的单独列表,以包括申请设备。
现在,签名信任圈有两个成员,并且每个成员拥有另一个成员的公钥。它们现在开始通过 iCloud 键值存储交换各个钥匙串项或将其储存在 CloudKit 中,视情境而定。如果两个信任圈成员都更新了相同的项目,其中一个会被选中,最终获得一致的结果。每个同步的项目都会加密,使只有用户信任圈内的设备才能解密,任何其他设备或 Apple 都无法解密。
新设备加入同步信任圈时会重复此“加入流程”。例如,第三台设备加入时,可与其中任一台现有设备进行配对。随着新的同级设备加入,每台同级设备均与新设备进行同步。此设计旨在确保所有成员拥有相同的钥匙串项。”
我理解是: 意思就是新加入的设备 A 想要把自己的同步身份的公钥加入 icloud 里同步的信任圈(syncing circle)中,那么: 1.A 设备把自己的同步身份加入 icloud keychain 里的信任圈(syncing circle),然后让所有的旧设备用自己的同步身份( syncing identity )的私钥签名以使之生效。比如针对 B 设备的,新设备 A 需要 B 调用 B 自己的同步身份的私钥对修改后的包含 A 的新信任圈(syncing circle)去签名,以使之生效。同理对于 C 设备也是这么个过程,因此过程中可能会调动每个旧设备的登入密码以启用私钥签名的动作。 也即是说,新设备要加入 icloud 里同步的信任圈(syncing circle)。新设备 A 需要一个旧成员,比如设备 B ,调用 B 自己的同步身份的私钥,对添加了 A 设备同步身份(syncing identity)公钥后的新信任圈(syncing circle)去签名,以使之生效。是否仅需要一个旧成员签名即可,还是需要全体旧成员都签名。签名的过程,是否需要输入旧设备的 passcode ,比如 B 设备的密码,才能调用相应设备的私钥做签名动作。
2.双重认证帐户时除了把把自己 A 设备身份的密钥存到 icloud 钥匙串的同步信任圈,还要让其它设备 B,C 都把 A 的设备身份加入到 B,C 设备的本机信任 list 里,并让 B,C 设备各自用自己的设备身份密钥给这个新加入了 A 设备的 list 签名认证。这样的话就必须要调用每一个加入过 keychain 的设备( B 和 C )的密钥来让它们各自给加入 A 设备的新 list 签名,也就需要输入 B 和 C 设备的登入密码来解锁和启用签名流程。
3.这里讨论的流程没有包括“iCloud 钥匙串恢复”的流程,仅是讨论新旧设备配对的问题,核心就是是否需要每一台旧设备的配对(授权),还是仅需要其中一台的。
这里有一个疑问,实际情况好像是第三台设备 A 加入时,必须与每一台旧设备(B 和 C)都配对(输入设备登入密码),而不是只与其中任一台( B 或者 C )配对就可。如果没有配对完成,新设备上的 apple id 登录流程都无法正常走完。
(四) 按文档: “仅同步部分项目 部分钥匙串项特定于设备,如 iMessage 信息密钥,因而必须保留在设备上。因此,每个将要同步的项目都必须使用 kSecAttrSynchronizable 属性明确标记。
Apple 为 Safari 浏览器用户数据(包括用户名、密码和信用卡号)、无线局域网密码、HomeKit 加密密钥以及其他支持端对端 iCloud 加密的钥匙串项设置了该属性。
另外,在默认情况下,第三方 App 添加的钥匙串项不会进行同步。将项目添加至钥匙串时,开发者必须设置 kSecAttrSynchronizable 属性。”
我理解是: 不知道 reset keychain 能不能清除这些第三方存在钥匙串里的内容。设置 kSecAttrSynchronizable 属性并能被 keychain 同步的第三方 APP 的数据项,是否能在 keychain 里被观察到。 又或者它们除了能在设备本地 keychain 不可见的情况下,在网络同步的 keychain 里也不可见。但即使在网络同步的 keychain 里也不可见,应该也能被 reset keychain 的操作给清除?
哦,对了,还有一种特殊情况:如果 icloud 存储空间已满,新增的 keychain 项目是不是就不会同步到 icloud 上了?