197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes/* 297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * Copyright (C) 2010 Google Inc. 397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * 497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * you may not use this file except in compliance with the License. 697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * You may obtain a copy of the License at 797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * 897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * 1097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * Unless required by applicable law or agreed to in writing, software 1197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 1297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * See the License for the specific language governing permissions and 1497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * limitations under the License. 1597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes */ 1697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes 1797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughespackage benchmarks.regression; 1897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes 1997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport com.google.caliper.Param; 2097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport com.google.caliper.Runner; 2197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport com.google.caliper.SimpleBenchmark; 2297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport java.io.ByteArrayInputStream; 2397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport java.net.URL; 2497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport java.security.Principal; 2597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport java.security.cert.Certificate; 2697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport java.security.cert.CertificateFactory; 2797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport javax.net.ssl.HostnameVerifier; 2897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport javax.net.ssl.HttpsURLConnection; 2997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport javax.net.ssl.SSLSession; 3097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport javax.net.ssl.SSLSessionContext; 3197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes 3297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes/** 3397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * This benchmark makes a real HTTP connection to a handful of hosts and 3497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * captures the served certificates as a byte array. It then verifies each 3597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * certificate in the benchmark loop, being careful to convert from the 3697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * byte[] to the certificate each time. Otherwise the certificate class 3797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * caches previous results which skews the results of the benchmark: In practice 3897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * each certificate instance is verified once and then released. 3997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes */ 4097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughespublic final class HostnameVerifierBenchmark extends SimpleBenchmark { 4197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes 4297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes @Param({"android.clients.google.com", 4397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes "m.google.com", 4497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes "www.google.com", 4597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes "www.amazon.com", 4697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes "www.ubs.com"}) String host; 4797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes 4897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes private String hostname; 4997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes private HostnameVerifier hostnameVerifier; 5097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes private byte[][] encodedCertificates; 5197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes 5297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes @Override protected void setUp() throws Exception { 5397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes URL url = new URL("https", host, "/"); 5497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier(); 5597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); 5697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes connection.setHostnameVerifier(new HostnameVerifier() { 5797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public boolean verify(String hostname, SSLSession sslSession) { 5897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes try { 5997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes encodedCertificates = certificatesToBytes(sslSession.getPeerCertificates()); 6097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } catch (Exception e) { 6197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new RuntimeException(e); 6297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 6397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes HostnameVerifierBenchmark.this.hostname = hostname; 6497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes return true; 6597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 6697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes }); 6797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes connection.getInputStream(); 6897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes connection.disconnect(); 6997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 7097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes 7197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public void timeVerify(int reps) throws Exception { 7297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes for (int i = 0; i < reps; i++) { 7397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes final Certificate[] certificates = bytesToCertificates(encodedCertificates); 7497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes FakeSSLSession sslSession = new FakeSSLSession() { 7597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes @Override public Certificate[] getPeerCertificates() { 7697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes return certificates; 7797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 7897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes }; 7997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes hostnameVerifier.verify(hostname, sslSession); 8097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 8197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 8297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes 8397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes private byte[][] certificatesToBytes(Certificate[] certificates) throws Exception { 8497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes byte[][] result = new byte[certificates.length][]; 8597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes for (int i = 0, certificatesLength = certificates.length; i < certificatesLength; i++) { 8697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes result[i] = certificates[i].getEncoded(); 8797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 8897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes return result; 8997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 9097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes 9197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes private Certificate[] bytesToCertificates(byte[][] encodedCertificates) throws Exception { 9297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); 9397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes Certificate[] result = new Certificate[encodedCertificates.length]; 9497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes for (int i = 0; i < encodedCertificates.length; i++) { 9597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes result[i] = certificateFactory.generateCertificate( 9697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes new ByteArrayInputStream(encodedCertificates[i])); 9797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 9897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes return result; 9997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 10097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes 10197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes private static class FakeSSLSession implements SSLSession { 10297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public int getApplicationBufferSize() { 10397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 10497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 10597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public String getCipherSuite() { 10697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 10797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 10897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public long getCreationTime() { 10997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 11097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 11197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public byte[] getId() { 11297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 11397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 11497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public long getLastAccessedTime() { 11597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 11697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 11797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public Certificate[] getLocalCertificates() { 11897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 11997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 12097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public Principal getLocalPrincipal() { 12197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 12297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 12397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public int getPacketBufferSize() { 12497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 12597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 12697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public javax.security.cert.X509Certificate[] getPeerCertificateChain() { 12797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 12897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 12997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public Certificate[] getPeerCertificates() { 13097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 13197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 13297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public String getPeerHost() { 13397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 13497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 13597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public int getPeerPort() { 13697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 13797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 13897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public Principal getPeerPrincipal() { 13997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 14097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 14197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public String getProtocol() { 14297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 14397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 14497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public SSLSessionContext getSessionContext() { 14597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 14697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 14797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public Object getValue(String name) { 14897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 14997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 15097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public String[] getValueNames() { 15197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 15297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 15397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public void invalidate() { 15497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 15597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 15697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public boolean isValid() { 15797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 15897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 15997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public void putValue(String name, Object value) { 16097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 16197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 16297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public void removeValue(String name) { 16397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes throw new UnsupportedOperationException(); 16497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 16597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 16697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes 16797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes public static void main(String[] args) { 16897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes Runner.main(HostnameVerifierBenchmark.class, args); 16997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes } 17097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes} 171