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