通过翻新操作固定Android SSL证书

时间:2019-07-30 05:27:27

标签: android ssl ssl-certificate retrofit2 certificate-pinning

我想在Android应用程序中进行证书固定。我对此感到非常沮丧。请帮助我

我有什么:-

  1. .cert类型的证书文件。
  2. 。存储私钥的密钥类型密钥文件。

我没有实施此证书的域名。我只有IP地址。我在我的项目中使用okHttp和改造。我已经在堆栈溢出中看到很多实现此目的的例子。

但是我没有得到一些东西: 1.如果我没有域名,是否可以将ssl转换为IP地址? 2. pins 字段将包含什么,我没有任何私钥。我在哪里可以找到私钥(sha256 / XXXXXXXXXX)?

Retrofit provideRetrofit(OkHttpClient okHttpClient, Gson gson) {
    CertificatePinner certPinner = new CertificatePinner.Builder()
            .add("patternField","pins")
            .build();

       OkHttpClient okHttpClientForPinning = new OkHttpClient.Builder()
            .certificatePinner(certPinner)
            .build();
    OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
    try {
       clientBuilder.sslSocketFactory(getSSLConfig(context).getSocketFactory());
    }
    catch (Exception e) {
        e.printStackTrace();
    }

    clientBuilder.hostnameVerifier(new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            boolean value = true;
            //TODO:Some logic to verify your host and set value
            return value;
        }
    });

    return new Retrofit.Builder()
            .baseUrl(backendUrl)
            .client(okHttpClient)                      
            .client(okHttpClientForPinning)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build();


}

1 个答案:

答案 0 :(得分:1)

证书图钉

  

我没有实施此证书的域名。我只有IP地址。

要通过IP地址获取服务器证书的密码,您可以尝试this bash script

#!/bin/bash
# Heavily inspired on:
#   * https://medium.com/@appmattus/android-security-ssl-pinning-1db8acb6621e#ecea

set -eu

Main()
{
    local domain="${1? Missing domain name to extract and hash the certificate public key !!!}"

    local domain="${domain##*://}"

    local certs=$( openssl s_client -servername "${domain}" -host "${domain}" -port 443 -showcerts </dev/null 2>/dev/null | sed -n '/Certificate chain/,/Server certificate/p' )

    local rest=$certs

    while [[ "$rest" =~ '-----BEGIN CERTIFICATE-----' ]]; do

        cert="${rest%%-----END CERTIFICATE-----*}-----END CERTIFICATE-----"
        rest=${rest#*-----END CERTIFICATE-----}

        local certificate_name="$( echo "$cert" | grep 's:' | sed 's/.*s:\(.*\)/\1/' )"

        if [ -n "${certificate_name}" ]; then
            printf "\nCERTIFICATE NAME:\n\n${certificate_name} \n\n"
        fi

        printf "\nCERTIFICATE PUBLIC KEY HASH:\n\n"

        echo "$cert" |
            openssl x509 -pubkey -noout |
            openssl rsa -pubin -outform der 2>/dev/null |
            openssl dgst -sha256 -binary |
            openssl enc -base64

        echo

        exit 0

    done
}

Main ${@}

将bash脚本保存到文件并按以下方式调用它:

bash hash-certificate-public-key-from-domain.bash ip-address-here

在我的个人网站上使用它的真实示例:

╭─exadra37@exadra37-Vostro-470 ~/Developer/Approov/currency-converter-demo  ‹volley-pinning-with-approov_cleanup-proguard*› 
╰─➤  ./bin/hash-certificate-public-key-from-domain.bash 68.183.252.187                                                                                                                                       130 ↵

CERTIFICATE NAME:

CN = exadra37.com 


CERTIFICATE PUBLIC KEY HASH:

1O0wDRM/roe6UTctDVQ5aN/ASNYsGQFVzXYhO34t5GE=

╭─exadra37@exadra37-Vostro-470 ~/Developer/Approov/currency-converter-demo  ‹volley-pinning-with-approov_cleanup-proguard*› 
╰─➤  ./bin/hash-certificate-public-key-from-domain.bash exadra37.com  

CERTIFICATE NAME:

CN = exadra37.com 


CERTIFICATE PUBLIC KEY HASH:

1O0wDRM/roe6UTctDVQ5aN/ASNYsGQFVzXYhO34t5GE=

╭─exadra37@exadra37-Vostro-470 ~/Developer/Approov/currency-converter-demo  ‹volley-pinning-with-approov_cleanup-proguard*› 
╰─➤  ./bin/hash-certificate-public-key-from-domain.bash https://exadra37.com

CERTIFICATE NAME:

CN = exadra37.com 


CERTIFICATE PUBLIC KEY HASH:

1O0wDRM/roe6UTctDVQ5aN/ASNYsGQFVzXYhO34t5GE=

如您所见,引脚1O0wDRM/roe6UTctDVQ5aN/ASNYsGQFVzXYhO34t5GE=的哈希值始终相同。

  
      
  1. 将要固定的字段包含什么,我没有任何私钥。我在哪里可以找到私钥(sha256 / XXXXXXXXXX)?
  2.   

私钥是私钥,因此,如果找到它,那么所有安全性都会丢失,除非您还控制要连接的服务器。无论如何,您都不需要它执行证书固定,只需像上面的bash脚本一样,通过生成证书的哈希(又称“ pin”)来固定证书的公钥即可。

因此,您要寻找的sha256是上述脚本中的图钉的输出,在我的示例1O0wDRM/roe6UTctDVQ5aN/ASNYsGQFVzXYhO34t5GE=中也是如此。

实施证书固定

虽然我不知道如何为您提供翻新服务,但我可以向您展示一种更简单的固定方式。

如今,对于Android而言,存在一种更简单的方法,我在博客文章Securing HTTPS With Certificate Pinning中对此进行了描述,您可以在其中了解到只需将证书图钉添加到网络安全配置文件中即可完成此操作,或者需要支持低于API级别24的内容,那么您可能需要将TrustKit软件包与文件结合使用。

带有TrustKit的示例network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>

    <!-- Official Android N API -->
    <!--https://android-developers.googleblog.com/2016/07/changes-to-trusted-certificate.html-->
    <domain-config>
        <domain>currency-converter-demo.pdm.approov.io</domain>
        <trust-anchors>
            <!--<certificates src="user" />-->
            <certificates src="system" />
        </trust-anchors>
        <pin-set>
            <!-- Pin for: currency-converter-demo.pdm.approov.io -->
            <pin digest="SHA-256">qXHiE7hFX2Kj4ZCtnr8u8yffl8w9CTv6kE0U5j0o1XY=</pin>

            <!-- Backup Pin for: currency-converter-demo.pdm.approov.io -->
            <pin digest="SHA-256">47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=</pin>
        </pin-set>

        <!-- TrustKit Android API -->
        <!-- enforce pinning validation -->
        <trustkit-config enforcePinning="true" disableDefaultReportUri="true">
            <!-- Add a reporting URL for pin validation reports -->
            <report-uri>https://report.domain</report-uri>
        </trustkit-config>
    </domain-config>

</network-security-config>