如何使用 Square OKHTTP 固定证书?

2024-04-26

我想我需要创建一个新的 SSL 套接字工厂? 另外,我不想使用全局 SSL 上下文(https://github.com/square/okhttp/issues/184 https://github.com/square/okhttp/issues/184)出于显而易见的原因。

thanks!

EDIT:

从 okhttp 2.1.0 开始,您可以非常轻松地固定证书。

See 源代码在这里 https://github.com/square/okhttp/blob/83090befcca69b44c257b96afb519ca66282ca63/okhttp/src/main/java/com/squareup/okhttp/CertificatePinner.java#L43开始


OKHTTP 3.0 更新

OKHTTP 3.0 有内置支持 http://square.github.io/okhttp/3.x/okhttp/okhttp3/CertificatePinner.html用于固定证书。首先粘贴以下代码:

 String hostname = "yourdomain.com";
 CertificatePinner certificatePinner = new CertificatePinner.Builder()
     .add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
     .build();
 OkHttpClient client = OkHttpClient.Builder()
     .certificatePinner(certificatePinner)
     .build();

 Request request = new Request.Builder()
     .url("https://" + hostname)
     .build();
 client.newCall(request).execute();

这会失败,因为AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA不是您证书的有效哈希值。抛出的异常将具有您的证书的正确哈希值:

 javax.net.ssl.SSLPeerUnverifiedException: Certificate pinning failure!
   Peer certificate chain:
     sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=: CN=publicobject.com, OU=PositiveSSL
     sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=: CN=COMODO RSA Secure Server CA
     sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=: CN=COMODO RSA Certification Authority
     sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=: CN=AddTrust External CA Root
   Pinned certificates for publicobject.com:
     sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
   at okhttp3.CertificatePinner.check(CertificatePinner.java)
   at okhttp3.Connection.upgradeToTls(Connection.java)
   at okhttp3.Connection.connect(Connection.java)
   at okhttp3.Connection.connectAndSetOwner(Connection.java)

确保将这些添加到您的 CertificatePinner 对象中,并且您已成功固定您的证书:

 CertificatePinner certificatePinner = new CertificatePinner.Builder()
   .add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
   .add("publicobject.com", "sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=")
   .add("publicobject.com", "sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=")
   .add("publicobject.com", "sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=")
   .build();

此处的所有内容均适用于较旧的 (2.x) 版本的 OKHTTP

看完之后这篇博文 http://nelenkov.blogspot.co.uk/2011/12/using-custom-certificate-trust-store-on.html我能够修改与 OkHttp 一起使用的概念。如果您想避免使用全局 SSL 上下文,则应至少使用版本 2.0。

此修改仅适用于 OkHttp 的当前实例,并更改该实例,以便它only接受指定证书中的证书。如果您希望接受其他证书(例如来自 Twitter 的证书),您只需创建一个新的 OkHttp 实例,无需进行下述修改。

1. 创建信任库

为了固定证书,您首先需要创建包含该证书的信任库。为了创建信任库,我们将使用 nelenkov 的这个方便的脚本,根据我们的目的稍作修改:

#!/bin/bash

if [ "$#" -ne 3 ]; then
  echo "Usage: importcert.sh <CA cert PEM file> <bouncy castle jar> <keystore pass>"
  exit 1
fi

CACERT=$1
BCJAR=$2
SECRET=$3

TRUSTSTORE=mytruststore.bks
ALIAS=`openssl x509 -inform PEM -subject_hash -noout -in $CACERT`

if [ -f $TRUSTSTORE ]; then
    rm $TRUSTSTORE || exit 1
fi

echo "Adding certificate to $TRUSTSTORE..."
keytool -import -v -trustcacerts -alias $ALIAS \
      -file $CACERT \
      -keystore $TRUSTSTORE -storetype BKS \
      -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider \
      -providerpath $BCJAR \
      -storepass $SECRET

echo "" 
echo "Added '$CACERT' with alias '$ALIAS' to $TRUSTSTORE..."

要运行这个脚本,你需要做三件事:

  1. 确保keytool(包含在 Android SDK 中)位于您的 $PATH 中。
  2. 确保您在与脚本相同的目录中下载了最新的 BouncyCastle jar 文件。 (下载here http://www.bouncycastle.org/download/bcprov-jdk15on-150.jar)
  3. 您想要固定的证书。

现在运行脚本

./gentruststore.sh your_cert.pem bcprov-jdk15on-150.jar your_secret_pass

输入“yes”以信任该证书,完成后mytruststore.bks将在您当前的目录中生成。

2. 将您的 TrustStore 应用到您的 Android 项目中

创建目录raw在你的res文件夹。复制mytruststore.bks here.

现在这是一个非常简单的类,它将您的证书固定到 OkHttp

import android.content.Context;
import android.util.Log;

import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

import java.io.InputStream;
import java.io.Reader;
import java.security.KeyStore;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;


/**
 * Created by martin on 02/06/14.
 */
public class Pinning {

    Context context;
    public static String TRUST_STORE_PASSWORD = "your_secret";
    private static final String ENDPOINT = "https://api.yourdomain.com/";

    public Pinning(Context c) {
        this.context = c;
    }

    private SSLSocketFactory getPinnedCertSslSocketFactory(Context context) {
        try {
            KeyStore trusted = KeyStore.getInstance("BKS");
            InputStream in = context.getResources().openRawResource(R.raw.mytruststore);
            trusted.load(in, TRUST_STORE_PASSWORD.toCharArray());
            SSLContext sslContext = SSLContext.getInstance("TLS");
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                    TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(trusted);
            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            Log.e("MyApp", e.getMessage(), e);
        }
        return null;
    }

    public void makeRequest() {
        try {
            OkHttpClient client = new OkHttpClient();
            client.setSslSocketFactory(getPinnedCertSslSocketFactory(context));

            Request request = new Request.Builder()
                    .url(ENDPOINT)
                    .build();

            Response response = client.newCall(request).execute();

            Log.d("MyApp", response.body().string());

        } catch (Exception e) {
            Log.e("MyApp", e.getMessage(), e);

        }
    }
}

正如你所看到的,我们实例化了一个新实例OkHttpClient并打电话setSslSocketFactory,传入一个SSLSocketFactory使用我们的自定义信任库。确保你设置了TRUST_STORE_PASSWORD到您传递到 shell 脚本中的密码。您的 OkHttp 实例现在应该只接受您指定的证书。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Square OKHTTP 固定证书? 的相关文章

  • 我们如何从 Android 通知中提取 bigpicturestyle 图像?

    我有一个通知侦听器服务 可以读取来自其他应用程序的通知 经用户许可 并提取所有数据 能够访问除通知展开视图中显示的图像之外的所有内容 我也在阅读 EXTRA PICTURE 意图值 if extras containsKey Notific
  • 模仿 youtube/gmail 应用程序的导航抽屉

    背景 近几个月来 谷歌发布了Youtube 应用程序 http www androidpolice com 2013 08 19 breaking massive youtube for android v5 0 update brings
  • Android中如何通过ViewModel类在Activity和Fragment之间共享数据?

    我想知道是否可以传递一个在 Activity 类中声明的字符串数据 并将该字符串数据传递给 ViewModel 类 然后将数据传递给 Fragment 类 视图模型类 class TimeTableViewModel extends Vie
  • 在 Android 中从麦克风录制 wav 文件 - 问题

    我需要能够使用 Android 中的麦克风创建 WAV 文件 目前 我遇到了很多麻烦 到目前为止 这就是我的情况 我正在使用 micDroid 项目代码的一部分来记录 read thread int sampleRate 44100 int
  • 如何解决:无法解析:com.mapbox.mapboxsdk:mapbox-android-sdk:9.5.0

    我在Android studio中尝试使用mapbox时遇到这个问题无法解析 com mapbox mapboxsdk mapbox android sdk 9 5 0 问题是什么 我的 build gradle 依赖项 dependenc
  • Auto-value-gson出现接口错误,注册一个InstanceCreator?

    我有一个如下所示的接口类 public interface Species String name And a Human实现的类 AutoValue使用类型适配器 AutoValue public abstract class Human
  • 在android中从JSON生成listview

    我对 Android 完全陌生 目前正在尝试从从我的服务器中提取的 JSON 数组生成列表视图 我已经阅读了很多教程 但没有运气 有一种独特的方法可以做到这一点 请您指出一些适合开始的资源 我读过了this http www josecgo
  • SQLite FTS4 使用特殊字符进行搜索

    我有一个 Android 应用程序 它使用 FTS4 虚拟表在 SQLite 数据库中搜索数据 它工作正常 但是当表中的数据包含特殊字符 如 或 时 SQLite MATCH 函数不会给出任何结果 我现在迷路了 谢谢 注意 默认的分词器真的
  • 在 Android 中跨单元测试和仪器测试共享资源

    现在谷歌已经添加了实验单元测试支持 http tools android com tech docs unit testing support 如何在单元测试和仪器测试之间共享资源 例如 假设我有一个TestUtils java我希望在单元
  • 如何在单个查询中搜索 RealmObject 的 RealmList 字段

    假设我有一堂课 public class Company extends RealmObject private String companyId private RealmList
  • 警报对话框中的 Webview 不显示内容

    我正在开发一个 Android 应用程序 我需要在网络视图和警报对话框上显示一个网站 该站点显示在网络视图中 但不显示在警报对话框中 到目前为止 这是我的代码 WebView WebView myWebView WebView v find
  • 带有 backstack Resume 的嵌套片段

    在我的应用程序中有几个fragments in an activity我正在维护一个backStack对于这些fragment 一切都很好 但其中有一个嵌套的片段 当我把它放入backStack然后再次按后退按钮恢复 该片段看起来与先前的内
  • 在android中从SD卡上传图像到facebook

    我无法从 SD 卡上传 Facebook 上的图像 我使用了下面的代码 但它没有给我错误 但同时它没有上传图像 byte data null try FileInputStream fis new FileInputStream filep
  • Android:分配内存失败

    我正在尝试创建一个具有 2047 mb 内存的模拟器 当我运行它时 我收到此错误 2011 02 22 14 24 14 Emulator 2011 02 22 14 24 14 Emulator This application has
  • Android S8+ 警告消息“不支持当前的显示尺寸设置,可能会出现意外行为”

    我在 Samsung S8 Android 7 中收到此警告消息 APP NAME 不支持当前的显示尺寸设置 可能会 行为出乎意料 它意味着什么以及如何删除它 谢谢 通过添加解决supports screens 机器人 xlargeScre
  • android系统用户和linux root用户有什么区别

    当我将手机连接到电脑并使用adb shell与我的手机通信并输入的命令ps命令输出当前在我的手机上运行的进程信息 我发现有两个特殊用户 一个是root 另一个是system 据我所知 Android是基于linux的 所以root用户是最大
  • 如何在android中安装和使用couch db

    我应该如何在 android 中安装和使用 couch Db 我的意思是本地沙发数据库 我可以在平板电脑和模拟器中使用它 为此我必须遵循哪些步骤 我目前正在开发一个使用它的项目 有两种选择 1 couchbase android 是的 co
  • 在线性布局内的 ScrollView 内并排对齐 TextView

    我有一个带有滚动视图的线性布局 我想保留它的当前格式 但只需将 textView2a 和 textView3a 并排放置 而不会破坏我当前的布局格式 我已经包含了我最近的尝试 但它们似乎不正确 提前致谢 Java菜鸟 当前有效的 XML
  • Android Espresso 单击按钮时出现错误

    我正在尝试使用 espresso 框架为 Android 应用程序编写一些 UI 测试 现在我只是检查启动屏幕上是否存在所有元素 然后尝试单击登录按钮 单击按钮时 测试由于错误而失败 我似乎无法理解为什么会发生这种情况 我的测试代码是 Ru
  • Keystore getEntry 在 Android 9 上返回 NULL

    c我已对存储在 Android 密钥库中的登录密码进行了加密和解密 在 Android 9 上 我观察到应用程序在尝试解密密码时崩溃 我无法重现它 但拥有 Pixel 3 的用户是崩溃的设备之一 下面是我如何从密钥库解密密码 private

随机推荐

  • Android 浏览器报告屏幕尺寸错误?

    我正在开发一个移动网站 我遇到了一个有趣的问题 我正在我的台式机以及我的 Motorola Droid Android 2 2 上进行测试 我设置了媒体查询来加载 3 个不同的样式表 320 像素宽 480 像素宽和 640 像素宽 我注意
  • 使用会话 ID 将消息添加到 IAsyncCollector 主题输出

    目前是否可以将消息推送到 Azure 函数的 IAsyncCollector 主题输出并设置会话 ID 我的主题实际上是关于 FIFO 排序的 所以我们必须设置会话 因此 我们设想只设置一个 Guid 作为唯一的会话 ID 我知道如何通过此
  • 显示MJPEG流的跨浏览器解决方案

    有没有一种轻量级 免费且可靠的方式在跨浏览器环境中显示 MJPEG 我正在尝试显示来自轴2120 http www axis com techsup cam servers cam 2120 index htm我正在开发的网站上有 IP 摄
  • 如何在 Guice 中定义方法拦截器的顺序?

    有时需要知道 Guice 中拦截方法调用的方法拦截器的顺序 一个简单的示例场景是使用 guice persist 提供的 Transactional 方法拦截器和自定义 Retry 方法拦截器 重试拦截器必须在事务拦截器外部运行 以确保重试
  • 操作 Symfony Intl 提供的国家列表和表单选择类型

    抛开政治不谈 我需要提供Kosovo作为选择国家时的形式选择 使用 Symfony 的内置表单选择类型执行此操作的最优雅的方法是什么country 同时还提供翻译Kosovo name 这是我到目前为止所做的事情 它有效 但我担心这可能有点
  • JPA 2 - 外键仅包含复合主键中的一个字段?

    我在 JPA 2 Hibernate 中获取复合主键和外键时遇到问题 我正在尝试创建一个包含国家和省份的简单场景 国家实体 Entity Table name country public class Country extends Dom
  • 版本变更jquery错误

    大家好 我使用 asp 构建了一个 Web 应用程序 其中包含一点来自 bootstap 的 jquery boorstrap dropdown js 对于其他一些比我开发的项目版本更低的项目 我将版本从4更改为3 5 现在我收到错误 Mi
  • 错误:无法计算表达式,因为代码已优化

    我的 asp net 应用程序中出现错误 内容如下 无法计算表达式 因为代码已优化或本机框架位于调用堆栈的顶部 protected void btnCustomerProfile Click object sender EventArgs
  • “: ${foo=value}”中冒号运算符的解释

    我理解 bash 中的冒号运算符的作用类似于a null http devmanual gentoo org tools reference bash index html multiple selection 我知道它用在参数扩展 htt
  • Android (ActionBarSherlock) 有什么方法可以在纵向和横向上保持相同的 ActionBar 高度吗?

    最近几天我一直在使用 ActionBar 和 ActionBarSherlock 在 ActionBar 中填写一些信息时遇到一些问题 当应用程序以纵向模式运行时 ActionBar看起来不错 并且可以显示所有数据 例如 但是当我将应用程序
  • 获取 Android 音乐播放器的专辑封面

    我想知道如何在音乐播放器中返回专辑封面的图像的代码 函数 你能解释一下我应该传递哪些参数吗 我可以将文件路径传递给该函数 imported required libraries public class SongsManager SDCar
  • 未定义拖放区

    我对 JavaScript 还很陌生 这让我发疯 我想使用 Dropzone js 因此我从以下位置下载了文件 dropzone jshere https raw githubusercontent com enyo dropzone ma
  • 使用图像的java自定义形状框架[重复]

    这个问题在这里已经有答案了 我喜欢创建一个像这个图像一样的java jframe 我已经用不同的形状 如三角形 圆形 多边形和一些疯狂的形状 创建了jframe 但是问题是太难 99 不可能 创建像这个图像的形状 所以我怎样才能制作一个像这
  • 在我的 flutter 应用程序中单击容器时更改容器的颜色

    我通过 API 获取了一些兴趣 数据 并向他们展示了使用未来的构建器作为容器 我想在单击容器时更改容器的背景颜色 这是我所做的 当我单击一个容器时 它会更改所有容器的背景颜色 我在容器的颜色中添加了一个 if 条件来检查它是否被单击 颜色
  • 表达式类型不明确,没有更多上下文 swift 4.0

    我正在实施pod Socket IO Client Swift but in SocketEngine swift文件我收到此错误 private func handleBase64 message String binary in bas
  • Proguard 混淆不起作用

    我试图混淆我的包名称 包括我使用的库之一 我在我的 gradle 文件中使用这个构建配置 buildTypes debug versionNameSuffix Development debuggable true runProguard
  • 使用 openGL、SOIL 加载图像

    我尝试了很多使用 SOIL 在 openGL 中加载和显示图像的示例 运行下面的源代码时 它仅显示一个没有图像的白色四边形 我尝试打开一个名为 foto 的图像 我将图像文件放在程序的文件夹中 bool keyStates new bool
  • Delphi:设置 TByteDynArray 长度的问题

    问题已结束 答案已接受 替换为Delphi 7 访问冲突 TByteDynArray 问题 https stackoverflow com questions 3157732 delphi 7 access violation tbyted
  • 删除一个单词及其后面的所有内容

    假设我有一个字符串 C Program Files x86 Steam steam exe lets go 342131 some random text 我想从该字符串中删除 steam exe 以及之后的所有内容 所以我修剪过的字符串看
  • 如何使用 Square OKHTTP 固定证书?

    我想我需要创建一个新的 SSL 套接字工厂 另外 我不想使用全局 SSL 上下文 https github com square okhttp issues 184 https github com square okhttp issues