Home | History | Annotate | Download | only in regression
      1 /*
      2  * Copyright (C) 2010 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package benchmarks.regression;
     18 
     19 import com.google.caliper.BeforeExperiment;
     20 import com.google.caliper.Param;
     21 import java.io.ByteArrayInputStream;
     22 import java.net.URL;
     23 import java.security.Principal;
     24 import java.security.cert.Certificate;
     25 import java.security.cert.CertificateFactory;
     26 import javax.net.ssl.HostnameVerifier;
     27 import javax.net.ssl.HttpsURLConnection;
     28 import javax.net.ssl.SSLSession;
     29 import javax.net.ssl.SSLSessionContext;
     30 
     31 /**
     32  * This benchmark makes a real HTTP connection to a handful of hosts and
     33  * captures the served certificates as a byte array. It then verifies each
     34  * certificate in the benchmark loop, being careful to convert from the
     35  * byte[] to the certificate each time. Otherwise the certificate class
     36  * caches previous results which skews the results of the benchmark: In practice
     37  * each certificate instance is verified once and then released.
     38  */
     39 public final class HostnameVerifierBenchmark {
     40 
     41     @Param({"android.clients.google.com",
     42             "m.google.com",
     43             "www.google.com",
     44             "www.amazon.com",
     45             "www.ubs.com"}) String host;
     46 
     47     private String hostname;
     48     private HostnameVerifier hostnameVerifier;
     49     private byte[][] encodedCertificates;
     50 
     51     @BeforeExperiment
     52     protected void setUp() throws Exception {
     53         URL url = new URL("https", host, "/");
     54         hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
     55         HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
     56         connection.setHostnameVerifier(new HostnameVerifier() {
     57             public boolean verify(String hostname, SSLSession sslSession) {
     58                 try {
     59                     encodedCertificates = certificatesToBytes(sslSession.getPeerCertificates());
     60                 } catch (Exception e) {
     61                     throw new RuntimeException(e);
     62                 }
     63                 HostnameVerifierBenchmark.this.hostname = hostname;
     64                 return true;
     65             }
     66         });
     67         connection.getInputStream();
     68         connection.disconnect();
     69     }
     70 
     71     public void timeVerify(int reps) throws Exception {
     72         for (int i = 0; i < reps; i++) {
     73             final Certificate[] certificates = bytesToCertificates(encodedCertificates);
     74             FakeSSLSession sslSession = new FakeSSLSession() {
     75                 @Override public Certificate[] getPeerCertificates() {
     76                     return certificates;
     77                 }
     78             };
     79             hostnameVerifier.verify(hostname, sslSession);
     80         }
     81     }
     82 
     83     private byte[][] certificatesToBytes(Certificate[] certificates) throws Exception {
     84         byte[][] result = new byte[certificates.length][];
     85         for (int i = 0, certificatesLength = certificates.length; i < certificatesLength; i++) {
     86             result[i] = certificates[i].getEncoded();
     87         }
     88         return result;
     89     }
     90 
     91     private Certificate[] bytesToCertificates(byte[][] encodedCertificates) throws Exception {
     92         CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
     93         Certificate[] result = new Certificate[encodedCertificates.length];
     94         for (int i = 0; i < encodedCertificates.length; i++) {
     95             result[i] = certificateFactory.generateCertificate(
     96                 new ByteArrayInputStream(encodedCertificates[i]));
     97         }
     98         return result;
     99     }
    100 
    101     private static class FakeSSLSession implements SSLSession {
    102         public int getApplicationBufferSize() {
    103             throw new UnsupportedOperationException();
    104         }
    105         public String getCipherSuite() {
    106             throw new UnsupportedOperationException();
    107         }
    108         public long getCreationTime() {
    109             throw new UnsupportedOperationException();
    110         }
    111         public byte[] getId() {
    112             throw new UnsupportedOperationException();
    113         }
    114         public long getLastAccessedTime() {
    115             throw new UnsupportedOperationException();
    116         }
    117         public Certificate[] getLocalCertificates() {
    118             throw new UnsupportedOperationException();
    119         }
    120         public Principal getLocalPrincipal() {
    121             throw new UnsupportedOperationException();
    122         }
    123         public int getPacketBufferSize() {
    124             throw new UnsupportedOperationException();
    125         }
    126         public javax.security.cert.X509Certificate[] getPeerCertificateChain() {
    127             throw new UnsupportedOperationException();
    128         }
    129         public Certificate[] getPeerCertificates() {
    130             throw new UnsupportedOperationException();
    131         }
    132         public String getPeerHost() {
    133             throw new UnsupportedOperationException();
    134         }
    135         public int getPeerPort() {
    136             throw new UnsupportedOperationException();
    137         }
    138         public Principal getPeerPrincipal() {
    139             throw new UnsupportedOperationException();
    140         }
    141         public String getProtocol() {
    142             throw new UnsupportedOperationException();
    143         }
    144         public SSLSessionContext getSessionContext() {
    145             throw new UnsupportedOperationException();
    146         }
    147         public Object getValue(String name) {
    148             throw new UnsupportedOperationException();
    149         }
    150         public String[] getValueNames() {
    151             throw new UnsupportedOperationException();
    152         }
    153         public void invalidate() {
    154             throw new UnsupportedOperationException();
    155         }
    156         public boolean isValid() {
    157             throw new UnsupportedOperationException();
    158         }
    159         public void putValue(String name, Object value) {
    160             throw new UnsupportedOperationException();
    161         }
    162         public void removeValue(String name) {
    163             throw new UnsupportedOperationException();
    164         }
    165     }
    166 }
    167