我想我需要创建一个新的SSL套接字工厂?此外,我不想使用全局SSL上下文(https://github.com/square/okhttp/issues/184)因为显而易见的原因。
谢谢!
编辑:
从 okhttp 2.1.0 开始,您可以非常轻松地固定证书。
请参阅此处的源代码以开始使用
如果您无权访问域(例如受限访问)并且无法测试虚假哈希,但您有证书文件,您可以使用openssl检索它:
openssl x509 -in cert.pem -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
这比我想象的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());
这就是它的全部!
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..."
要运行这个脚本,您需要三样东西:
keytools
(包含在Android SDK中)在您的$PATH上。现在运行脚本
./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%的销售税。计算后,订单总额表单字段将更新为总额,包括美元符号和