当前位置: 首页 > 知识库问答 >
问题:

如何使用Square OKHTTP固定证书?

田慈
2023-03-14

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

谢谢!

编辑:

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

请参阅此处的源代码以开始使用

共有3个答案

曾宏毅
2023-03-14

如果您无权访问域(例如受限访问)并且无法测试虚假哈希,但您有证书文件,您可以使用openssl检索它:

openssl x509 -in cert.pem -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
马飞
2023-03-14

这比我想象的OkHttp更容易。

请遵循以下步骤:

1.获取公共sha1密钥。OkHttp文档为我们提供了一种用示例代码完成此任务的清晰方法。如果它消失了,请将其粘贴在下面:

例如,要固定 https://publicobject.com,请从损坏的配置开始:

String hostname = "publicobject.com";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
    .add(hostname, "sha1/BOGUSPIN")
    .build();
OkHttpClient client = new OkHttpClient();
client.setCertificatePinner(certificatePinner);

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

如预期的那样,此操作失败,出现证书固定异常:

javax.net.ssl.SSLPeer未验证异常: 证书固定失败!
对等证书链: 中文=科摩多 RSA 域验证安全服务器 CA sha1/blhOM3W9V2S 中文=: CN=公共对象.com, OU=正数列表 sh1/SXXOAOSEZ6BgGmxAt/EAcsajw=: CN=COMODO RSA 域验证安全服务器 CA sha1/blhOM3W9V/bVQHSW6n24=: CN=中国=中国人民网 RSA 证书颁发机构 sha1/T5x9IXMCRQ7 优QXXXNXOCMEEQ84c=: CN=AddTrust 外部 CA 根目录

publicobject.com的固定证书:

com.squareup.okhttp.CertificatePinner.check(CertificatePinner.java)com.squareup.okhttp.Connection.upgradeToTls(Connection.java)com.squareup.okhttp.Connection.connect(Connection.java)com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java)

接着将异常中的公钥散列粘贴到证书pinner的配置中:

附注:如果您在Android上执行此操作,则在UI线程上执行此操作时,您将获得单独的异常,因此请确保在后台线程上执行此操作。

2.配置OkHttp客户端:

OkHttpClient client = new OkHttpClient();
client.setCertificatePinner(new CertificatePinner.Builder()
       .add("publicobject.com", "sha1/DmxUShsZuNiqPQsX2Oi9uv2sCnw=")
       .add("publicobject.com", "sha1/SXxoaOSEzPC6BgGmxAt/EAcsajw=")
       .add("publicobject.com", "sha1/blhOM3W9V/bVQhsWAcLYwPU6n24=")
       .add("publicobject.com", "sha1/T5x9IXmcrQ7YuQxXnxoCmeeQ84c=")
       .build());

这就是它的全部!

屠嘉
2023-03-14

OKHTTP 3.0内置了对固定证书的支持。首先粘贴以下代码:

 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();

这将失败,因为< code > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 不是您的证书的有效哈希。抛出的异常将包含您的证书的正确哈希值:

 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("html" target="_blank">publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
   .add("publicobject.com", "sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=")
   .add("publicobject.com", "sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=")
   .add("publicobject.com", "sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=")
   .build();

在阅读了这篇博文之后,我能够修改这个概念以用于OkHttp。如果您想避免使用全局SSL上下文,应该至少使用2.0版。

此修改仅适用于OkHttp的当前实例,并更改该实例,使其仅接受来自指定证书的证书。如果您希望接受其他证书(例如来自Twitter的证书),只需创建一个新的OkHttp实例,而不需要进行下面描述的修改。

为了固定证书,您首先需要创建一个包含此证书的信任库。要创建信任库,我们将使用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. 确保keytools(包含在Android SDK中)在您的$PATH上。
  2. 确保您在与脚本相同的目录中下载了最新的BouncyCastle jar文件。(在此处下载)
  3. 您要固定的证书。

现在运行脚本

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

键入yes以信任证书,完成后mytruststore.bks将在当前目录中生成。

在< code>res文件夹下创建一个目录< code>raw。在此复制< code>mytruststore.bks。

现在有一个非常简单的类,可以将证书固定到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设置为您传入外壳脚本的密码。您的OkHttp实例现在应该只接受您指定的证书。

 类似资料:
  • 问题内容: 如何在Swift中将证书固定到NSURLSession? 该OWASP网站只包含Objective- C和NSURLConnection的一个例子。 问题答案: Swift 3+ 更新: 只需定义一个委托类并实现didReceiveChallenge函数( 此代码改编自Objective-c OWASP示例 ): (您可以在此处找到Swift 2 的Gist- 从初始答案开始) 然后使

  • 本文向大家介绍如何在pytest中使用固定装置?,包括了如何在pytest中使用固定装置?的使用技巧和注意事项,需要的朋友参考一下 固定装置是应在pytest中与之关联的每个测试方法之前执行的方法。Pytest是python中的测试框架。要安装pytest,我们需要使用命令pip install pytest。安装后,我们可以通过pytest –version命令验证是否已安装python 。py

  • 我目前正在为我的React本机应用程序实施SSL证书固定。 我找到了一个很好的答案,详细解释了为和存档此文件的步骤 但不幸的是,解决方案只能在使用API发出请求的情况下工作,我正在尝试找到一个还包括API的解决方案

  • 本文向大家介绍如何固定MySQL插入?,包括了如何固定MySQL插入?的使用技巧和注意事项,需要的朋友参考一下 借助以下语法,可以在同时插入多个记录时加快MySQL的插入速度 让我们首先创建一个演示表 同时插入多个记录。查询如下-

  • 问题内容: 简单方案: 我需要为设置一个固定宽度。我试过了: 也 对于 乃至 但是的宽度仍然相同。 问题答案: 对于Bootstrap 4.0: 在Bootstrap4.0.0中,您不能可靠地使用这些类(在Firefox中有效,但在Chrome中不适用)。您需要使用OhadR的答案: 对于Bootstrap 3.0: 在twitter bootstrap 3中使用:其中*是宽度的列数。 对于Boo

  • 这是我需要解决的问题。 创建包含输入表单的基本网页。JavaScript将嵌入到HTML文档中。 输入表格应包括: 用户名字段订单数量输入字段物料价格只读字段–订单总成本“提交按钮”的值设置为5.31只读字段,不使用任何类型的表单按钮元素用户应能够输入其名称和订单数量,然后单击“提交”。单击“提交”时,表单将计算订单总额,包括8.25%的销售税。计算后,订单总额表单字段将更新为总额,包括美元符号和