/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package benchmarks.regression; import com.google.caliper.Param; import com.google.caliper.Runner; import com.google.caliper.SimpleBenchmark; import java.io.ByteArrayInputStream; import java.net.URL; import java.security.Principal; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSessionContext; /** * This benchmark makes a real HTTP connection to a handful of hosts and * captures the served certificates as a byte array. It then verifies each * certificate in the benchmark loop, being careful to convert from the * byte[] to the certificate each time. Otherwise the certificate class * caches previous results which skews the results of the benchmark: In practice * each certificate instance is verified once and then released. */ public final class HostnameVerifierBenchmark extends SimpleBenchmark { @Param({"android.clients.google.com", "m.google.com", "www.google.com", "www.amazon.com", "www.ubs.com"}) String host; private String hostname; private HostnameVerifier hostnameVerifier; private byte[][] encodedCertificates; @Override protected void setUp() throws Exception { URL url = new URL("https", host, "/"); hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier(); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setHostnameVerifier(new HostnameVerifier() { public boolean verify(String hostname, SSLSession sslSession) { try { encodedCertificates = certificatesToBytes(sslSession.getPeerCertificates()); } catch (Exception e) { throw new RuntimeException(e); } HostnameVerifierBenchmark.this.hostname = hostname; return true; } }); connection.getInputStream(); connection.disconnect(); } public void timeVerify(int reps) throws Exception { for (int i = 0; i < reps; i++) { final Certificate[] certificates = bytesToCertificates(encodedCertificates); FakeSSLSession sslSession = new FakeSSLSession() { @Override public Certificate[] getPeerCertificates() { return certificates; } }; hostnameVerifier.verify(hostname, sslSession); } } private byte[][] certificatesToBytes(Certificate[] certificates) throws Exception { byte[][] result = new byte[certificates.length][]; for (int i = 0, certificatesLength = certificates.length; i < certificatesLength; i++) { result[i] = certificates[i].getEncoded(); } return result; } private Certificate[] bytesToCertificates(byte[][] encodedCertificates) throws Exception { CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); Certificate[] result = new Certificate[encodedCertificates.length]; for (int i = 0; i < encodedCertificates.length; i++) { result[i] = certificateFactory.generateCertificate( new ByteArrayInputStream(encodedCertificates[i])); } return result; } private static class FakeSSLSession implements SSLSession { public int getApplicationBufferSize() { throw new UnsupportedOperationException(); } public String getCipherSuite() { throw new UnsupportedOperationException(); } public long getCreationTime() { throw new UnsupportedOperationException(); } public byte[] getId() { throw new UnsupportedOperationException(); } public long getLastAccessedTime() { throw new UnsupportedOperationException(); } public Certificate[] getLocalCertificates() { throw new UnsupportedOperationException(); } public Principal getLocalPrincipal() { throw new UnsupportedOperationException(); } public int getPacketBufferSize() { throw new UnsupportedOperationException(); } public javax.security.cert.X509Certificate[] getPeerCertificateChain() { throw new UnsupportedOperationException(); } public Certificate[] getPeerCertificates() { throw new UnsupportedOperationException(); } public String getPeerHost() { throw new UnsupportedOperationException(); } public int getPeerPort() { throw new UnsupportedOperationException(); } public Principal getPeerPrincipal() { throw new UnsupportedOperationException(); } public String getProtocol() { throw new UnsupportedOperationException(); } public SSLSessionContext getSessionContext() { throw new UnsupportedOperationException(); } public Object getValue(String name) { throw new UnsupportedOperationException(); } public String[] getValueNames() { throw new UnsupportedOperationException(); } public void invalidate() { throw new UnsupportedOperationException(); } public boolean isValid() { throw new UnsupportedOperationException(); } public void putValue(String name, Object value) { throw new UnsupportedOperationException(); } public void removeValue(String name) { throw new UnsupportedOperationException(); } } public static void main(String[] args) { Runner.main(HostnameVerifierBenchmark.class, args); } }