当前位置:   article > 正文

通过证书固定从您的android客户端与服务器进行安全通信

base-config domain-config

Security and privacy are some of the most difficult tasks for any Android developer and it’s obvious because Android is an open-source platform and everyone knows how it works.

对于任何Android开发人员而言,安全性和隐私都是最艰巨的任务,这很明显,因为Android是一个开源平台,每个人都知道它的工作方式。

In this article, we’re going to deal with secure communication in Android, mainly between client and server.

在本文中,我们将处理Android中的安全通信,主要是客户端之间的通信 和服务器。

介绍 (Introduction)

Currently, the most common architecture of web services is REST-based on HTTP. The best protection method for this model of communication is the TLS/SSL standard.

当前,最常见的Web服务体系结构是基于HTTP的REST。 这种通信模型的最佳保护方法是TLS / SSL标准。

It can be combined with the HTTP protocol to create an encrypted variant called HTTPS. HTTPS ensures safe, encrypted communication between apps and server.

可以将其与HTTP协议结合以创建称为HTTPS的加密变体。 HTTPS确保应用程序和服务器之间的安全加密通信。

问题 (Problem)

It’s common for developers to implement networking calls over HTTPS, but not properly.

对于开发人员来说,通过HTTPS实施网络调用是很常见的做法,但是这样做不正确。

This can be solved by replacing the protocol name from HTTP to HTTPS in the URL. This will provide security to a certain extent by enabling TLS/SSL encryption by default (only if the server supports it).

可以通过将协议名称从HTTP替换为URL中的HTTPS来解决。 通过默认启用TLS / SSL加密(仅在服务器支持的情况下),这将在一定程度上提供安全性。

However, this is not good enough to keep your data secure. Simply replacing the protocol enables the encryption, but the app will trust every certificate issued by the server.

但是,这不足以确保数据安全。 只需替换协议即可启用加密,但是应用程序将信任服务器颁发的每个证书。

This means that the hacker can create fake certificates. The certificates will then allow the hacker to intercept encrypted communication which is well-known as a man-in-the-middle attack.

这意味着黑客可以创建伪造的证书。 然后,证书将允许黑客拦截加密的通信,这被称为中间人攻击。

It is the main reason why you should spend more time and effort to implement an HTTPS configuration correctly.

这是您应该花费更多的时间和精力来正确实现HTTPS配置的主要原因。

(Solution)

To avoid this threat, we should implement certificate pinning.

为了避免这种威胁,我们应该实现证书固定。

To do this, we need a server certificate with a fingerprint. We will compare the remote server certificate with the fingerprint while making the connection.

为此,我们需要带有指纹的服务器证书。 建立连接时,我们将比较远程服务器证书和指纹。

If they are identical, then it is a secure connection, otherwise, you should not do any data transfer as the connection is compromised.

如果它们相同,则表明它是安全连接,否则,由于连接受到破坏,您不应进行任何数据传输。

There are three ways to implement certificate pinning in Android:

有以下三种方法可在Android中实现证书固定:

  1. Network security configuration.

    网络安全配置。
  2. TrustManager.

    TrustManager。
  3. OkHttp and certificate pinning.

    OkHttp和证书固定。

网络安全配置 (Network Security Configuration)

This is one of the easiest ways and the native way to do certificate pinning in Android.

这是在Android中进行证书固定的最简单的方法之一。

Unlike the other two methods, this configuration requires no coding but network security configuration has one flaw: it only supports Android N and above.

与其他两种方法不同,此配置不需要编码,但是网络安全配置有一个缺陷:它仅支持Android N及更高版本。

The network security configuration feature lets apps customize their network security settings in a safe, declarative configuration file without modifying app code. These settings can be configured for specific domains and a specific app.

网络安全配置功能使应用程序可以在安全的声明性配置文件中自定义其网络安全设置,而无需修改应用程序代码。 可以为特定域和特定应用程序配置这些设置。

Network security configuration uses an XML file which has to be created under the res\xml directory and we need to declare this XML file in the manifest as shown below:

网络安全配置使用必须在res\xml目录下创建的XML文件,我们需要在清单中声明此XML文件,如下所示:

<?xml version="1.0" encoding="utf-8"?><manifest ... >    <application       android:networkSecurityConfig="@xml/network_security_config"                    ... >        ...    </application></manifest>

Now that we know how to create a network security file, it’s time to configure it.

现在我们知道了如何创建网络安全文件,是时候对其进行配置了。

Here, we have two main tags, <base-config> and <domain-config>.

在这里,我们有两个主要标签, <base-config><domain-config>

  • <base-config> is used to declare things or configurations that should be applied to the entire app, regardless of which domain holds the connection.

    <base-config>用于声明应应用于整个应用程序的事物或配置,而不管哪个域拥有连接。

  • On the other hand, <domain-config> is used to configure specific rules to only certain domains of your choice.

    另一方面, <domain-config>用于将特定规则配置为仅对您选择的某些域进行配置。

Have a look:

看一看:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <network-security-config>
  3. <base-config cleartextTrafficPermitted="false">
  4. <trust-anchors>
  5. <certificates src="system"/>
  6. </trust-anchors>
  7. </base-config>
  8. <domain-config>
  9. <domain includeSubdomains="true">secure.example.com</domain>
  10. <trust-anchors>
  11. <certificates src="@raw/crtf"/>
  12. </trust-anchors>
  13. </domain-config>
  14. </network-security-config>

Here, we used the <base-config> tag to disable clear-text traffic which means only HTTPS service calls will happen throughout the app and also mentions to use system certificates for networking.

在这里,我们使用<base-config>标记来禁用明文流量,这意味着整个应用程序中只会发生HTTPS服务调用,还提到使用系统证书进行联网。

But, coming to <domain-config>, we’ve mentioned a specific domain and configured certain rules for it, like only use the certificate file in the res/raw directory to make a network connection with the “secure.example.com” domain.

但是,在<domain-config> ,我们提到了一个特定的域并为其配置了某些规则,例如仅使用res/raw目录中的证书文件与“ secure.example.com ”建立网络连接。域。

Now that we know how to make use of the certificate, it’s time we use certificate pinning. Here, we use the <pin-set> tag to configure a certificate with a particular pin as shown below.

现在我们知道了如何使用证书,是时候使用证书固定了。 在这里,我们使用<pin-set>标记配置具有特定引脚的证书,如下所示。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <network-security-config>
  3. <domain-config>
  4. <domain includeSubdomains="true">sampleexample.com</domain>
  5. <pin-set expiration="2018-01-01">
  6. <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
  7. <!-- backup pin -->
  8. <pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin>
  9. </pin-set>
  10. </domain-config>
  11. </network-security-config>

信托管理人 (TrustManager)

This is one of the oldest methods to implement certificate pinning in Android.

这是在Android中实现证书固定的最古老的方法之一。

TrustManager is responsible for deciding if the app should allow credentials given by the peer or not. This technique is from the javax.net.ssl package and we used it here to implement certificate pinning.

TrustManager负责确定应用程序是否应允许对等方提供的凭据。 该技术来自javax.net.ssl包,我们在这里使用它来实现证书固定。

第1步 (Step 1)

Add your certificate file in the res/raw directory. It would be preferable if the certificate is in PEM or DER format without any comment lines in it.

将证书文件添加到res/raw目录中。 如果证书为PEM或DER格式,且其中没有任何注释行,则将是更可取的。

第2步 (Step 2)

Initialize the KeyStore with a certificate as shown below:

如下所示使用证书初始化密钥库:

  1. val resource_stream = resources.openRawResource(R.raw.cert)
  2. val key_store_type = KeyStore.getDefaultType()
  3. val key_store = KeyStore.getInstance(key_store_type)
  4. key_store.load(resource_stream, null)

第三步 (Step 3)

Now that we have the certificate instance it’s time to initialize TrustManager.

现在我们有了证书实例,是时候初始化TrustManager了。

  1. val trust_manager_algorithm = TrustManagerFactory.getDefaultAlgorithm()
  2. val trust_manager_factory = TrustManagerFactory.getInstance(trust_manager_algorithm)
  3. trust_manager_factory.init(keyStore)

第4步 (Step 4)

Now that we have the certificate and trust manager instances, let’s complete the final step by creating the SSL context with TLS protocol and then create a secure SSL connection with the TrustManager.

现在我们有了证书和信任管理器实例,让我们通过使用TLS协议创建SSL上下文,然后与TrustManager创建安全的SSL连接来完成最后一步。

  1. val ssl_context = SSLContext.getInstance("TLS")
  2. ssl_context.init(null, trust_manager_factory.trustManagers, null)
  3. val url = URL("http://www.secureexample.com/")
  4. val url_connection = url.openConnection() as HttpsURLConnection
  5. url_connection.sslSocketFactory = ssl_context.socketFactory

OkHttp和证书固定 (OkHttp and Certificate Pinning)

OkHttp is a very famous networking library from Square. Retrofit uses OkHttp for networking. The Okhttp team has made it very simple to implement certificate pinning.

OkHttp是来自Square的非常著名的网络库。 改造使用OkHttp进行联网。 Okhttp团队使实现证书固定变得非常简单。

First, we need to create a certificate pinner instance from the dedicated OkHttp CertificatePinner builder and then we add a domain and corresponding fingerprint to it.

首先,我们需要从专用的OkHttp CertificatePinner构建器创建证书固定器实例,然后向其添加域和相应的指纹。

Finally, add the builder to the OkHttp client. Have a look:

最后,将构建器添加到OkHttp客户端。 看一看:

  1. val certificatePinner = CertificatePinner.Builder()
  2. .add(
  3. "www.secureexample.com",
  4. "sha256/7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y="
  5. ).build()
  6. val okHttpClient = OkHttpClient.Builder()
  7. .certificatePinner(certificatePinner)
  8. .build()

We can also add multiple fingerprints to the builder. This will be helpful to add additional fingerprints if the present one is going to expire. We can also import the certificate files to the resources folder, as shown in the TrustManager case.

我们还可以向构建器添加多个指纹。 如果当前的指纹即将过期,这将有助于添加其他指纹。 我们也可以将证书文件导入到资源文件夹,如TrustManager案例所示。

Now, you need to manually write a class that will extract the fingerprint from the file. You can also use the Peer certificate extractor to extract fingerprints.

现在,您需要手动编写一个类,该类将从文件中提取指纹。 您还可以使用对等证书提取器提取指纹。

It’s definitely not recommended to mention the fingerprints statically in the code. Mention them in the Gradle file as a build-config field.

绝对不建议在代码中静态提及指纹。 在Gradle文件中将它们作为build-config字段提及。

证书简介 (Briefly About Certificates)

There are almost 138 certificate authorities that are accepted by the Android ecosystem and the count increases every day.

Android生态系统接受了将近138个证书颁发机构,并且这一数字每天都在增加。

You can add your self-signed, leaf, intermediate, or root certificate. Let me explain these certificates a bit more so that you’ll have a good idea of what they are.

您可以添加自签名证书,叶证书,中间证书或根证书。 让我进一步解释这些证书,以便您对它们的含义有所了解。

树叶证书 (Leaf Certificate)

By using a leaf certificate you are making it 100% sure that this is your certificate exactly, and you are establishing a secure connection.

通过使用叶证书,您可以100%确保这正是您的证书,并且您正在建立安全连接。

Leaf certificates have a very short expiry time so you need to push the update to your app to make sure of the connectivity. It’s highly recommended to use back-up keys.

叶子证书的有效时间非常短,因此您需要将更新推送到您的应用程序以确保连接性。 强烈建议使用备份密钥。

中级证书 (Intermediate Certificate)

By using an intermediate certificate you’re depending on the intermediate certificate authority.

通过使用中间证书,您将依赖于中间证书颁发机构。

This method has an advantage. As long as you stick to the same certificate provider, then any changes to your leaf certificates will work without having to update your app. Using an intermediate certificate is secure only when your provider is trustworthy.

该方法具有优势。 只要您坚持使用同一证书提供者,那么对叶子证书的任何更改都将起作用,而无需更新您的应用程序。 仅在您的提供商可信赖的情况下,使用中间证书才是安全的。

根证书 (Root Certificate)

By using the root certificate, you’re depending on all of the intermediate certificates approved by the root certificate authority. If any of the intermediate certificates are compromised then there are chances for your app to be cracked by hackers.

通过使用根证书,您将依赖于由根证书颁发机构批准的所有中间证书。 如果任何中间证书被盗用,那么您的应用就有可能被黑客破解。

结论 (Conclusion)

My suggestion of using OkHttp with certificate pinning is the best way to go.

我建议将OkHttp与证书固定一起使用是最好的方法。

Although many of us prefer native network security configurations, as I said, it only supports Android N and above devices. There will be no complete protection with the native methods, yet.

尽管我们许多人都喜欢本机网络安全配置,但正如我所说,它仅支持Android N及更高版本的设备。 本地方法还没有完全的保护。

Hopefully, in a year or two, the minimum android version will reach Android N and then we can use the native security configuration.

希望在一两年内,最低的android版本将达到Android N,然后我们可以使用本机安全配置。

Thank you for reading.

感谢您的阅读。

翻译自: https://medium.com/better-programming/secure-communication-with-the-server-from-your-android-client-with-certificate-pinning-5f53cea55972

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/679801
推荐阅读
相关标签
  

闽ICP备14008679号