myx509trustmanagerimpl需要哪个jia包

Android 证书锁 - 简书
Android 证书锁
在讲解本篇文章之前可以先简单了解一下关于、和的基础知识
为什么需要数字证书锁
在Android设备中,一般由系统校验服务端数字证书的合法性,用可信CA签发的数字证书的网站才可以正常访问,私有签发的数字证书的网站无法访问(需要手动安装证书并信任)。这种作法不能抵御在用户设备上安装证书(将中间人服务器的证书放到设备的信任列表中,如charles的对https抓包的做法)进行中间人攻击。如果客户端没有做任何主动性的防御,很可能被不法分子利用伪造CA证书进行中间人攻击。受信任的CA(证书颁发机构)有好几百个,任何一家受信任的CA都可以签发任意网站的证书,这些证书在客户端看来都是合法的。如果客户端使用证书锁,它会强制校验服务端的证书,一旦发现不匹配就会禁止通信。
android证书锁的用法
1、Certificate Pinning其实Certificate Pinning是OkHttp 实现的一个类似于的技术,目的是为了使客户端可以有主动的信任CA的权利,它的工作原理就是使用预先设置的证书指纹和服务器传过来的证书链中的证书指纹进行匹配,只要有任何一对指纹匹配成功,则认为是一次合法的连接,否则禁止本次链接
2、预埋证书把数字证书以文件或者字符串的形式写在本地,在SSL握手的时候用本地预埋的证书和服务器传过来的证书进行匹配,如果匹配不成功则禁止本次通信
Certificate Pinning和预埋证书做法的比较
先贴上代码 以OkHttp为例 预埋证书的写法首先定义一个类实现类实现X509TrustManager接口,实现对客户端证书链的校验方法和服务端的校验方法,不写的话表示不做任何校验,默认信任所有证书链中的证书
证书信任管理器
读取客户端预埋的证书
预埋的证书
配置Client
new OkHttpClient.Builder()
.sslSocketFactory(getSSLFactory(),new MyX509TrustManager)
Certificate Pinning的写法
妥妥的几行代码搞定
new OkHttpClient.Builder()
.certificatePinner(new CertificatePinner.Builder()
.add("", "sha256/**********")
.add("", "sha256/**********")
.add("", "sha256/**********")
两种做法相比较之下,Certificate Pinning更为简洁,并且也把指纹和hostname 绑定起来,这样做的好处就是对指定的hostname所在服务器发送过来的证书指纹进行校验,在一定程度上既控制了证书信任同时也考虑到了灵活性。而预埋证书的做法要实现相同的功能,仅仅实现上述代码还不够,还需要在Client配置的时候加上hostnameVerifier校验。
完整代码的实现
String hostname = "";
String pinner = "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostname,pinner)
OkHttpClient client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
Request request = new Request.Builder()
.url("https://" + hostname)
client.newCall(request).execute();
pinner就是证书指纹,sha256表示的是哈希值得一种算法,pinner也可以是 sha1/* ,具体pinner要根据购买证书所支持的配置,这个服务通过hostname可以查看的证书指纹。在SSL握手的时候,会检查配置中的指纹和服务端传过来的证书证的指纹是否相匹配,只要有一个指纹匹配,则进行下一步,否则直接抛出异常,禁止本次连接。相关源代码实现如下:
public void check(String hostname, List&Certificate& peerCertificates)
throws SSLPeerUnverifiedException {
List&Pin& pins = findMatchingPins(hostname);
if (pins.isEmpty())
if (certificateChainCleaner != null) {
peerCertificates = certificateChainCleaner.clean(peerCertificates, hostname);
for (int c = 0, certsSize = peerCertificates.size(); c & certsS c++) {
X509Certificate x509Certificate = (X509Certificate) peerCertificates.get(c);
// Lazily compute the hashes for each certificate.
ByteString sha1 =
ByteString sha256 =
for (int p = 0, pinsSize = pins.size(); p & pinsS p++) {
Pin pin = pins.get(p);
if (pin.hashAlgorithm.equals("sha256/")) {
if (sha256 == null) sha256 = sha256(x509Certificate);
if (pin.hash.equals(sha256)) // Success!
} else if (pin.hashAlgorithm.equals("sha1/")) {
if (sha1 == null) sha1 = sha1(x509Certificate);
if (pin.hash.equals(sha1)) // Success!
throw new AssertionError();
OkHttpClient验证证书指纹,在CertificatePinner类中有该方法的作用是确认证书中至少有一个和绑定的指纹是否匹配;如果匹配则Okhttp认为TLS握手成功,如果不匹配则失败,并且抛出SSLPerrUnverifiedException异常。(如果没有证书绑定,则OKHttp认为TLS握手成功)。具体调用过程和实现细节可以查看OkHttp的RealConnection这个类。
关于中间人攻击
目前在网络通信中,中间人的存在是无法杜绝的,因为中间人利用的不是漏洞,而是利用网络协议本身的特性。只要是它又能里转发数据包,并且实现相应的网络协议,就可以接入到终端和服务器之间实现中间人攻击。在HTTPS网络中想做中间人攻击,必须要在握手之前接入到网络中,一旦HTTPS握手过程结束,之后传输的数据完全都是加密的,解密非常的困难。想要破解加密的数据最简单的方法就是知道浏览器和网站协商的那个密码是什么,但是密码还是在握手过程中被RSA,DSA这种非对称加密算法加密的,不知道私钥还没有办法解密,同时浏览器和网站之间到底使用什么加密算法来进行加密还是在握手之间协商的,而这些方法都是保存在发给浏览器的证书中,于是最简单的方法就是伪造一个证书,同时要实现TLS协议,在握手开始前进行中间人攻击。另外,HTTPS握手过程对密码协商的验证是很严格的,中间验证数据的环节一旦有异常,浏览器和网站都会中断连接,因此伪造SSL证书进行中间人攻击目前是对HTTPS网络最好攻击方式,但是伪造的证书无法经过浏览器的受信检查会给出提示。
中间人攻击图
更多关于各种中间人攻击的相关知识,我推荐这篇文章,里面有各种攻击手段和原理讲解()
学做一个会表达的程序员引用谷歌市场的帮助说明:/faqs/answer/6346016
本文面向的是发布的应用中
接口实施方式不安全的开发者。具体而言,该问题是指在与远程主机建立 HTTPS 连接时实施方式会忽略所有 SSL 证书验证错误,从而使您的应用容易受到中间人攻击。攻击者可能会读取传输的数据(例如登录凭据),甚至更改通过 HTTPS 连接传输的数据。要查看受影响应用的完整列表,请访问。
为了正确处理 SSL 证书验证,请更改您的自定义 X509TrustManager 接口的
方法中的代码,指定在服务器提供的证书不符合您的预期时生成
错误。如有技术问题,您可以在
上发帖咨询(使用&android-security&和&TrustManager&标签)。
请尽快解决此问题并增加升级版 APK 的版本号。从 2016 年 5 月 17 日起,Google Play 将禁止发布
接口实施方式不安全的任何新应用或应用更新。
要确认您所做的更改是否正确,请将更新后的应用版本提交至,并在 5 小时后回来查看。如果应用并未正确升级,系统将会显示警告。
尽管这些具体问题可能不会影响每个实施 TrustManager 接口的应用,但您最好不要忽略任何 SSL 证书验证错误。如果应用包含会让用户面临入侵风险的安全漏洞,那么我们可能会将其视为,因其违反了内容政策和开发者分发协议第
条的相关规定。
***********************************************************************************
全文搜索,结果发现在 proguard 文件夹下的 dump.txt 文件中出现了
_____________________________________________________________________
+ Program class: com/baidu/b/a/f
& Superclass:& & java/lang/Object
& Major version: 0x32
& Minor version: 0x0
& Access flags:& 0x20
& & = class com.baidu.b.a.f extends java.lang.Object
Interfaces (count = 1):
& + Class [javax/net/ssl/X509TrustManager]
Constant Pool (count = 34):
& + Class [com/baidu/b/a/d]
& + Class [com/baidu/b/a/d$b]
& + Class [com/baidu/b/a/f]
& + Class [java/lang/Object]
& + Class [java/security/cert/CertificateException]
& + Class [javax/net/ssl/X509TrustManager]
解决方法:更新百度地图的 Sdk
参考:/announcement/394
_____________________________________________________________________
+ Program class: com/loopj/android/http/MySSLSocketFactory$1
& Superclass:& & java/lang/Object
& Major version: 0x32
& Minor version: 0x0
& Access flags:& 0x20
& & = class com.loopj.android.http.MySSLSocketFactory$1 extends java.lang.Object
Interfaces (count = 1):
& + Class [javax/net/ssl/X509TrustManager]
Constant Pool (count = 41):
& + Class [com/loopj/android/http/MySSLSocketFactory]
& + Class [com/loopj/android/http/MySSLSocketFactory$1]
& + Class [java/lang/Object]
& + Class [java/security/cert/CertificateException]
& + Class [javax/net/ssl/X509TrustManager]
解决方法:
AsyncHttpClient
&3 新浪微博
public static class MySSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public MySSLSocketFactory(KeyStore truststore)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
chain[0].checkValidity();
} catch (Exception e) {
throw new CertificateException("Certificate not valid or trusted.");
public X509Certificate[] getAcceptedIssuers() {
return null;
sslContext.init(null, new TrustManager[] { tm }, null);
public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
checkServerTrusted 添加检查证书有效性(加粗部分)
阅读(...) 评论()开发更安全的安卓应用要注意哪些?
招聘信息:
本文由&&-&&翻译,&校稿。英文出处:。
安卓应用常被用于处理非常敏感的数据。开发者有责任确保用户提供的信息不被居心不良者轻易截取。开放式&Web&应用安全项目(OWASP)[9,10]尝试着列举移动应用潜在的安全问题。
其中一些是系统架构师的责任(例如弱服务器端控制有关的问题),一些是后端开发者的责任(授权检查相关问题),最后一些就是纯粹与移动应用本身有关。本文我们将关注通过安卓开发者努力可以解决的问题。
因此我们将在这里提出三个潜在的漏洞源:使用网络服务(WS)通信时的风险、在存储设备上存储数据时潜在的信息泄漏以及第三方软件能轻易编辑应用程序的漏洞。一、安全的网络服务调用
对于使用WS的敏感应用,最重要的就是保证用户分享在后台的数据是安全的。事实上,如果网络上的请求能被轻易截取,最安全的应用程序也是毫无用处的。威胁:中间人攻击(MITM)
应用程序遭受中间人攻击有两个主要的风险。
1.信息泄漏
如果窃取者控制了用户使用应用的本地网络,他暗地里轻易就能截取到 app 和 WS 的所有通信。
2.网络服务(WS)模仿
对 WS 有一定认识的人可以阻塞应用调用并且提供伪造的回应,这时用户认为他们的请求已经执行,然而请求根本没有到达后台。
测试应用在中间人攻击时的脆弱性相当简单:你只需要使用一个代理软件(例如CharlesProxy[12]),然后建立设备来使用安装了这个代理的机器。如果应用不能阻止中间人攻击,你将能看到它执行的每个请求。现在,想象你的 app 用户通过“不安全”的网络连接到你的网络服务:窃取者可以毫不费力地将代理安装在网络路由器上,就能嗅到所有不加密的请求。攻击源:TLS/SSL证书链
保证通信安全至少要使用 HTTPS 协议,也就是说使用安全传输层协议(TLS)或是它的前身安全套接层协议(SSL)加密的通信。
然而,如果有必要,这并不是系统需要遵守的唯一条件。为了理解清楚,我们来看看 SSL 协议的工作原理。
SSL 证书(至少)包括三个证书:
根证书。这是由证书认证机构(CA)颁发的,也就是一个可以确保整个通信时安全的值得信任的组织。
中间证书。有许多个中间证书。它们建立终端用户证书和根证书的连接,是为提供WS的服务器服务,由根证书签名的证书。
终端用户证书。终端用户证书是适用于WS物理服务器的证书。
安卓 SSL 本地保护:
安卓网络层有一个内置的CA 证书列表(超过一百个,你可以在设备参数中检查这个列表)。每个HTTPS网络调用需要在证书链上有一个CA证书。
然而,没有办法确保其余的链适合我们想要连接的服务器。例如一个窃取者可以向CA购买中间证书实施中间人攻击。所有的网络事务都将被系统视作无效。这种漏洞非常常见:一个研究表明[1]73%使用HTTPS 协议的应用并没有用正确的方式检查证书。
怎样保证连接的是我们的后台并且这个连接是安全?
解决上述问题的方式是手动检查中间证书(适用于特定服务器)是已知证书。这意味着我们需要将特定的服务器证书存储在应用中,可以将它作为常数存储在资源文件或直接放在源代码中来实现。
我们可能会疑惑为什么需要检查中间证书而不是终端用户。这里有两个理由,第一,终端用户证书生存期很短。第二点是安全理由:想象一下,一个黑客完全控制了系统,那他将拥有你的私钥(服务器需要私钥签名请求)。应用会认为请求是由正确的终端用户私钥签名,并且会允许连接。如果认证在中间服务器检查时实现,那就有可能通过联系中间CA远程废除证书。
SSLSocketFactory&类可以验证一个 SSL&连接是否安全。创建一个执行中间证书检查的 SSLSocketFactory,我们需要执行以下步骤。
1.创建一个继承于 X509TrustManger 的类。这是一个&java.net.ssl&包中的抽象类,用于检查服务器端 SSL&socket 的合法性。public&class&MyX509TrustManager&implements&X509TrustManager&{
private&X509Certificate&
public&MyX509TrustManager&(InputStream&knownIntermediateCertificate)&throws&CertificateException&{
CertificateFactory&certFactory&=&CertificateFactory.getInstance("X.509");
certificate&=&certFactory.generateCertificate(knownIntermediateCertificate);
public&void&checkClientTrusted(X509Certificate[]&chain,&String&authType)&throws&CertificateException&{
//&Do&nothing.&We&only&want&to&check&server&side&certificate.
public&void&checkServerTrusted(X509Certificate[]&chain,&String&authType)&throws&CertificateException&{
//&Verify&that&the&certificate&domain&name&matches&the&expected&one
if&(!chain[0].getIssuerDN().equals(certificate.getSubjectDN()))&{
throw&new&CertificateException("Parent&certificate&of&server&was&different&than&expected&signing&certificate");
//&Verifiy&that&the&certificate&key&matches&the&expected&one
chain[0].verify(certificate.getPublicKey());
//&Verify&that&the&certificate&has&not&expired
chain[0].checkValidity();
}&catch&(Exception&e)&{
throw&new&CertificateException("Parent&certificate&of&server&was&different&than&expected&signing&certificate");
public&X509Certificate[]&getAcceptedIssuers()&{
//&Do&nothing
return&new&X509Certificate[0];
2.设置一个新的默认 SSLSocketFactory。代码需要在网络调用前运行。TrustManager[]&trustManagerArray&=&new&TrustManager[1];
MyTrustManager&trustManager&=&new&MyTrustManager(TRUSTED_CERTIFICATE);
trustManagerArray[0]&=&trustM
final&SSLContext&
//&TLS&is&the&last&SSL&protocol&and&is&used&by&all&the&CA
sslc&=&SSLContext.getInstance("TLS");
//&We&only&need&to&give&a&TrustManager&list&as&we&don't&need&to&perform&client&authentification
sslc.init(null,&trustManagers,&null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslc.getSocketFactory());证书检查潜在缺陷
1.中间证书会过期(其生存期大概是10年)。在证书过期前将新的证书添加到白名单可以有效检测证书的变化。
2.中间证书认证机构会失效。如果中间证书认证机构失效,它所提供的安全机制将会完全无效。事实上,如果黑客保留了中间 CA ,他将能够伪造证书链,拥有和你的证书链相同的中间证书。此时他就能实施中间人攻击。尽管CA理论上是安全的,依然可能发生像2011年Dignotar证书失效的事件。一旦发生这种情况,唯一能做的事情就是改变服务器上的SSL证书链,并且发布一个内嵌新的中间证书的版本。
3.SSLSocketFactory 认为它的策略适用于应用中的所有网络调用。如果sdk是内置的,那就有必要为远程服务器的这些sdk嵌入中间证书。存在的不确定性是无法轻易察觉服务器证书的变化。
动态植入证书会遇到这种问题。应用只允许一个证书(主服务器一个)并且在应用运行时获取一个授权中间证书的动态列表,然后将这些证书添加到&SSLContext&的&trust&manager中。
总而言之,在大多数情况下,中间检查机制能够防御中间人攻击。黑客窃听通信时,他必须将自己的证书列入证书链,&TrustManager不能识别这个证书,于是拒绝 HTTPS&连接。二、设备上的存储安全
多亏了SharedPreferences&接口,安卓平台提供了一种方便的方式存储参数以及大文件。尽管存储在shared&preferences中的数据隐藏在隐藏目录中,如果设备获得了root权限,那就可以轻而易举地恢复数据。
因此,如果存储在应用中的是敏感数据,有必要加密shared&preferences中的数据。有两种方式:
1.使用密码库加密/解密&SharedPreferences 的 values(最后是key)。有许多形式的 java 密码库,例如&javax.crypto、Bouncycastle[2] 和&Concealed[3]。
2.使用提供&SharedPreferences 包装类的库。这些密码库使用很方便,开发者不需要关心使用什么算法。然而,使用这些库会失去灵活性并且有些并不使用安全算法。因此,它们并不适合存储敏感的数据。SecurePreference[4] 是其中一个最常用的提供这种包装特性的库。如果你选择这种方式,你可以用非常直接的方式实例化一个继承自SharedPreferences 的&SecurePreferences 类:SecurePreferences&securePreferences&=&new&SecurePreferences(context,&"MyPassword",&null);
不幸的是,这种方法不能满足每个应用的用户体验。例如如果我们想要在pin码输入前显示存储的信息,那我们就不能使用安全加密系统。
幸好,安卓提供了一种安全的方式来为一些应用程序/设备生成特定的key:&KeyStore。安卓 KeyStore 是为了允许应用将私钥放在不能被其他应用的地方,或者是不能通过实质性访问存储在设备上的数据获取私钥的地方。
机制非常简单:首先,运行应用检查应用相关的私钥是否存在。如果不存在,就生成一个并存储在KeyStore 中。如果私钥存在,它可以成为安全密钥来解析SharedPreferences&的数据,这多亏了上文描述的算法。
Obaro&Ogbo写了一篇详细的文章深刻描绘了如何使用 KeyStore 生成私钥/公钥对。KeyStore 主要的缺点是只允许API18以上版本使用。但是有一个兼容API14以上版本的补丁库(这不是“官方”的布丁,所以你必须自己承担后果)。
因此,我们建议当需要决定优先使用哪种系统时可以参考下面的策略图:三、防止应用被源代码分析和修改
有时,安卓开发者不希望应用被其他人分析,解读,最后被修改。这种要求有各种理由:
我们不希望黑客移除用于阻止非付费用户使用某些功能的应用锁。
我们开发的敏感应用时的风险是,黑客会将应用修改成所有输入信息都会返回给他。尽管应用商店不容易发生这种情况,但是用户可以去许多其他地方下载到伪造的应用,这些应用会用完全透明的方式偷取他所有的数据。
每个安卓开发者都应该注意,当开发敏感应用时,经验丰富的人反编译一个安卓应用是相当简单的。特别是使用“本地”应用配置的情况。事实上,因为大多数安卓app的特性(使用 Java 字节码),反编译字节码后解读,改正,最后重建一个修改过的应用非常简单。
这部分我们会强调一些可以规避风险的技术工具和构建原则。同时,我们需要注意,因为应用程序运行在客户端设备上,我们并没有百分之百确信的方法来规避这些风险。
1.有价值的算法写在服务器端
下面是构建指南。如果你的应用程序价值是以算法为基础的,你当然不希望有人能轻易解读、复制并且将你的算法嵌入自己的应用程序中。此时,最好的解决方式是在服务器端实现算法。应用程序只需提供待处理的数据给服务器,然后获取算法的返回值。这种结构的明显缺点是,在离线状态下无法使用app&的核心功能。
2.防止WS完全开放
如果应用程序的功能是借助 WS 获取数据,你可以发送在认证阶段获得的session token 或者在每个请求中授予user / password 来保证WS 安全。如果仅仅是在app&参数中使用认证标志,将这个标志设置成“always&connected”就可以轻松修改应用程序代码。这么做的风险是用户需要定期输入使用过的id和密码来延长会话。
3.使用Proguard混淆代码
Proguard 是 Java 工程中常用的工具。Proguard 工具执行三个操作:压缩步骤(移除无用代码)、优化步骤(内联方法、移除无用方法等)、混淆步骤。在最后一个步骤中,Proguard 会重命名Java 文件中所有类、属性、方法名,为了使它们在字节码被反编译后难以辨认。Proguard 当然也确保 JVM 能够区分不同的编译元素。
这个工具的有趣之处在于它使反编译字节码可读性变差了很多。然而,尽管代码元素被重命名,通过逆向工程化应用的方式依然可能猜测出混淆后的方法和属性的功能。Proguard&也生成了一个 mapping 文件,可以将混淆的 stacktrace 转换成可读状态[6]。
网上有许多详细解释如何配置Proguard&的指导,比如在安卓系统文档中的配置[7]。
4.使用编译库
通过Java本地接口(JNI),我们可以使用 C/C++ 语言写的本地代码(已编译代码)并且与Java&代码交互。开发安卓程序时会更简单,因为 NDK 提供了可以在应用程序中使用已编译代码的工具。整体机制很简单:编译你的 C/C++代码(必须包含标准的JNI&入口点),获得一个 .so 文件。这时你就在应用程序工程中包含了库和java&接口。
编译库的主要优势是,反编译代码可读性更差,因为 .so 文件使用本地机器语言而不是java&字节码。用 C/C++ 开发应用程序高度敏感的部分(例如最高机密算法或是安全层)然后与其余用传统 Java 编写的部分交互,这将是一个不错的实践(如果实际上很方便)。
使用 NDK&依然有许多缺点:我们必须为应用程序针对的不同类型的硬件结构编译本地库,这样就放弃了产生 crash&时得到适当stacktrace 的可能性,同时它也大大增加了代码结构。总结
在本文,我们建议的解决方法覆盖了 3 个 OWASP 中排名前十的手机安全问题[9]。像我们介绍中提到的,只有当系统结构是安全的,应用程序才是安全的。一个人可以开发技术上安全的应用,但如果服务器没有授权良好的认证系统,所有的努力都是无意义的。同时,确保完美的安全边界是手机开发者的责任,这篇文章给出了覆盖安全边界的解决方法。参考
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量10332点击量7922点击量6595点击量5228点击量5203点击量4934点击量4593点击量4552点击量4377
&2016 Chukong Technologies,Inc.
京公网安备89类似问题 &
J2EE &&&&最新内容
J2EE &&&&相关内容}

我要回帖

更多关于 x509trustmanager ca 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信