在 Android 上导入 VPN 客户端证书只需几分钟。要确认它落在正确的位置则要花更长时间,而这正是大多数人在安装对话框提示成功之后就跳过的部分。成功提示只说明文件被解析了。它完全没有说明哪个提供方持有私钥,也没有说明 Downloads 文件夹里是否还留着一份副本。

第 1 步:在 P12 离开你的机器之前先读它

从文件本身开始。如果你说不出里面的主体、签发者和到期日期,那你导入的东西日后将无法验证。

PKCS#12 包通常包含一张客户端证书、它的私钥以及签发者链。openssl pkcs12 -in client.p12 -info -noout 会打印 MAC 和加密算法而不导出密钥材料,因此你能看出该包是否受密码保护、用的是哪种密码。接着运行 keytool -list -v -keystore client.p12 -storetype PKCS12 获取别名、SHA-256 指纹以及你要与手机比对的生效窗口。

用与文件不同的渠道发送密码,或者在不会留下副本的受管分发流程中交付文件。把密码粘贴在与压缩包同一条聊天消息里,就把两道控制变成了一道。

第 2 步:把它装进 VPN 应用真正读取的那个槽位

在原生 Android 11 到 14 上,路径是设置、安全、加密与凭据、安装证书,然后是 VPN 与应用用户证书。措辞和嵌套层级会随版本与厂商皮肤而变化,所以要跟随凭据类型的标签,而不是记住的菜单位置。在工作资料中,要从工作侧内部安装,因为凭据不会跨越资料边界。

不要把客户端身份放进 CA 证书槽位。那个槽位供给的是用户信任库,而自 Android 7 起,除非网络安全性配置明确允许,应用会忽略用户添加的 CA,因此放在那里的客户端证书永远不会出现在 VPN 的密钥选择器里。

有些 VPN 客户端根本不碰系统库,而是把 P12 导入自己的应用目录。这是合法设计,但它改变了之后每一步:密钥现在住在应用的沙箱里,强度完全取决于该应用如何管理自己的存储。在假定 KeyChain 参与之前,先查客户端文档。

第 3 步:证明哪个提供方持有密钥

导入确认的是解析,而不是硬件支撑。在 Android 12 及更高版本上,KeyInfo.getSecurityLevel() 会报告密钥位于可信执行环境、StrongBox 还是软件中,它取代了更早的 isInsideSecureHardware() 调用。如果 VPN 客户端不显示该值,第 1 步的指纹就是你的退路。导入期间被重新编码的证书不会逐字节一致,但公钥和主体仍然一致。

不可导出不等于不可用。无法离开设备的密钥仍可被任何获用户授权选择该别名的应用使用,这就是别名提示是真正的控制而非形式的原因。Android Keystore 文档值得读一遍,如果你要做那个设计决定。

然后算一下你做过的副本。笔记本上的 P12、工单附件里的那份、上个月备份里的那份,在签发者吊销它们之前都仍是有效身份。手机实例的硬件保护对它们毫无帮助。

第 4 步:弄清楚屏幕锁要求到底归谁

这里有三个秘密被混在一起:设备解锁 PIN、私钥口令和 VPN 账户密码。针对其中一个的提示从来不是要求重置另外两个,而重置错的那个正是人们把自己锁在一个本来运行良好的资料之外的原因。

当设备管理员或受管资料策略要求锁屏时,这项要求属于该策略,而不属于证书。adb shell dumpsys device_policy 会列出活动的管理员以及他们强制的密码质量,这是判断 MDM 代理是否为你 PIN 规则改变之原因的最快方式。删除证书不会放宽策略,而删除策略是管理决定,不是设置微调。

也要预期可用性上的取舍。如果密钥要求用户授权,隧道在首次解锁之前无法建立,因此定时同步和远程唤醒按设计就会失败。要在部署之前决定这一点,而不是之后。

不要走捷径去编辑 locksettings.db,也不要重放过时的忘记图案绕行方案。那些流程是为特定构建写的,它们可能把凭据存储留在框架不再预期的状态,而且它们从来不会改变当初要求锁屏的那条策略。

第 5 步:停用身份并验证拒绝

停用有三部分,只有第一部分是本地操作。删除 VPN 配置,在设置、安全、加密与凭据、用户凭据下删除用户证书,然后让签发者吊销证书序列号。仅本地删除会留下一份凭据,只要有人留着 P12,服务器就仍然接受它。

去验证结果而不是假定。用已停用的配置尝试连接,并确认服务器拒绝它。隧道仍然建立,意味着你吊销了错误的序列号,或者客户端悄悄退回到了另一个已安装的身份。

如果你在回滚一次失败的导入,请从原始加密包重新导入并再次核对指纹,而不是复用你留在磁盘上的已解密密钥文件。

相关文章