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.Param; 20 import com.google.caliper.Runner; 21 import com.google.caliper.SimpleBenchmark; 22 import java.io.ByteArrayInputStream; 23 import java.net.URL; 24 import java.security.Principal; 25 import java.security.cert.Certificate; 26 import java.security.cert.CertificateFactory; 27 import javax.net.ssl.HostnameVerifier; 28 import javax.net.ssl.HttpsURLConnection; 29 import javax.net.ssl.SSLSession; 30 import javax.net.ssl.SSLSessionContext; 31 32 /** 33 * This benchmark makes a real HTTP connection to a handful of hosts and 34 * captures the served certificates as a byte array. It then verifies each 35 * certificate in the benchmark loop, being careful to convert from the 36 * byte[] to the certificate each time. Otherwise the certificate class 37 * caches previous results which skews the results of the benchmark: In practice 38 * each certificate instance is verified once and then released. 39 */ 40 public final class HostnameVerifierBenchmark extends SimpleBenchmark { 41 42 @Param({"android.clients.google.com", 43 "m.google.com", 44 "www.google.com", 45 "www.amazon.com", 46 "www.ubs.com"}) String host; 47 48 private String hostname; 49 private HostnameVerifier hostnameVerifier; 50 private byte[][] encodedCertificates; 51 52 @Override 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 public static void main(String[] args) { 168 Runner.main(HostnameVerifierBenchmark.class, args); 169 } 170 } 171