如何在 Android 设备上安装受信任的 CA 证书?

Posted

技术标签:

【中文标题】如何在 Android 设备上安装受信任的 CA 证书?【英文标题】:How to install trusted CA certificate on Android device? 【发布时间】:2011-05-26 13:42:24 【问题描述】:

我已经创建了自己的 CA 证书,现在我想将它安装在我的 android Froyo 设备 (HTC Desire Z) 上,以便设备信任我的证书。

Android 将 CA 证书存储在其 Java 密钥库中的 /system/etc/security/cacerts.bks 中。我将文件复制到我的计算机,使用portecle 1.5 添加我的证书并将其推回设备。

现在,Android 似乎不会自动重新加载文件。我已经阅读了几篇我需要重新启动设备的博客文章。这样做会导致文件再次被原始文件覆盖。

我的下一个尝试是通过复制 SD 卡并使用设置菜单中的相应选项来安装证书。该设备告诉我证书已安装,但显然它不信任该证书。而且,当我尝试将密钥库复制到我的计算机时,我仍然找到原始库存cacerts.bks

那么,在 Android 2.2 设备上安装我自己的根 CA 证书作为可信证书的正确方法是什么?有没有办法以编程方式做到这一点?

【问题讨论】:

你可以在这里假设一个有根电话。 :) 【参考方案1】:

在 Android KitKat 之前,您必须 root 设备才能安装新证书。

从 Android KitKat (4.0) 到 Marshmallow (6.0),一切皆有可能且简单。我能够在我的无根设备上安装 Charles Web 调试代理证书并成功嗅探 SSL 流量。

从http://wiki.cacert.org/FAQ/ImportRootCert提取

在 Android 版本 4.0 之前,使用 Android 版本 Gingerbread & Froyo,只有一个只读文件 ( /system/etc/security/cacerts.bks ) 包含所有 CA(“系统”)证书受信任的信任库默认情况下在 Android 上。系统应用程序和使用 Android SDK 开发的所有应用程序都使用它。使用这些说明在 Android Gingerbread、Froyo、...上安装 CAcert 证书...

从 Android 4.0(Android ICS/'Ice Cream Sandwich'、Android 4.3 'Jelly Bean' 和 Android 4.4 'KitKat')开始,系统可信证书位于文件夹 '/system 中的(只读)系统分区上/etc/security/' 作为单独的文件。但是,用户现在可以轻松添加自己的“用户”证书,这些证书将存储在“/data/misc/keychain/certs-added”中。

系统安装的证书可以在 Android 设备的“设置”->“安全”->“证书”->“系统”部分进行管理,而用户信任的证书则在“用户”部分进行管理。使用用户信任证书时,Android 将强制 Android 设备的用户实施额外的安全措施:使用用户提供的证书时,必须使用 PIN 码、图案锁或密码来解锁设备。

将 CAcert 证书安装为“用户信任”证书非常简单。将新证书安装为“系统受信任”证书需要更多工作(并且需要 root 访问权限),但它的优点是可以避免 Android 锁屏要求。

从 Android N (7.0) 开始变得更难了,请参阅Charles proxy website 的摘录:

从 Android N 开始,您需要向您的应用添加配置,以便 让它信任 Charles SSL Proxying 生成的 SSL 证书。 这意味着您只能将 SSL 代理与您的应用程序一起使用 控制。

为了将您的应用配置为信任 Charles,您需要添加一个 网络安全配置文件到您的应用程序。这个文件可以 覆盖系统默认值,使您的应用程序信任安装的用户 CA 证书(例如 Charles Root 证书)。您可以指定 这仅适用于您的应用程序的调试版本,因此 生产版本使用默认信任配置文件。

将文件 res/xml/network_security_config.xml 添加到您的应用中:

<network-security-config>    
    <debug-overrides> 
        <trust-anchors> 
            <!-- Trust user added CAs while debuggable only -->
            <certificates src="user" /> 
        </trust-anchors>    
    </debug-overrides>  
</network-security-config>

然后在你的应用清单中添加对这个文件的引用,如下:

<?xml version="1.0" encoding="utf-8"?> 
<manifest>
    <application android:networkSecurityConfig="@xml/network_security_config">
    </application> 
</manifest>

【讨论】:

我的自定义证书文件(/system/etc/security/cacerts/*.0)在重启/重启 AVD 后没有保留,所以这个解决方案没有成功。 @BornToCode 很有趣 - 我很少使用 AVD,所以我不知道这个限制 我看到设置debug-overrides,这是否意味着这个network_security_config 只针对调试变体?如果我有其他变体,例如 UAT 变体,那么这将不起作用? @Isaac 这意味着它将适用于 debuggable=true 的任何变体 @DeanWild - 非常感谢!我试图让它永远工作,并在调试我的应用程序时不断收到“无效的 ssl 证书”。对于我在三星 Note 8 上的 Android 9 上运行的 Android 应用来说,这个解决方案非常有效。【参考方案2】:

如果您有 root 设备,您可以使用 Magisk 模块将用户证书移动到系统,使其成为可信证书

https://github.com/Magisk-Modules-Repo/movecert

【讨论】:

你愿意多解释一下如何做吗?该网站本身没有关于安装和如何使用的说明。谢谢!顺便说一句,Magisk 模块现在位于github.com/Magisk-Modules-Repo/movecert 你需要有一个root设备并安装了Magisk,然后打开Magisk点击底部导航图标右边第一个图标的模块图标,然后搜索移动证书,点击安装>>重启【参考方案3】:

您是否尝试过:设置 -> 安全 -> 从 SD 卡安装? – 亚历山大·艾格 2010 年 12 月 20 日 20:11

我不确定为什么这不是一个答案,但我只是遵循了这个建议并且它奏效了。

【讨论】:

【参考方案4】:

这些步骤对我有用:

    在您的移动设备上安装 Dory Certificate Android 应用程序:https://play.google.com/store/apps/details?id=io.tempage.dorycert&hl=en_US 使用 USB 数据线将移动设备连接到笔记本电脑。 在手机内部存储器上创建根文件夹,复制该文件夹中的证书文件并断开电缆。 打开 Dory Certificate Android 应用,点击圆形 [+] 按钮并选择右侧的 Import File Certificate 选项。 选择格式,提供名称(我键入与文件名相同),浏览证书文件并单击[确定]。 将列出三张卡片。我忽略了只有 [SIGN CSR] 按钮的卡片,然后继续点击另外两张卡片上的 [INSTALL] 按钮。 我刷新了 PWA Web 应用程序,我没有打开我的移动 Chrome(它托管在本地 IIS Web 服务器上),瞧!没有铬警告消息。绿色的锁在那里。它工作正常。

另外,我发现这些选项我不需要自己尝试,但看起来很容易理解:

苹果设备:http://help.netmotionsoftware.com/support/docs/mobilityxg/1100/help/mobilityhelp.htm#page/Mobility%2520Server%2Fconfig.05.083.html%23 安卓设备:http://help.netmotionsoftware.com/support/docs/mobilityxg/1100/help/mobilityhelp.htm#page/Mobility%20Server/config.05.084.html

最后,它可能不相关,但是,如果您希望为托管在本地 IIS Web 服务器上的 PWA 应用程序(网站)创建和设置自签名证书(使用 mkcert),我关注了这个页面:

https://medium.com/@aweber01/locally-trusted-development-certificates-with-mkcert-and-iis-e09410d92031

谢谢,希望对你有帮助!! :)

【讨论】:

【参考方案5】:

有一个比此处或相关线程中发布的更简单的解决方案。如果您使用的是 webview(就像我一样),您可以通过在其中执行 javascript 函数来实现这一点。如果您不使用 web 视图,您可能需要为此创建一个隐藏的视图。这是一个几乎可以在任何浏览器(或 web 视图)中运行以启动 ca 安装的功能(通常通过共享的 os 证书存储库,包括在 Droid 上)。它对 iFrame 使用了一个很好的技巧。只需将 .crt 文件的 url 传递给此函数:

function installTrustedRootCert( rootCertUrl )
    id = "rootCertInstaller";
    iframe = document.getElementById( id );
    if( iframe != null ) document.body.removeChild( iframe );
    iframe = document.createElement( "iframe" );
    iframe.id = id;
    iframe.style.display = "none";
    document.body.appendChild( iframe );
    iframe.src = rootCertUrl;

更新:

iframe 技巧适用于 API 19 及更高版本的 Droid,但旧版本的 webview 不会像这样工作。不过,一般的想法仍然有效 - 只需使用 webview 下载/打开文件,然后让操作系统接管。这可能是一个更简单、更通用的解决方案(现在在实际的 java 中):

 public static void installTrustedRootCert( final String certAddress )
     WebView certWebView = new WebView( instance_ );
     certWebView.loadUrl( certAddress );
 

注意 instance_ 是对 Activity 的引用。如果您知道证书的 url,这将非常有效。但是,就我而言,我使用服务器端软件动态解决了这个问题。我不得不添加相当多的额外代码来拦截重定向 url,并以不会导致基于线程复杂化的崩溃的方式调用它,但我不会在这里添加所有这些混淆......

【讨论】:

【参考方案6】:

链接here 的指南可能会回答原始问题,而无需编写自定义 SSL 连接器。

找到了关于导入根证书的非常详细的操作指南,该指南实际上指导您在不同版本的 Android 设备(以及其他设备)上安装受信任的 CA 证书。

基本上你需要:

    下载:手机中的 cacerts.bks 文件。

    adb pull /system/etc/security/cacerts.bks cacerts.bks

    从您要允许的认证机构下载 .crt 文件。

    使用BouncyCastle Provider修改您计算机上的 cacerts.bks 文件

    将 cacerts.bks 文件上传回您的手机并重新启动。

这里是更详细的一步一步更新早期的安卓手机: How to update HTTPS security certificate authority keystore on pre-android-4.0 device

【讨论】:

【参考方案7】:

如果您需要用于 HTTPS 连接的证书,您可以将 .bks 文件作为原始资源添加到您的应用程序并扩展 DefaultHttpConnection,以便您的证书用于 HTTPS 连接。

public class MyHttpClient extends DefaultHttpClient 

    private Resources _resources;

    public MyHttpClient(Resources resources) 
        _resources = resources;
    

    @Override
    protected ClientConnectionManager createClientConnectionManager() 
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory
            .getSocketFactory(), 80));
        if (_resources != null) 
            registry.register(new Scheme("https", newSslSocketFactory(), 443));
         else 
            registry.register(new Scheme("https", SSLSocketFactory
                .getSocketFactory(), 443));
        
        return new SingleClientConnManager(getParams(), registry);
    

    private SSLSocketFactory newSslSocketFactory() 
        try 
            KeyStore trusted = KeyStore.getInstance("BKS");
            InputStream in = _resources.openRawResource(R.raw.mystore);
            try 
                trusted.load(in, "pwd".toCharArray());
             finally 
                in.close();
            
            return new SSLSocketFactory(trusted);
         catch (Exception e) 
            throw new AssertionError(e);
        
    

【讨论】:

感谢您的回复。实际上,我需要以某种方式安装证书,以使设备上的每个应用程序都信任该证书。同样的问题也应该存在于一些较小的 CA,如 CAcert,其证书默认不受信任。他们如何安装证书? 您尝试了吗:设置 -> 安全 -> 从 SD 卡安装 这可能也很有趣:android.git.kernel.org/?p=platform/packages/apps/… 我有同样的问题,我必须使用 Adroid 2.3.3 应用程序加载 .PDX X509 证书,然后创建 SSL 连接。任何人都可以帮我注释代码吗?【参考方案8】:

我为能够使用startssl 证书所做的工作非常简单。 (在我的手机上)

我将 /system/etc/security/cacerts.bks 复制到我的 sdcard 中

下载http://www.startssl.com/certs/ca.crt和http://www.startssl.com/certs/sub.class1.server.ca.crt

访问 portecle.sourceforge.net 并直接从网页运行 portecle。

从我的 sdcard 中打开了我的 cacerts.bks 文件(要求输入密码时没有输入任何内容)

在portacle中选择导入并打开sub.class1.server.ca.crt,我的情况是它已经有了ca.crt,但也许你也需要安装它。

保存密钥库并将其复制到 /system/etc/security/cacerts.bks(我先备份了该文件以防万一)

重新启动我的手机,现在我可以访问我的网站了

【讨论】:

来自 Mozilla 的新用户:Distrusting New WoSign and StartCom Certificates。 知道如何将 cacert.bks 放回非根设备上吗?【参考方案9】:

这是一个替代解决方案,它实际上将您的证书添加到默认证书的内置列表中:Trusting all certificates using HttpClient over HTTPS

但是,它仅适用于您的应用程序。无法以编程方式为用户设备上的所有应用程序执行此操作,因为这会带来安全风险。

【讨论】:

【参考方案10】:

我花了很多时间试图找到答案(我需要 Android 才能查看 StartSSL 证书)。结论:Android 2.1 和 2.2 允许您导入证书,但只能用于 WiFi 和 ***。没有用于更新受信任根证书列表的用户界面,但有关于添加该功能的讨论。目前尚不清楚是否有可靠的解决方法来手动更新和替换 cacerts.bks 文件。

详细信息和链接:http://www.mcbsys.com/techblog/2010/12/android-certificates/。在该帖子中,请参阅 Android 错误 11231 的链接——您可能希望对该错误添加您的投票和查询。

【讨论】:

一位 Android 开发人员回答了我的问题。更新 cacerts.bks:“在 2.3 之前的所有版本中,都需要 OTA 来更新非 root 手机上的 cacerts.bks。” code.google.com/p/android/issues/detail?id=11231#c25。 OTA = 无线,对吧?这可能是您的手机不断恢复到出厂 cacerts.bks 的原因吗?但是,如果您确实具有 root 访问权限,那么您似乎应该能够下载源代码,添加您的证书,然后使用 certimport.sh 脚本构建 cacerts.bks。 android.git.kernel.org/?p=platform/libcore.git;a=tree;f=luni/…. 谢谢。这显然不是我想听到的答案,但似乎是正确的答案。我希望有一种方法可以在不更新整个系统的情况下安装证书。我当然可以构建新的 cacerts.bks,使用 root 访问权限我什至可以替换旧的,但每次重新启动时它都会恢复到原始版本。如果不重新启动,Android 似乎拒绝重新加载受信任的证书文件。 在 3.X 和 4.X 平台上安装 CA 证书怎么样? 4.X 以上:***.com/questions/4461360/…

以上是关于如何在 Android 设备上安装受信任的 CA 证书?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Android设备上安装可信CA证书?

如果您的CA不受系统信任,如何将Android应用程序连接到SSL服务器?

iOS MDM 服务器 SSL 证书不受设备信任

如何在卸载应用程序时删除应用程序安装的受信任 CA 证书

如何在 Android 上使用 OWASP ZAP 进行 MiTM 攻击?

android手机如何导入CA证书