1.Https knowledge

1.1 Differences between HTTP and HTTPS

Data transmitted through HTTP is unencrypted, that is, plaintext. Therefore, it is very insecure to use HTTP to transmit private information. To ensure that private data can be encrypted, Netscape designed Secure Sockets Layer (SSL) to encrypt data transmitted through HTTP. HTTPS was born. To put it simply, HTTPS is a network protocol that uses SSL and HTTP to encrypt transmission and authenticate identities. It is more secure than HTTP.

The main differences between HTTPS and HTTP are as follows:

  • HTTPS requires you to apply for a certificate from a CA. Generally, there are few free certificates, so a certain cost is required.

  • HTTP is a hypertext transmission protocol, and information is transmitted in plain text. HTTPS is a secure SSL encryption transmission protocol.

  • HTTP and HTTPS use completely different connections and use different ports, the former 80 and the latter 443.

  • HTTP connections are simple and stateless; HTTPS is a network protocol that uses SSL and HTTP to encrypt transmission and authenticate identity. It is more secure than HTTP.

1.2 Advantages of Https

  • Authenticate users and servers to ensure that data is sent to the correct clients and servers; (Certificate verification)

  • Encrypt data to prevent it from being stolen; (encryption)

  • Maintain data integrity and ensure that data is not changed during transmission. (Abstract Algorithm)

2. Use a self-signed certificate in Okhttp

Websites that support HTTPS are issued by the Certificate Authority (CA). However, the Certificate issued by the CA requires a fee and the validity period is limited. The Certificate must be renewed when it expires. Otherwise the link is untrusted by default and cannot be accessed directly through okHttp.

However, you can use the JDK to generate a self-signed certificate using keytool.exe and use the certificate content. The message “not secure” will also appear, but we can access the link through okHTTP.

2.1 Use of self-issued documents

Place the certificate file in assets (or in another directory, as long as it can be read correctly) and sslSocketFactory() adds the certificate information when creating the OkhttpClient object.

private SSLContext getSLLContext() {
        SSLContext sslContext = null;
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            InputStream certificate = mContext.getAssets().open("gdroot-g2.crt");
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            String certificateAlias = Integer.toString(0);
            keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
            sslContext = SSLContext.getInstance("TLS");
            final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return sslContext;
    }
Copy the code

As you can see from the above code, the certificate information is read through InputStream, so to avoid packaging the certificate file into APK, we can simply place the certificate file content in a String and stream the String.

When using OKHTTP, set it to sslSocketFactory.

OkHttpClient httpClient = new OkHttpClient().newBuilder()
                .sslSocketFactory(getSLLContext().getSocketFactory())
                .build();
Copy the code

2.2 Trust All Certificates

By adding a certificate, the client can access the Https server. However, if the server changes the certificate, the client needs to replace the Https certificate accordingly. Otherwise, data cannot be obtained through normal interaction. We can customize X509TrustManager to avoid all certificate detection and realize the purpose of trusting all certificates.

 private OkHttpClient getHttpsClient() { OkHttpClient.Builder okhttpClient = new OkHttpClient().newBuilder(); / / trust all server address okhttpClient. HostnameVerifier (newHostnameVerifier() {@override public Boolean verify(String s, SSLSession SSLSession) {// Set totrue
                return true; }}); TrustManager[] trustAllCerts = new TrustManager[] {newX509TrustManager() {
            @Override
            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] x509Certificates,
                    String s) throws java.security.cert.CertificateException {
            }

            @Override
            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] x509Certificates,
                    String s) throws java.security.cert.CertificateException {
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                returnnew java.security.cert.X509Certificate[] {}; }}}; try { SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); / / for OkHttpClient sslSocketFactory OkHttpClient. SslSocketFactory (sslContext. GetSocketFactory ()); } catch (Exception e) { e.printStackTrace(); }return okhttpClient.build();
    }
Copy the code

Create an X509TrustManager object and implement the methods in it. Since X509TrustManager is a generic certificate format, you just need to get the format. Finally init the security protocol and put it into OKHTTP’s sslSocketFactory. Since Retrofit is just a wrapper around the Okhttp network interface, in practice this approach also works in Retrofit.