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

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

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

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

我的下一个尝试是通过复制它并使用设置菜单中的相应选项从SD卡安装证书。 该设备告诉我,证书已经安装,但显然它不相信证书。 而且,当我试图将密钥库复制到我的电脑时,我仍然可以find原始的cacerts.bks

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

从Android 4.0开始,这是现在可能的。 我很容易地在我的根目录设备上安装Charles Web Debbuging Proxy cert,并成功地嗅探SSLstream量。

摘自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 /安全/'作为单个文件。 但是,用户现在可以轻松地添加自己的“用户”证书,这些证书将存储在“/ data / misc / keychain / certs-added”中。

系统安装的证书可以在Android设备的“设置” – >“安全” – >“证书” – >“系统”部分进行pipe理,而用户可信证书则在“用户”部分进行pipe理。 使用用户信任的证书时,Android会强制Android设备的用户采取额外的安全措施:使用用户提供的证书时,必须使用PIN码,模式locking或密码解锁设备。

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

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

详细信息和链接: http : //www.mcbsys.com/techblog/2010/12/android-certificates/ 。 在那篇文章中,看到Android bug 11231的链接 – 你可能想要添加你的投票和查询到那个bug。

如果需要用于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); } } } 

这里链接的指南可能会回答原来的问题,而不需要编写一个自定义的SSL连接器。

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

基本上你需要:

  1. 从手机上下载cacerts.bks文件。

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

  2. 从您想要允许的authentication机构下载.crt文件。

  3. 使用BouncyCastle提供程序修改您的计算机上的cacerts.bks文件

  4. 将cacerts.bksfile upload回您的手机并重启。

下面是一个更详细的步骤来更新更早的Android手机: 如何更新HTTPS安全证书授权密钥存储在Android 4.0前设备

我所做的努力使用startssl证书是相当容易的。 (在我的手机上)

我复制/system/etc/security/cacerts.bks到我的SD卡

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

去portecle.sourceforge.net并直接从网页上运行portecle。

从我的SD卡打开我的cacerts.bks文件(当input密码时不input)

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

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

重新启动我的手机,现在我可以使用startssl证书无误地访问我的网站。

这里有一个比这里发布的更容易的解决scheme,或在相关的线程。 如果你正在使用webview(就像我),你可以通过在其中执行一个JAVASCRIPT函数来实现。 如果你不使用webview,你可能想为此创build一个隐藏的。 这里有一个函数可以在几乎任何浏览器(或webview)中启动ca安装(通常通过共享的os证书库,包括Droid)。 它与iFrames使用一个很好的技巧。 只需将URL传递给.crt文件即可:

 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将无法如此工作。 一般的想法仍然有效,但只需下载/打开与web视图的文件,然后让os接pipe。 这可能是一个更容易和更通用的解决scheme(现在在实际的Java中):

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

请注意,instance_是对Activity的引用。 如果您知道证书的URL,这完美的工作。 但是,在我的情况下,我用服务器端软件dynamic地解决这个问题。 我不得不添加一些额外的代码来拦截一个redirecturl,并以一种不会导致基于线程复杂化的崩溃的方式调用它,但是我不会在这里添加所有这些混淆。

以下是实际将您的证书添加到默authentication书列表中的备用解决scheme: 通过HTTPS使用HttpClient信任所有证书

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