How to use HTTPS correctly in the rapid development series--retrofit?

Source: Internet
Author: User
Tags cas sha1 go daddy ssl certificate mitm attack

Many articles on the use of client https is very vague, not only that, some developers directly from the Internet to copy some of the use of HTTPS "vulnerability" code, invisible to the client in a high-risk situation.

Today we will be on the use of HTTPS in-depth discussion, hoping to solve the past confusion. For HTTPS, you need to know how it works to see how HTTPS works? , more about HTTPS I will stand on the client's point of view in the back of the land on a succession of written.

Introduction to Certificate Locking

The first thing to say is the certificate lock.

Certificate locking is used to restrict which certificates and certification authorities are trustworthy. We call this a certificate lock by pinning the certificate of a server in the code, then using a custom trust store instead of the system's own, and then connecting to our server. In other words, a certificate lock is the code that verifies whether the current server holds a specified certificate, and if not, forcibly disconnects the link.

Is there any good for a classmate to ask for a certificate lock? Maximum benefits use certificate locking to increase security and reduce costs. Why do you say that? If you want to crack the communication, you need to get the client first, and then decompile, modify and then repackage the signature, compared to the original practice, this is undoubtedly increased the difficulty of cracking. In addition to this, because a certificate lock can use a self-signed certificate, it means that we do not need to buy a certificate from an Android-approved certificate authority, so that we can save a little more than 1000 dollars per year of certificate fees.

Using certificate Locking in Retrofit

Now, let's take a look at how to lock the certificate in retrofit.

new OkHttpClient.Builder()    .certificatePinner(new CertificatePinner.Builder()            .add("sbbic.com""sha1/C8xoaOSEzPC6BgGmxAt/EAcsajw=")            .add("closedevice.com""sha1/T5x9IXmcrQ7YuQxXnxoCmeeQ84c=")            .build())

It is not difficult to see through the above code that the certificate lock in retrofit is also implemented with okhttpclient: by adding Certificatepinner to Okhttpclient. The Certificatepinner object is created as a builder and can be used to lock multiple certificates through its add () method.

Principle of certificate Locking

Now let's dive into the principle of certificate locking. We know that both HTTP and HTTPS are server-side passive, the client is active. So the problem is, after the client makes the first request, it can't determine if the server is legitimate. Then it is likely that the following scenario will appear:

Normally, we want to view an article's content according to the article aid, with the following process:

At this point, what happens if a hacker intercepts the communication process maliciously?

At this point the malicious server can fully initiate a two-way attack: On the server can be spoofed to deceive the client, the more serious is that the client segment and the server is completely unaware that the attack has been. This is called a man-in-the-middle attack.

A man-in-the-middle attack (MITM attack) refers to hackers intercepting and tampering with communication data in the network. Also divided into passive mitm and active mitm, passive MITM only steal communication data without modification, and active MITM improper can steal data, also will tamper with communication data. The most common man-in-the-middle attacks often take place on public WiFi or public routes, and it's interesting to ask me privately, not a demo.

Now you can see how certificate locking improves security, avoids man-in-the-middle attacks, and uses a simple flowchart to illustrate:

It is not hard to see that a certificate lock can effectively avoid a man-in-the-middle attack.

Disadvantages of certificate Locking

Certificate locking Despite high security, this increase in security sacrifices flexibility. Once the certificate changes, our client must also be upgraded, in addition, our server has to be compatible with the previous client to make some compromises or to directly deactivate the previous client, which is not so friendly to developers and users.

But in fact, in rare cases we change the certificate. Therefore, if the product security requirements are relatively high or start a certificate lock it.

Use a certificate issued by an Android-approved certification authority

Some students may be curious to use HTTPS in their own company, but there is no code to write the binding certificate in the client code? Take the code that accesses GitHub as an example:

 Public void LoadData() {Retrofit Retrofit =NewRetrofit.builder (). BASEURL ("https://api.github.com/"). build ();        Githubapi API = Retrofit.create (Githubapi.class);        Call<responsebody> call = Api.contributorsbysimplegetcall (Musername, Mrepo); Call.enqueue (NewCallback<responsebody> () {@Override             Public void Onresponse(call<responsebody> call, response<responsebody> Response) {//Handle Response}@Override             Public void onfailure(call<responsebody> call, Throwable t) {//Handle Failure}        }); }

In the article on how HTTPS works we have said that Android has helped us provision more than 150 certificates, which you can see in the credentials of settings---security---in Windows, You can open certmgr.msc in the command line to open the Certificate Manager, where you can see the certificate for Windows presets. It is now clear that the reason for the absence of a built-in certificate is that the certificate that we use for our service is a certificate purchased from an Android-approved certificate authority, which is already built into Android, and by default, Retrofit 2.0 relies on Okhttp 3.0 is to trust them so that they can be accessed directly without having to set anything on the client.

Use a certificate or self-signed certificate issued by a certification authority other than an android-approved

After all, the purchase of a certificate is money, and now there are few free certificates, so using a self-signed certificate is another common way. What is a self-signed certificate? The so-called self-signed certificate is the certificate that is issued to itself without a trusted certificate Authority (hereinafter, I will also classify a certificate issued by a non-Android-recognized certification authority as a self-signed certificate). The most typical is the 12306 train ticket, the use of the certificate is not issued by a trusted certification authority, but its srca (medium-Iron digital certificate Certification Center, referred to as the iron CA, it is the railway itself to engage in the organization, so the equivalent of their own to issue a certificate) issued certificates, such as:

SSL certificates fall into three categories:
1. Certificates issued by Android-accredited certification authorities or institutions affiliated with the structure, such as Symantec,go Daddy, are about 150 or more. More on your own in the phone "settings--security--trust credentials" in view

2. No certificate issued by Android-approved certificate
3. Self-issued certificates

Of these three types of certificates, only the first one does not appear safe in use and does not throw an exception.

Because we are using a self-signed certificate, the client does not trust the server and throws an exception: javax.net.ssl.SSLHandshakeException: . To do this, we need to customize the Trust processor (TrustManager) to replace the system's default trust processor. This will make it possible for us to use a custom certificate issued by a certificate authority that is said or not recognized by Android.

There are two scenarios for usage scenarios: one is that the client does not need a built-in certificate in the case of low security requirements, and the other is a built-in certificate for the client.
I'll show you some of these issues in both cases below.

Client does not have a built-in certificate

We know that because we are using self-signed certificates, so we need to customize TrustManager, so many developers of the processing strategy is very simple and rude: Let the client do not verify the server certificate, its implementation code is as follows:

 Public StaticSslsocketfactorygetsslsocketfactory()throwsException {//Create a certificate trust manager that does not validate the certificate chain.         Finaltrustmanager[] Trustallcerts =Newtrustmanager[]{NewX509trustmanager () {@Override             Public void checkclienttrusted(java.security.cert.x509certificate[] chain, String authtype)throwsCertificateexception {}@Override             Public void checkservertrusted(java.security.cert.x509certificate[] chain, String authtype)throwsCertificateexception {}@Override             PublicJava.security.cert.x509certificate[]getacceptedissuers() {return Newjava.security.cert.x509certificate[0]; }        }};//Install the All-trusting trust manager        FinalSslcontext Sslcontext = sslcontext.getinstance ("TLS"); Sslcontext.init (NULL, Trustallcerts,NewJava.security.SecureRandom ());//Create an SSL socket factory with our All-trusting manager        returnSslcontext. Getsocketfactory (); }//Using custom Sslsocketfactory  Private void Onhttps(Okhttpclient.builder Builder) {Try{builder.sslsocketfactory (Getsslsocketfactory ()). Hostnameverifier (Org.apache.http.conn.ssl.SSLSocketFactory.AL        Low_all_hostname_verifier); }Catch(Exception e)        {E.printstacktrace (); }    }

The code above is not easy to apply in the actual project, unless you can tolerate his harm. Why do you say that? Keep looking down.

In the code above, we did not implement the x509trustmanager of the three cores in our own implementation (mainly without checkServerTrusted() validating the certificate), which is equivalent to ignoring the verification server certificate directly. Therefore, the HTTPS link can be established regardless of the server's certificate.

Seems to solve our problems, but in fact, it brings greater harm. At this point, although the HTTPS connection can be established, but invisible among the people attack opened a door. At this point, the hacker can completely intercept our HTTPS request, and then use a forged certificate to impersonate the real service side of the digital certificate, because the client does not verify the certificate (also can not determine whether the server is normal or fake), so that the client and the hacker's servers to establish a connection. This is equivalent to you think you are opposite is a beautiful woman, but did not think has been switched, think "Civet Cat for Prince" on the understanding. (For those of you who don't understand this, see the example in Certificate locking.) )

So how to avoid it? We need to rewrite the method in the custom TrustManager, checkServerTrusted() and in the method commander to validate the book, the perfect code is as follows:

     Public StaticSslsocketfactorygetsslsocketfactory()throwsException {//Create a trust manager that does not validate certificate chains        Finaltrustmanager[] Trustallcerts =Newtrustmanager[]{NewX509trustmanager () {//The public key in the certificate             Public Static FinalString Pub_key ="3082010a0282010100d52ff5dd432b3a05113ec1a7065fa5a80308810e4e181cf14f7598c8d553cccb7d5111fdcdb55f6ee84fc92cd594adc124 5a9c4cd41cbe407a919c5b4d4a37a012f8834df8cfe947c490464602fc05c18960374198336ba1c2e56d2e984bdfb8683610520e417a1a9a5053a1045 7355cf45878612f04bb134e3d670cf96c6e598fd0c693308fe3d084a0a91692bbd9722f05852f507d910b782db4ab13a92a7df814ee4304dccdad1b76 6bb671b6f8de578b7f27e76a2000d8d9e6b429d4fef8ffaa4e8037e167a2ce48752f1435f08923ed7e2dafef52ff30fef9ab66fdb556a82b257443ba3 0a93fda7a0af20418aa0b45403a2f829ea6e4b8ddbb9987f1bf0203010001 ";@Override             Public void checkclienttrusted(java.security.cert.x509certificate[] chain, String authtype)throwsCertificateexception {}//client and verifies the validity of the SSL certificate            @Override             Public void checkservertrusted(java.security.cert.x509certificate[] chain, String authtype)throwscertificateexception {if(Chain = =NULL) {Throw NewIllegalArgumentException ("checkservertrusted:x509certificate Array IsNull"); }if(! (Chain.length >0)) {Throw NewIllegalArgumentException ("Checkservertrusted:x509certificate is empty"); }if(! (NULL! = AuthType && authtype.equalsignorecase ("RSA"))) {Throw NewCertificateexception ("Checkservertrusted:authtype is not RSA"); }//Perform Customary SSL/TLS checks                Try{Trustmanagerfactory TMF = trustmanagerfactory.getinstance ("X509"); Tmf.init ((KeyStore)NULL); for(TrustManager trustManager:tmf.getTrustManagers ())                    {(X509trustmanager) trustmanager). checkservertrusted (chain, authtype); }                }Catch(Exception e) {Throw NewCertificateexception (e); }//Hack Ahead:biginteger and ToString (). We know a DER encoded public Key begins                //With 0x30 (ASN.1 SEQUENCE and constructed), so there are no leading 0x00 to drop.Rsapublickey PubKey = (rsapublickey) chain[0].getpublickey (); String encoded =NewBigInteger (1 / * Positive * /, pubkey.getencoded ()). ToString ( -);//Pin it!                Final BooleanExpected = pub_key.equalsignorecase (encoded);if(!expected) {Throw NewCertificateexception ("checkservertrusted:expected public key:"+ Pub_key +", got public key:"+ encoded); }            }@Override             PublicJava.security.cert.x509certificate[]getacceptedissuers() {return Newjava.security.cert.x509certificate[0]; }        }};//Install the All-trusting trust manager        FinalSslcontext Sslcontext = sslcontext.getinstance ("TLS"); Sslcontext.init (NULL, Trustallcerts,NewJava.security.SecureRandom ());//Create an SSL socket factory with our All-trusting manager        returnSslcontext. Getsocketfactory (); }

Where Pub_key is the public key in our certificate, you can extract it yourself from your own certificate. We see in the checkServerTrusted() method that we use the public key information of the certificate to confirm the authenticity of the certificate, and if the validation fails, the request is interrupted. Of course, the validity of the certificate will be more perfect, the implementation is relatively simple, here do not explain.

In addition to the above checkServerTrusted() way of implementing certificate validation, we can also use retrofit in Certificatepinner to achieve certificate locking, the same can achieve our goal.

Client built-in certificate

If we are using a self-signed certificate, how can the retrofit in the client be set up? The key is the TrustManager we mentioned above. Using a self-signed certificate in retrofit is roughly the following steps:

    1. To add a certificate to the project
    2. Custom trust Manager TrustManager
    3. Replace the system default trust manager with a custom TrustManager

We follow the steps to explain.

Add a certificate to the project

For example, now that we have a certificate media.bks, you first need to put it in the Res/raw directory, of course, you can put in the assets directory.

We know that Java natively supports the certificate format JKS, but unfortunately the JKS format is not supported in Android, but requires a certificate in BKS format. So we need to convert the JKS certificate into a BKS format certificate, about JKS to BKS no longer focus on this article

Custom TrustManager

Unlike above, this requires the loading of a local certificate, as shown in the code:

 protected StaticSslsocketfactorygetsslsocketfactory(Context context,int[] certificates) {if(Context = =NULL) {Throw NewNullPointerException ("context = = NULL"); }//certificatefactory used for certificate generationCertificatefactory certificatefactory;Try{certificatefactory = Certificatefactory.getinstance (" the");//create a KeyStore containing our trusted CAsKeyStore KeyStore = keystore.getinstance (Keystore.getdefaulttype ()); Keystore.load (NULL,NULL); for(inti =0; i < certificates.length; i++) {//Read local certificateInputStream is= Context.getresources (). Openrawresource (Certificates[i]); Keystore.setcertificateentry (String.valueof (i), certificatefactory.generatecertificate ( is));if( is!=NULL) { is. Close (); }            }//create a TrustManager that trusts the CAs in our KeyStoreTrustmanagerfactory trustmanagerfactory = trustmanagerfactory.getinstance (trustmanagerfactory.getdefaultalgorithm            ()); Trustmanagerfactory.init (KeyStore);//create an Sslcontext the uses our TrustManagerSslcontext Sslcontext = sslcontext.getinstance ("TLS"); Sslcontext.init (NULL, Trustmanagerfactory.gettrustmanagers (),NewSecureRandom ());returnSslcontext.getsocketfactory (); }Catch(Exception e) {        }return NULL; }
Replace the system default trust manager with a custom TrustManager
   privatevoidonHttpCertficates(OkHttpClient.Builder builder) {        intnewint[]{R.raw.media};        builder.socketFactory(getSSLSocketFactory(AppContext.context(), certficates));    }

This allows the client to use a self-signed certificate. It is not hard to find that the key to using a certificate issued by a non-Android-certified certification authority is to modify the Sslcontext-TrustManager in Android so that our signatures can be verified.

Temporary

This article briefly introduces the use of certificate locking, principles and advantages and disadvantages, and then the client using a custom certificate in some of the points are introduced, I hope to help you build a secure Android client.

Also, in most cases, I recommend using certificate locking to improve security. For two-way certificate verification, there is time to add.

How to use HTTPS correctly in the rapid development series--retrofit?

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.