HTTPCLIENT-614: allow different strategies when checking CN of x509 cert

* Test coverage

Contributed by Julius Davies <juliusdavies at gmail.com>
Reviewed by Oleg Kalnichevski

git-svn-id: https://svn.apache.org/repos/asf/jakarta/httpcomponents/httpclient/trunk@487346 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2006-12-14 20:49:34 +00:00
parent dd9500e009
commit 81e5ce2d12
7 changed files with 1401 additions and 139 deletions

View File

@ -0,0 +1,434 @@
/*
* $HeadURL$
* $Revision$
* $Date$
*
* ====================================================================
*
* Copyright 2002-2004 The Apache Software Foundation
*
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.conn.ssl;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.io.InputStream;
import java.security.cert.Certificate;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
/**
* Interface for checking if a hostname matches the names stored inside the
* server's X.509 certificate. Implements javax.net.ssl.HostnameVerifier, but
* we don't actually use that interface. Instead we added some methods that
* take String parameters (instead of javax.net.ssl.HostnameVerifier's
* SSLSession). JUnit is a lot easier this way! :-)
* <p/>
* We provide the HostnameVerifier.DEFAULT, HostnameVerifier.STRICT, and
* HostnameVerifier.ALLOW_ALL implementations. But feel free to define
* your own implementation!
* <p/>
* Inspired by Sebastian Hauer's original StrictSSLProtocolSocketFactory in the
* HttpClient "contrib" repository.
*
* @author Julius Davies
* @author <a href="mailto:hauer@psicode.com">Sebastian Hauer</a>
* @since 8-Dec-2006
*/
public interface HostnameVerifier extends javax.net.ssl.HostnameVerifier {
boolean verify(String host, SSLSession session);
void verify(String host, SSLSocket ssl) throws IOException;
void verify(String host, X509Certificate cert) throws SSLException;
/**
* Checks to see if the supplied hostname matches any of the supplied CNs
* or "DNS" Subject-Alts. Most implementations only look at the first CN,
* and ignore any additional CNs. Most implementations do look at all of
* the "DNS" Subject-Alts. The CNs or Subject-Alts may contain wildcards
* according to RFC 2818.
*
* @param cns CN fields, in order, as extracted from the X.509
* certificate.
* @param subjectAlts Subject-Alt fields of type 2 ("DNS"), as extracted
* from the X.509 certificate.
* @param host The hostname to verify.
* @throws SSLException If verification failed.
*/
void verify(String host, String[] cns, String[] subjectAlts)
throws SSLException;
/**
* The DEFAULT HostnameVerifier works the same way as Curl and Firefox.
* <p/>
* The hostname must match either the first CN, or any of the subject-alts.
* A wildcard can occur in the CN, and in any of the subject-alts.
* <p/>
* The only difference between DEFAULT and STRICT is that a wildcard (such
* as "*.foo.com") with DEFAULT matches all subdomains, including
* "a.b.foo.com".
*/
public final static HostnameVerifier DEFAULT =
new AbstractVerifier() {
public final void verify(final String host, final String[] cns,
final String[] subjectAlts)
throws SSLException {
verify(host, cns, subjectAlts, false);
}
public final String toString() { return "DEFAULT"; }
};
/**
* The Strict HostnameVerifier works the same way as Sun Java 1.4, Sun
* Java 5, Sun Java 6-rc. It's also pretty close to IE6. This
* implementation appears to be compliant with RFC 2818 for dealing with
* wildcards.
* <p/>
* The hostname must match either the first CN, or any of the subject-alts.
* A wildcard can occur in the CN, and in any of the subject-alts. The
* one divergence from IE6 is how we only check the first CN. IE6 allows
* a match against any of the CNs present. We decided to follow in
* Sun Java 1.4's footsteps and only check the first CN. (If you need
* to check all the CN's, feel free to write your own implementation!).
* <p/>
* A wildcard such as "*.foo.com" matches only subdomains in the same
* level, for example "a.foo.com". It does not match deeper subdomains
* such as "a.b.foo.com".
*/
public final static HostnameVerifier STRICT =
new AbstractVerifier() {
public final void verify(final String host, final String[] cns,
final String[] subjectAlts)
throws SSLException {
verify(host, cns, subjectAlts, true);
}
public final String toString() { return "STRICT"; }
};
/**
* The ALLOW_ALL HostnameVerifier essentially turns hostname verification
* off. This implementation is a no-op, and never throws the SSLException.
*/
public final static HostnameVerifier ALLOW_ALL =
new AbstractVerifier() {
public final void verify(final String host, final String[] cns,
final String[] subjectAlts) {
// Allow everything - so never blowup.
}
public final String toString() { return "ALLOW_ALL"; }
};
abstract class AbstractVerifier implements HostnameVerifier {
/**
* This contains a list of 2nd-level domains that aren't allowed to
* have wildcards when combined with country-codes.
* For example: [*.co.uk].
* <p/>
* The [*.co.uk] problem is an interesting one. Should we just hope
* that CA's would never foolishly allow such a certificate to happen?
* Looks like we're the only implementation guarding against this.
* Firefox, Curl, Sun Java 1.4, 5, 6 don't bother with this check.
*/
private final static String[] BAD_COUNTRY_2LDS =
{ "ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info",
"lg", "ne", "net", "or", "org" };
static {
// Just in case developer forgot to manually sort the array. :-)
Arrays.sort(BAD_COUNTRY_2LDS);
}
AbstractVerifier() {}
public final void verify(String host, SSLSocket ssl)
throws IOException {
if(host == null) {
throw new NullPointerException("host to verify is null");
}
SSLSession session = ssl.getSession();
if(session == null) {
// In our experience this only happens under IBM 1.4.x when
// spurious (unrelated) certificates show up in the server'
// chain. Hopefully this will unearth the real problem:
InputStream in = ssl.getInputStream();
in.available();
/*
If you're looking at the 2 lines of code above because
you're running into a problem, you probably have two
options:
#1. Clean up the certificate chain that your server
is presenting (e.g. edit "/etc/apache2/server.crt"
or wherever it is your server's certificate chain
is defined).
OR
#2. Upgrade to an IBM 1.5.x or greater JVM, or switch
to a non-IBM JVM.
*/
// If ssl.getInputStream().available() didn't cause an
// exception, maybe at least now the session is available?
session = ssl.getSession();
if(session == null) {
// If it's still null, probably a startHandshake() will
// unearth the real problem.
ssl.startHandshake();
// Okay, if we still haven't managed to cause an exception,
// might as well go for the NPE. Or maybe we're okay now?
session = ssl.getSession();
}
}
Certificate[] certs = session.getPeerCertificates();
X509Certificate x509 = (X509Certificate) certs[0];
verify(host, x509);
}
public final boolean verify(String host, SSLSession session) {
try {
Certificate[] certs = session.getPeerCertificates();
X509Certificate x509 = (X509Certificate) certs[0];
verify(host, x509);
return true;
}
catch(SSLException e) {
return false;
}
}
public final void verify(String host, X509Certificate cert)
throws SSLException {
String[] cns = getCNs(cert);
String[] subjectAlts = getDNSSubjectAlts(cert);
verify(host, cns, subjectAlts);
}
public final void verify(final String host, final String[] cns,
final String[] subjectAlts,
final boolean strictWithSubDomains)
throws SSLException {
// Build the list of names we're going to check. Our DEFAULT and
// STRICT implementations of the HostnameVerifier only use the
// first CN provided. All other CNs are ignored.
// (Firefox, wget, curl, Sun Java 1.4, 5, 6 all work this way).
LinkedList names = new LinkedList();
if(cns != null && cns.length > 0 && cns[0] != null) {
names.add(cns[0]);
}
if(subjectAlts != null) {
for(int i = 0; i < subjectAlts.length; i++) {
if(subjectAlts[i] != null) {
names.add(subjectAlts[i]);
}
}
}
if(names.isEmpty()) {
String msg = "Certificate for <" + host + "> doesn't contain CN or DNS subjectAlt";
throw new SSLException(msg);
}
// StringBuffer for building the error message.
StringBuffer buf = new StringBuffer();
// We're can be case-insensitive when comparing the host we used to
// establish the socket to the hostname in the certificate.
String hostName = host.trim().toLowerCase();
boolean match = false;
for(Iterator it = names.iterator(); it.hasNext();) {
// Don't trim the CN, though!
String cn = (String) it.next();
cn = cn.toLowerCase();
// Store CN in StringBuffer in case we need to report an error.
buf.append(" <");
buf.append(cn);
buf.append('>');
if(it.hasNext()) {
buf.append(" OR");
}
// The CN better have at least two dots if it wants wildcard
// action. It also can't be [*.co.uk] or [*.co.jp] or
// [*.org.uk], etc...
boolean doWildcard = cn.startsWith("*.") &&
cn.lastIndexOf('.') >= 0 &&
acceptableCountryWildcard(cn);
if(doWildcard) {
match = hostName.endsWith(cn.substring(1));
if(match && strictWithSubDomains) {
// If we're in strict mode, then [*.foo.com] is not
// allowed to match [a.b.foo.com]
match = countDots(hostName) == countDots(cn);
}
} else {
match = hostName.equals(cn);
}
if(match) {
break;
}
}
if(!match) {
throw new SSLException("hostname in certificate didn't match: <" + host + "> !=" + buf);
}
}
public static boolean acceptableCountryWildcard(String cn) {
int cnLen = cn.length();
if(cnLen >= 7 && cnLen <= 9) {
// Look for the '.' in the 3rd-last position:
if(cn.charAt(cnLen - 3) == '.') {
// Trim off the [*.] and the [.XX].
String s = cn.substring(2, cnLen - 3);
// And test against the sorted array of bad 2lds:
int x = Arrays.binarySearch(BAD_COUNTRY_2LDS, s);
return x < 0;
}
}
return true;
}
public static String[] getCNs(X509Certificate cert) {
LinkedList cnList = new LinkedList();
/*
Sebastian Hauer's original StrictSSLProtocolSocketFactory used
getName() and had the following comment:
Parses a X.500 distinguished name for the value of the
"Common Name" field. This is done a bit sloppy right
now and should probably be done a bit more according to
<code>RFC 2253</code>.
I've noticed that toString() seems to do a better job than
getName() on these X500Principal objects, so I'm hoping that
addresses Sebastian's concern.
For example, getName() gives me this:
1.2.840.113549.1.9.1=#16166a756c6975736461766965734063756362632e636f6d
whereas toString() gives me this:
EMAILADDRESS=juliusdavies@cucbc.com
Looks like toString() even works with non-ascii domain names!
I tested it with "&#x82b1;&#x5b50;.co.jp" and it worked fine.
*/
String subjectPrincipal = cert.getSubjectX500Principal().toString();
StringTokenizer st = new StringTokenizer(subjectPrincipal, ",");
while(st.hasMoreTokens()) {
String tok = st.nextToken();
int x = tok.indexOf("CN=");
if(x >= 0) {
cnList.add(tok.substring(x + 3));
}
}
if(!cnList.isEmpty()) {
String[] cns = new String[cnList.size()];
cnList.toArray(cns);
return cns;
} else {
return null;
}
}
/**
* Extracts the array of SubjectAlt DNS names from an X509Certificate.
* Returns null if there aren't any.
* <p/>
* Note: Java doesn't appear able to extract international characters
* from the SubjectAlts. It can only extract international characters
* from the CN field.
* <p/>
* (Or maybe the version of OpenSSL I'm using to test isn't storing the
* international characters correctly in the SubjectAlts?).
*
* @param cert X509Certificate
* @return Array of SubjectALT DNS names stored in the certificate.
*/
public static String[] getDNSSubjectAlts(X509Certificate cert) {
LinkedList subjectAltList = new LinkedList();
Collection c = null;
try {
c = cert.getSubjectAlternativeNames();
}
catch(CertificateParsingException cpe) {
// Should probably log.debug() this?
cpe.printStackTrace();
}
if(c != null) {
Iterator it = c.iterator();
while(it.hasNext()) {
List list = (List) it.next();
int type = ((Integer) list.get(0)).intValue();
// If type is 2, then we've got a dNSName
if(type == 2) {
String s = (String) list.get(1);
subjectAltList.add(s);
}
}
}
if(!subjectAltList.isEmpty()) {
String[] subjectAlts = new String[subjectAltList.size()];
subjectAltList.toArray(subjectAlts);
return subjectAlts;
} else {
return null;
}
}
/**
* Counts the number of dots "." in a string.
* @param s string to count dots from
* @return number of dots
*/
public static int countDots(final String s) {
int count = 0;
for(int i = 0; i < s.length(); i++) {
if(s.charAt(i) == '.') {
count++;
}
}
return count;
}
}
}

View File

@ -34,16 +34,14 @@ import org.apache.http.conn.SecureSocketFactory;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
@ -54,8 +52,6 @@ import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
/**
* <p>
@ -156,6 +152,7 @@ public class SSLSocketFactory implements SecureSocketFactory {
private final SSLContext sslcontext;
private final javax.net.ssl.SSLSocketFactory socketfactory;
private HostnameVerifier hostnameVerifier = HostnameVerifier.DEFAULT;
public SSLSocketFactory(
String algorithm,
@ -206,8 +203,7 @@ public class SSLSocketFactory implements SecureSocketFactory {
public SSLSocketFactory() {
super();
this.sslcontext = null;
this.socketfactory = (javax.net.ssl.SSLSocketFactory)
javax.net.ssl.SSLSocketFactory.getDefault();
this.socketfactory = HttpsURLConnection.getDefaultSSLSocketFactory();
}
private static KeyManager[] createKeyManagers(final KeyStore keystore, final String password)
@ -261,155 +257,47 @@ public class SSLSocketFactory implements SecureSocketFactory {
if (params == null) {
throw new IllegalArgumentException("Parameters may not be null");
}
SSLSocket socket = (SSLSocket) this.socketfactory.createSocket();
SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket();
if (localAddress != null) {
socket.bind(new InetSocketAddress(localAddress, localPort));
sslSocket.bind(new InetSocketAddress(localAddress, localPort));
}
int timeout = HttpConnectionParams.getConnectionTimeout(params);
socket.connect(new InetSocketAddress(host, port), timeout);
verifyHostName( host, (SSLSocket) socket );
sslSocket.connect(new InetSocketAddress(host, port), timeout);
hostnameVerifier.verify(host, sslSocket);
// verifyHostName() didn't blowup - good!
return socket;
return sslSocket;
}
/**
* @see SecureSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
*/
public Socket createSocket(
Socket socket,
String host,
int port,
boolean autoClose)
throws IOException, UnknownHostException {
SSLSocket s = (SSLSocket) this.socketfactory.createSocket(
socket,
host,
port,
autoClose
final Socket socket,
final String host,
final int port,
final boolean autoClose
) throws IOException, UnknownHostException {
SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket(
socket,
host,
port,
autoClose
);
verifyHostName( host, (SSLSocket) socket );
hostnameVerifier.verify(host, sslSocket);
// verifyHostName() didn't blowup - good!
return s;
return sslSocket;
}
private static void verifyHostName( String host, SSLSocket ssl )
throws IOException {
if ( host == null ) {
throw new NullPointerException( "host to verify was null" );
}
SSLSession session = ssl.getSession();
if ( session == null ) {
// In our experience this only happens under IBM 1.4.x when
// spurious (unrelated) certificates show up in the server's chain.
// Hopefully this will unearth the real problem:
InputStream in = ssl.getInputStream();
in.available();
/*
If you're looking at the 2 lines of code above because you're
running into a problem, you probably have two options:
#1. Clean up the certificate chain that your server
is presenting (e.g. edit "/etc/apache2/server.crt" or
wherever it is your server's certificate chain is
defined).
OR
#2. Upgrade to an IBM 1.5.x or greater JVM, or switch to a
non-IBM JVM.
*/
// If ssl.getInputStream().available() didn't cause an exception,
// maybe at least now the session is available?
session = ssl.getSession();
if ( session == null ) {
// If it's still null, probably a startHandshake() will
// unearth the real problem.
ssl.startHandshake();
// Okay, if we still haven't managed to cause an exception,
// might as well go for the NPE. Or maybe we're okay now?
session = ssl.getSession();
}
}
Certificate[] certs = session.getPeerCertificates();
X509Certificate x509 = (X509Certificate) certs[ 0 ];
String cn = getCN( x509 );
if ( cn == null ) {
String subject = x509.getSubjectX500Principal().toString();
String msg = "certificate doesn't contain CN: " + subject;
throw new SSLException( msg );
}
// I'm okay with being case-insensitive when comparing the host we used
// to establish the socket to the hostname in the certificate.
// Don't trim the CN, though.
cn = cn.toLowerCase();
host = host.trim().toLowerCase();
boolean doWildcard = false;
if ( cn.startsWith( "*." ) ) {
// The CN better have at least two dots if it wants wildcard action,
// but can't be [*.co.uk] or [*.co.jp] or [*.org.uk], etc...
String withoutCountryCode = "";
if ( cn.length() >= 7 && cn.length() <= 9 ) {
withoutCountryCode = cn.substring( 2, cn.length() - 2 );
}
doWildcard = cn.lastIndexOf( '.' ) >= 0 &&
!"ac.".equals( withoutCountryCode ) &&
!"co.".equals( withoutCountryCode ) &&
!"com.".equals( withoutCountryCode ) &&
!"ed.".equals( withoutCountryCode ) &&
!"edu.".equals( withoutCountryCode ) &&
!"go.".equals( withoutCountryCode ) &&
!"gouv.".equals( withoutCountryCode ) &&
!"gov.".equals( withoutCountryCode ) &&
!"info.".equals( withoutCountryCode ) &&
!"lg.".equals( withoutCountryCode ) &&
!"ne.".equals( withoutCountryCode ) &&
!"net.".equals( withoutCountryCode ) &&
!"or.".equals( withoutCountryCode ) &&
!"org.".equals( withoutCountryCode );
// The [*.co.uk] problem is an interesting one. Should we just
// hope that CA's would never foolishly allow such a
// certificate to happen?
}
boolean match;
if ( doWildcard ) {
match = host.endsWith( cn.substring( 1 ) );
public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
if ( hostnameVerifier == null ) {
this.hostnameVerifier = HostnameVerifier.DEFAULT;
} else {
match = host.equals( cn );
}
if ( !match ) {
throw new SSLException( "hostname in certificate didn't match: <" + host + "> != <" + cn + ">" );
this.hostnameVerifier = hostnameVerifier;
}
}
private static String getCN( X509Certificate cert ) {
// Note: toString() seems to do a better job than getName()
//
// For example, getName() gives me this:
// 1.2.840.113549.1.9.1=#16166a756c6975736461766965734063756362632e636f6d
//
// whereas toString() gives me this:
// EMAILADDRESS=juliusdavies@cucbc.com
String subjectPrincipal = cert.getSubjectX500Principal().toString();
int x = subjectPrincipal.indexOf( "CN=" );
if ( x >= 0 ) {
int y = subjectPrincipal.indexOf( ',', x );
// If there are no more commas, then CN= is the last entry.
y = ( y >= 0 ) ? y : subjectPrincipal.length();
return subjectPrincipal.substring( x + 3, y );
} else {
return null;
}
public HostnameVerifier getHostnameVerifier() {
return hostnameVerifier;
}
}

View File

@ -0,0 +1,451 @@
/*
* $HeadURL$
* $Revision$
* $Date$
*
* ====================================================================
*
* Copyright 1999-2006 The Apache Software Foundation
*
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.conn.ssl;
/**
* Some X509 certificates to test against.
* <p/>
* Note: some of these certificates have Japanese Kanji in the "subjectAlt"
* field (UTF8). Not sure how realistic that is since international characters
* in DNS names usually get translated into ASCII using "xn--" style DNS
* entries. "xn--i8s592g.co.jp" is what FireFox actually uses when trying to
* find &#x82b1;&#x5b50;.co.jp. So would the CN in the certificate contain
* "xn--i8s592g.co.jp" in ASCII, or "&#x82b1;&#x5b50;.co.jp" in UTF8? (Both?)
*
* @author Julius Davies
* @since 11-Dec-2006
*/
public interface CertificatesToPlayWith {
/**
* CN=foo.com
*/
public final static byte[] X509_FOO = (
"-----BEGIN CERTIFICATE-----\n" +
"MIIERjCCAy6gAwIBAgIJAIz+EYMBU6aQMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE1MzE0MVoXDTI4MTEwNTE1MzE0MVowgaQx\n" +
"CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0\n" +
"IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl\n" +
"cnRpZmljYXRlczEQMA4GA1UEAxMHZm9vLmNvbTElMCMGCSqGSIb3DQEJARYWanVs\n" +
"aXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" +
"ggEBAMhjr5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2B\n" +
"lYho4O84X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRy\n" +
"zerA/ZtrlUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY\n" +
"07hNKXAb2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8\n" +
"BqnGd87xQU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiV\n" +
"JTxpTKqym93whYk93l3ocEe55c0CAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB\n" +
"hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE\n" +
"FJ8Ud78/OrbKOIJCSBYs2tDLXofYMB8GA1UdIwQYMBaAFHua2o+QmU5S0qzbswNS\n" +
"yoemDT4NMA0GCSqGSIb3DQEBBQUAA4IBAQC3jRmEya6sQCkmieULcvx8zz1euCk9\n" +
"fSez7BEtki8+dmfMXe3K7sH0lI8f4jJR0rbSCjpmCQLYmzC3NxBKeJOW0RcjNBpO\n" +
"c2JlGO9auXv2GDP4IYiXElLJ6VSqc8WvDikv0JmCCWm0Zga+bZbR/EWN5DeEtFdF\n" +
"815CLpJZNcYwiYwGy/CVQ7w2TnXlG+mraZOz+owr+cL6J/ZesbdEWfjoS1+cUEhE\n" +
"HwlNrAu8jlZ2UqSgskSWlhYdMTAP9CPHiUv9N7FcT58Itv/I4fKREINQYjDpvQcx\n" +
"SaTYb9dr5sB4WLNglk7zxDtM80H518VvihTcP7FHL+Gn6g4j5fkI98+S\n" +
"-----END CERTIFICATE-----\n").getBytes();
/**
* CN=&#x82b1;&#x5b50;.co.jp
*/
public final static byte[] X509_HANAKO = (
"-----BEGIN CERTIFICATE-----\n" +
"MIIESzCCAzOgAwIBAgIJAIz+EYMBU6aTMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE1NDIxNVoXDTI4MTEwNTE1NDIxNVowgakx\n" +
"CzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEUMBIGA1UEBwwLRm9yZXN0\n" +
"IEhpbGwxFzAVBgNVBAoMDmh0dHBjb21wb25lbnRzMRowGAYDVQQLDBF0ZXN0IGNl\n" +
"cnRpZmljYXRlczEVMBMGA1UEAwwM6Iqx5a2QLmNvLmpwMSUwIwYJKoZIhvcNAQkB\n" +
"FhZqdWxpdXNkYXZpZXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n" +
"MIIBCgKCAQEAyGOvloI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7PlpgpjU\n" +
"g4pNjYGViGjg7zhfbjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc8BQc\n" +
"wHf0ZHLN6sD9m2uVSp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTjHE5t\n" +
"7iu1JVjTuE0pcBvah2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindxOSAn\n" +
"AxK6q/wGqcZ3zvFBTcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfDHArD\n" +
"qUYxqJUlPGlMqrKb3fCFiT3eXehwR7nlzQIDAQABo3sweTAJBgNVHRMEAjAAMCwG\n" +
"CWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNV\n" +
"HQ4EFgQUnxR3vz86tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLS\n" +
"rNuzA1LKh6YNPg0wDQYJKoZIhvcNAQEFBQADggEBALJ27i3okV/KvlDp6KMID3gd\n" +
"ITl68PyItzzx+SquF8gahMh016NX73z/oVZoVUNdftla8wPUB1GwIkAnGkhQ9LHK\n" +
"spBdbRiCj0gMmLCsX8SrjFvr7cYb2cK6J/fJe92l1tg/7Y4o7V/s4JBe/cy9U9w8\n" +
"a0ctuDmEBCgC784JMDtT67klRfr/2LlqWhlOEq7pUFxRLbhpquaAHSOjmIcWnVpw\n" +
"9BsO7qe46hidgn39hKh1WjKK2VcL/3YRsC4wUi0PBtFW6ScMCuMhgIRXSPU55Rae\n" +
"UIlOdPjjr1SUNWGId1rD7W16Scpwnknn310FNxFMHVI0GTGFkNdkilNCFJcIoRA=\n" +
"-----END CERTIFICATE-----\n").getBytes();
/**
* CN=foo.com, subjectAlt=bar.com
*/
public final static byte[] X509_FOO_BAR = (
"-----BEGIN CERTIFICATE-----\n" +
"MIIEXDCCA0SgAwIBAgIJAIz+EYMBU6aRMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE1MzYyOVoXDTI4MTEwNTE1MzYyOVowgaQx\n" +
"CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0\n" +
"IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl\n" +
"cnRpZmljYXRlczEQMA4GA1UEAxMHZm9vLmNvbTElMCMGCSqGSIb3DQEJARYWanVs\n" +
"aXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" +
"ggEBAMhjr5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2B\n" +
"lYho4O84X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRy\n" +
"zerA/ZtrlUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY\n" +
"07hNKXAb2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8\n" +
"BqnGd87xQU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiV\n" +
"JTxpTKqym93whYk93l3ocEe55c0CAwEAAaOBkDCBjTAJBgNVHRMEAjAAMCwGCWCG\n" +
"SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E\n" +
"FgQUnxR3vz86tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuz\n" +
"A1LKh6YNPg0wEgYDVR0RBAswCYIHYmFyLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEA\n" +
"dQyprNZBmVnvuVWjV42sey/PTfkYShJwy1j0/jcFZR/ypZUovpiHGDO1DgL3Y3IP\n" +
"zVQ26uhUsSw6G0gGRiaBDe/0LUclXZoJzXX1qpS55OadxW73brziS0sxRgGrZE/d\n" +
"3g5kkio6IED47OP6wYnlmZ7EKP9cqjWwlnvHnnUcZ2SscoLNYs9rN9ccp8tuq2by\n" +
"88OyhKwGjJfhOudqfTNZcDzRHx4Fzm7UsVaycVw4uDmhEHJrAsmMPpj/+XRK9/42\n" +
"2xq+8bc6HojdtbCyug/fvBZvZqQXSmU8m8IVcMmWMz0ZQO8ee3QkBHMZfCy7P/kr\n" +
"VbWx/uETImUu+NZg22ewEw==\n" +
"-----END CERTIFICATE-----\n").getBytes();
/**
* CN=foo.com, subjectAlt=bar.com, subjectAlt=&#x82b1;&#x5b50;.co.jp
* (hanako.co.jp in kanji)
*/
public final static byte[] X509_FOO_BAR_HANAKO = (
"-----BEGIN CERTIFICATE-----\n" +
"MIIEajCCA1KgAwIBAgIJAIz+EYMBU6aSMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE1MzgxM1oXDTI4MTEwNTE1MzgxM1owgaQx\n" +
"CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0\n" +
"IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl\n" +
"cnRpZmljYXRlczEQMA4GA1UEAxMHZm9vLmNvbTElMCMGCSqGSIb3DQEJARYWanVs\n" +
"aXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" +
"ggEBAMhjr5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2B\n" +
"lYho4O84X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRy\n" +
"zerA/ZtrlUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY\n" +
"07hNKXAb2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8\n" +
"BqnGd87xQU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiV\n" +
"JTxpTKqym93whYk93l3ocEe55c0CAwEAAaOBnjCBmzAJBgNVHRMEAjAAMCwGCWCG\n" +
"SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E\n" +
"FgQUnxR3vz86tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuz\n" +
"A1LKh6YNPg0wIAYDVR0RBBkwF4IHYmFyLmNvbYIM6Iqx5a2QLmNvLmpwMA0GCSqG\n" +
"SIb3DQEBBQUAA4IBAQBeZs7ZIYyKtdnVxVvdLgwySEPOE4pBSXii7XYv0Q9QUvG/\n" +
"++gFGQh89HhABzA1mVUjH5dJTQqSLFvRfqTHqLpxSxSWqMHnvRM4cPBkIRp/XlMK\n" +
"PlXadYtJLPTgpbgvulA1ickC9EwlNYWnowZ4uxnfsMghW4HskBqaV+PnQ8Zvy3L0\n" +
"12c7Cg4mKKS5pb1HdRuiD2opZ+Hc77gRQLvtWNS8jQvd/iTbh6fuvTKfAOFoXw22\n" +
"sWIKHYrmhCIRshUNohGXv50m2o+1w9oWmQ6Dkq7lCjfXfUB4wIbggJjpyEtbNqBt\n" +
"j4MC2x5rfsLKKqToKmNE7pFEgqwe8//Aar1b+Qj+\n" +
"-----END CERTIFICATE-----\n").getBytes();
/**
* CN=*.foo.com
*/
public final static byte[] X509_WILD_FOO = (
"-----BEGIN CERTIFICATE-----\n" +
"MIIESDCCAzCgAwIBAgIJAIz+EYMBU6aUMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MTU1NVoXDTI4MTEwNTE2MTU1NVowgaYx\n" +
"CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0\n" +
"IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl\n" +
"cnRpZmljYXRlczESMBAGA1UEAxQJKi5mb28uY29tMSUwIwYJKoZIhvcNAQkBFhZq\n" +
"dWxpdXNkYXZpZXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" +
"CgKCAQEAyGOvloI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7PlpgpjUg4pN\n" +
"jYGViGjg7zhfbjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc8BQcwHf0\n" +
"ZHLN6sD9m2uVSp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTjHE5t7iu1\n" +
"JVjTuE0pcBvah2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindxOSAnAxK6\n" +
"q/wGqcZ3zvFBTcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfDHArDqUYx\n" +
"qJUlPGlMqrKb3fCFiT3eXehwR7nlzQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCG\n" +
"SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E\n" +
"FgQUnxR3vz86tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuz\n" +
"A1LKh6YNPg0wDQYJKoZIhvcNAQEFBQADggEBAH0ipG6J561UKUfgkeW7GvYwW98B\n" +
"N1ZooWX+JEEZK7+Pf/96d3Ij0rw9ACfN4bpfnCq0VUNZVSYB+GthQ2zYuz7tf/UY\n" +
"A6nxVgR/IjG69BmsBl92uFO7JTNtHztuiPqBn59pt+vNx4yPvno7zmxsfI7jv0ww\n" +
"yfs+0FNm7FwdsC1k47GBSOaGw38kuIVWqXSAbL4EX9GkryGGOKGNh0qvAENCdRSB\n" +
"G9Z6tyMbmfRY+dLSh3a9JwoEcBUso6EWYBakLbq4nG/nvYdYvG9ehrnLVwZFL82e\n" +
"l3Q/RK95bnA6cuRClGusLad0e6bjkBzx/VQ3VarDEpAkTLUGVAa0CLXtnyc=\n" +
"-----END CERTIFICATE-----\n").getBytes();
/**
* CN=*.co.jp
*/
public final static byte[] X509_WILD_CO_JP = (
"-----BEGIN CERTIFICATE-----\n" +
"MIIERjCCAy6gAwIBAgIJAIz+EYMBU6aVMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MTYzMFoXDTI4MTEwNTE2MTYzMFowgaQx\n" +
"CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0\n" +
"IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl\n" +
"cnRpZmljYXRlczEQMA4GA1UEAxQHKi5jby5qcDElMCMGCSqGSIb3DQEJARYWanVs\n" +
"aXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" +
"ggEBAMhjr5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2B\n" +
"lYho4O84X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRy\n" +
"zerA/ZtrlUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY\n" +
"07hNKXAb2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8\n" +
"BqnGd87xQU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiV\n" +
"JTxpTKqym93whYk93l3ocEe55c0CAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB\n" +
"hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE\n" +
"FJ8Ud78/OrbKOIJCSBYs2tDLXofYMB8GA1UdIwQYMBaAFHua2o+QmU5S0qzbswNS\n" +
"yoemDT4NMA0GCSqGSIb3DQEBBQUAA4IBAQA0sWglVlMx2zNGvUqFC73XtREwii53\n" +
"CfMM6mtf2+f3k/d8KXhLNySrg8RRlN11zgmpPaLtbdTLrmG4UdAHHYr8O4y2BBmE\n" +
"1cxNfGxxechgF8HX10QV4dkyzp6Z1cfwvCeMrT5G/V1pejago0ayXx+GPLbWlNeZ\n" +
"S+Kl0m3p+QplXujtwG5fYcIpaGpiYraBLx3Tadih39QN65CnAh/zRDhLCUzKyt9l\n" +
"UGPLEUDzRHMPHLnSqT1n5UU5UDRytbjJPXzF+l/+WZIsanefWLsxnkgAuZe/oMMF\n" +
"EJMryEzOjg4Tfuc5qM0EXoPcQ/JlheaxZ40p2IyHqbsWV4MRYuFH4bkM\n" +
"-----END CERTIFICATE-----\n").getBytes();
/**
* CN=*.foo.com, subjectAlt=*.bar.com, subjectAlt=*.&#x82b1;&#x5b50;.co.jp
* (*.hanako.co.jp in kanji)
*/
public final static byte[] X509_WILD_FOO_BAR_HANAKO = (
"-----BEGIN CERTIFICATE-----\n" +
"MIIEcDCCA1igAwIBAgIJAIz+EYMBU6aWMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MTczMVoXDTI4MTEwNTE2MTczMVowgaYx\n" +
"CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0\n" +
"IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl\n" +
"cnRpZmljYXRlczESMBAGA1UEAxQJKi5mb28uY29tMSUwIwYJKoZIhvcNAQkBFhZq\n" +
"dWxpdXNkYXZpZXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" +
"CgKCAQEAyGOvloI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7PlpgpjUg4pN\n" +
"jYGViGjg7zhfbjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc8BQcwHf0\n" +
"ZHLN6sD9m2uVSp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTjHE5t7iu1\n" +
"JVjTuE0pcBvah2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindxOSAnAxK6\n" +
"q/wGqcZ3zvFBTcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfDHArDqUYx\n" +
"qJUlPGlMqrKb3fCFiT3eXehwR7nlzQIDAQABo4GiMIGfMAkGA1UdEwQCMAAwLAYJ\n" +
"YIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1Ud\n" +
"DgQWBBSfFHe/Pzq2yjiCQkgWLNrQy16H2DAfBgNVHSMEGDAWgBR7mtqPkJlOUtKs\n" +
"27MDUsqHpg0+DTAkBgNVHREEHTAbggkqLmJhci5jb22CDiou6Iqx5a2QLmNvLmpw\n" +
"MA0GCSqGSIb3DQEBBQUAA4IBAQBobWC+D5/lx6YhX64CwZ26XLjxaE0S415ajbBq\n" +
"DK7lz+Rg7zOE3GsTAMi+ldUYnhyz0wDiXB8UwKXl0SDToB2Z4GOgqQjAqoMmrP0u\n" +
"WB6Y6dpkfd1qDRUzI120zPYgSdsXjHW9q2H77iV238hqIU7qCvEz+lfqqWEY504z\n" +
"hYNlknbUnR525ItosEVwXFBJTkZ3Yw8gg02c19yi8TAh5Li3Ad8XQmmSJMWBV4XK\n" +
"qFr0AIZKBlg6NZZFf/0dP9zcKhzSriW27bY0XfzA6GSiRDXrDjgXq6baRT6YwgIg\n" +
"pgJsDbJtZfHnV1nd3M6zOtQPm1TIQpNmMMMd/DPrGcUQerD3\n" +
"-----END CERTIFICATE-----\n").getBytes();
/**
* CN=foo.com, CN=bar.com, CN=&#x82b1;&#x5b50;.co.jp
*/
public final static byte[] X509_THREE_CNS_FOO_BAR_HANAKO = (
"-----BEGIN CERTIFICATE-----\n" +
"MIIEbzCCA1egAwIBAgIJAIz+EYMBU6aXMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MTk0NVoXDTI4MTEwNTE2MTk0NVowgc0x\n" +
"CzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEUMBIGA1UEBwwLRm9yZXN0\n" +
"IEhpbGwxFzAVBgNVBAoMDmh0dHBjb21wb25lbnRzMRowGAYDVQQLDBF0ZXN0IGNl\n" +
"cnRpZmljYXRlczEQMA4GA1UEAwwHZm9vLmNvbTEQMA4GA1UEAwwHYmFyLmNvbTEV\n" +
"MBMGA1UEAwwM6Iqx5a2QLmNvLmpwMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
"ZXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyGOv\n" +
"loI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7PlpgpjUg4pNjYGViGjg7zhf\n" +
"bjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc8BQcwHf0ZHLN6sD9m2uV\n" +
"Sp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTjHE5t7iu1JVjTuE0pcBva\n" +
"h2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindxOSAnAxK6q/wGqcZ3zvFB\n" +
"TcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfDHArDqUYxqJUlPGlMqrKb\n" +
"3fCFiT3eXehwR7nlzQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf\n" +
"Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUnxR3vz86\n" +
"tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuzA1LKh6YNPg0w\n" +
"DQYJKoZIhvcNAQEFBQADggEBAGuZb8ai1NO2j4v3y9TLZvd5s0vh5/TE7n7RX+8U\n" +
"y37OL5k7x9nt0mM1TyAKxlCcY+9h6frue8MemZIILSIvMrtzccqNz0V1WKgA+Orf\n" +
"uUrabmn+CxHF5gpy6g1Qs2IjVYWA5f7FROn/J+Ad8gJYc1azOWCLQqSyfpNRLSvY\n" +
"EriQFEV63XvkJ8JrG62b+2OT2lqT4OO07gSPetppdlSa8NBSKP6Aro9RIX1ZjUZQ\n" +
"SpQFCfo02NO0uNRDPUdJx2huycdNb+AXHaO7eXevDLJ+QnqImIzxWiY6zLOdzjjI\n" +
"VBMkLHmnP7SjGSQ3XA4ByrQOxfOUTyLyE7NuemhHppuQPxE=\n" +
"-----END CERTIFICATE-----\n").getBytes();
/**
* subjectAlt=foo.com
*/
public final static byte[] X509_NO_CNS_FOO = (
"-----BEGIN CERTIFICATE-----\n" +
"MIIESjCCAzKgAwIBAgIJAIz+EYMBU6aYMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MjYxMFoXDTI4MTEwNTE2MjYxMFowgZIx\n" +
"CzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEUMBIGA1UEBwwLRm9yZXN0\n" +
"IEhpbGwxFzAVBgNVBAoMDmh0dHBjb21wb25lbnRzMRowGAYDVQQLDBF0ZXN0IGNl\n" +
"cnRpZmljYXRlczElMCMGCSqGSIb3DQEJARYWanVsaXVzZGF2aWVzQGdtYWlsLmNv\n" +
"bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMhjr5aCPoyp0R1iroWA\n" +
"fnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2BlYho4O84X244QrZTRl8kQbYt\n" +
"xnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRyzerA/ZtrlUqf+lKo0uWcocxe\n" +
"Rc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY07hNKXAb2odnVqgzcYiDkLV8\n" +
"ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8BqnGd87xQU3FVZI4tbtkB+Kz\n" +
"jD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiVJTxpTKqym93whYk93l3ocEe5\n" +
"5c0CAwEAAaOBkDCBjTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM\n" +
"IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUnxR3vz86tso4gkJIFiza\n" +
"0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuzA1LKh6YNPg0wEgYDVR0RBAsw\n" +
"CYIHZm9vLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEAjl78oMjzFdsMy6F1sGg/IkO8\n" +
"tF5yUgPgFYrs41yzAca7IQu6G9qtFDJz/7ehh/9HoG+oqCCIHPuIOmS7Sd0wnkyJ\n" +
"Y7Y04jVXIb3a6f6AgBkEFP1nOT0z6kjT7vkA5LJ2y3MiDcXuRNMSta5PYVnrX8aZ\n" +
"yiqVUNi40peuZ2R8mAUSBvWgD7z2qWhF8YgDb7wWaFjg53I36vWKn90ZEti3wNCw\n" +
"qAVqixM+J0qJmQStgAc53i2aTMvAQu3A3snvH/PHTBo+5UL72n9S1kZyNCsVf1Qo\n" +
"n8jKTiRriEM+fMFlcgQP284EBFzYHyCXFb9O/hMjK2+6mY9euMB1U1aFFzM/Bg==\n" +
"-----END CERTIFICATE-----\n").getBytes();
/**
* Intermediate CA for all of these.
*/
public final static byte[] X509_INTERMEDIATE_CA = (
"-----BEGIN CERTIFICATE-----\n" +
"MIIEnDCCA4SgAwIBAgIJAJTNwZ6yNa5cMA0GCSqGSIb3DQEBBQUAMIGGMQswCQYD\n" +
"VQQGEwJDQTELMAkGA1UECBMCQkMxFjAUBgNVBAoTDXd3dy5jdWNiYy5jb20xFDAS\n" +
"BgNVBAsUC2NvbW1vbnNfc3NsMRUwEwYDVQQDFAxkZW1vX3Jvb3RfY2ExJTAjBgkq\n" +
"hkiG9w0BCQEWFmp1bGl1c2Rhdmllc0BnbWFpbC5jb20wHhcNMDYxMTA1MjE0OTMx\n" +
"WhcNMDcxMTA1MjE0OTMxWjCBojELMAkGA1UEBhMCQ0ExCzAJBgNVBAgTAkJDMRIw\n" +
"EAYDVQQHEwlWYW5jb3V2ZXIxFjAUBgNVBAoTDXd3dy5jdWNiYy5jb20xFDASBgNV\n" +
"BAsUC2NvbW1vbnNfc3NsMR0wGwYDVQQDFBRkZW1vX2ludGVybWVkaWF0ZV9jYTEl\n" +
"MCMGCSqGSIb3DQEJARYWanVsaXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZI\n" +
"hvcNAQEBBQADggEPADCCAQoCggEBAL0S4y3vUO0EM6lwqOEfK8fvrUprIbsikXaG\n" +
"XzejcZ+T3l2Dc7t8WtBfRf78i4JypMqJQSijrUicj3H6mOMIReKaXm6ls4hA5d8w\n" +
"Lhmgiqsz/kW+gA8SeWGWRN683BD/RbQmzOls6ynBvap9jZlthXWBrSIlPCQoBLXY\n" +
"KVaxGzbL4ezaq+XFMKMQSm2uKwVmHHQNbfmZlPsuendBVomb/ked53Ab9IH6dwwN\n" +
"qJH9WIrvIzIVEXWlpvQ5MCqozM7u1akU+G8cazr8theGPCaYkzoXnigWua4OjdpV\n" +
"9z5ZDknhfBzG1AjapdG07FIirwWWgIyZXqZSD96ikmLtwT29qnsCAwEAAaOB7jCB\n" +
"6zAdBgNVHQ4EFgQUe5raj5CZTlLSrNuzA1LKh6YNPg0wgbsGA1UdIwSBszCBsIAU\n" +
"rN8eFIvMiRFXXgDqKumS0/W2AhOhgYykgYkwgYYxCzAJBgNVBAYTAkNBMQswCQYD\n" +
"VQQIEwJCQzEWMBQGA1UEChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9u\n" +
"c19zc2wxFTATBgNVBAMUDGRlbW9fcm9vdF9jYTElMCMGCSqGSIb3DQEJARYWanVs\n" +
"aXVzZGF2aWVzQGdtYWlsLmNvbYIJAJTNwZ6yNa5bMAwGA1UdEwQFMAMBAf8wDQYJ\n" +
"KoZIhvcNAQEFBQADggEBAIB4KMZvHD20pdKajFtMBpL7X4W4soq6EeTtjml3NYa9\n" +
"Qc52bsQEGNccKY9afYSBIndaQvFdtmz6HdoN+B8TjYShw2KhyjtKimGLpWYoi1YF\n" +
"e4aHdmA/Gp5xk8pZzR18FmooxC9RqBux+NAM2iTFSLgDtGIIj4sg2rbn6Bb6ZlQT\n" +
"1rg6VucXCA1629lNfMeNcu7CBNmUKIdaxHR/YJQallE0KfGRiOIWPrPj/VNk0YA6\n" +
"XFg0ocjqXJ2/N0N9rWVshMUaXgOh7m4D/5zga5/nuxDU+PoToA6mQ4bV6eCYqZbh\n" +
"aa1kQYtR9B4ZiG6pB82qVc2dCqStOH2FAEWos2gAVkQ=\n" +
"-----END CERTIFICATE-----\n").getBytes();
/**
* Root CA for all of these.
*/
public final static byte[] X509_ROOT_CA = (
"-----BEGIN CERTIFICATE-----\n" +
"MIIEgDCCA2igAwIBAgIJAJTNwZ6yNa5bMA0GCSqGSIb3DQEBBQUAMIGGMQswCQYD\n" +
"VQQGEwJDQTELMAkGA1UECBMCQkMxFjAUBgNVBAoTDXd3dy5jdWNiYy5jb20xFDAS\n" +
"BgNVBAsUC2NvbW1vbnNfc3NsMRUwEwYDVQQDFAxkZW1vX3Jvb3RfY2ExJTAjBgkq\n" +
"hkiG9w0BCQEWFmp1bGl1c2Rhdmllc0BnbWFpbC5jb20wHhcNMDYxMTA1MjEzNjQz\n" +
"WhcNMjYxMTA1MjEzNjQzWjCBhjELMAkGA1UEBhMCQ0ExCzAJBgNVBAgTAkJDMRYw\n" +
"FAYDVQQKEw13d3cuY3VjYmMuY29tMRQwEgYDVQQLFAtjb21tb25zX3NzbDEVMBMG\n" +
"A1UEAxQMZGVtb19yb290X2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZpZXNA\n" +
"Z21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv+OnocmJ\n" +
"79UeO2hlCwK+Cle5uZWnU6uwJl+08z5cvebb5tT64WL9+psDbfgUH/Gm9JsuxKTg\n" +
"w1tZO/4duIgnaLNSx4HoqaTjwigd/hR3TsoGEPXTCkz1ikgTCOEDvl+iMid6aOrd\n" +
"mViE8HhscxKZ+h5FE7oHZyuT6gFoiaIXhFq+xK2w4ZwDz9L+paiwqywyUJJMnh9U\n" +
"jKorY+nua81N0oxpIhHPspCanDU4neMzCzYOZyLR/LqV5xORvHcFY84GWMz5hI25\n" +
"JbgaWJsYKuCAvNsnQwVoqKPGa7x1fn7x6oGsXJaCVt8weUwIj2xwg1lxMhrNaisH\n" +
"EvKpEAEnGGwWKQIDAQABo4HuMIHrMB0GA1UdDgQWBBSs3x4Ui8yJEVdeAOoq6ZLT\n" +
"9bYCEzCBuwYDVR0jBIGzMIGwgBSs3x4Ui8yJEVdeAOoq6ZLT9bYCE6GBjKSBiTCB\n" +
"hjELMAkGA1UEBhMCQ0ExCzAJBgNVBAgTAkJDMRYwFAYDVQQKEw13d3cuY3VjYmMu\n" +
"Y29tMRQwEgYDVQQLFAtjb21tb25zX3NzbDEVMBMGA1UEAxQMZGVtb19yb290X2Nh\n" +
"MSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZpZXNAZ21haWwuY29tggkAlM3BnrI1\n" +
"rlswDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAlPl3/8h1LttR1svC\n" +
"S8RXbHpAWIT2BEDhGHUNjSmgDQNkE/itf/FCEXh0tlU4bYdtBSOHzflbnzOyIPId\n" +
"VZeSWs33V38xDFy6KoVg1gT8JxkLmE5S1vWkpsHIlpw/U6r7KD0Kx9FYx5AiXjw0\n" +
"lzz/zlVNuO2U09KIDwDPVG1mBzQiMiSWj1U1pM4KxINkWQwDy/fvu/I983s8lW5z\n" +
"hf2WuFNzQN3fcMK5dpBE9NVIu27oYuGYh2sak34v+7T700W2ooBB71qFXtm9P5rl\n" +
"Yp9RCEsg3KEEPNTtCBs8fROeXvLDrP0cmBIqwGYDuRNCxFDTOdjv6YGdA8nLOjaH\n" +
"2dDk0g==\n" +
"-----END CERTIFICATE-----\n").getBytes();
/**
* Below is the private key for all the server certificates above (but
* not the intermediate CA or the root CA). All of those server certs
* came from the same private key.
*/
public final static String RSA_PUBLIC_MODULUS =
"00c863af96823e8ca9d11d62ae85807e713204c1985a80a2747f7ac863c5" +
"8d82e8c1ecf9698298d4838a4d8d81958868e0ef385f6e3842b653465f24" +
"41b62dc671a1e204820fe67c82367f80cbcb52586a39bf965cf0141cc077" +
"f46472cdeac0fd9b6b954a9ffa52a8d2e59ca1cc5e45cefbd4a37c70f1f7" +
"9c7674ad5d07c78640672e94e31c4e6dee2bb52558d3b84d29701bda8767" +
"56a83371888390b57c8a5bc49a8356316ae9f1406a913729121621098a77" +
"713920270312baabfc06a9c677cef1414dc5559238b5bb6407e2b38c3f73" +
"cfc4020c901f0e3647474dca350e66c4e817c31c0ac3a94631a895253c69" +
"4caab29bddf085893dde5de87047b9e5cd";
public final static String RSA_PUBLIC_EXPONENT = "65537";
public final static String RSA_PRIVATE_EXPONENT =
"577abd3295553d0efd4d38c13b62a6d03fa7b7e40cce4f1d5071877d96c6" +
"7a39a63f0f7ab21a89db8acae45587b3ef251309a70f74dc1ac02bde68f3" +
"8ed658e54e685ed370a18c054449512ea66a2252ed36e82b565b5159ec83" +
"f23df40ae189550a183865b25fd77789e960f0d8cedcd72f32d7a66edb4b" +
"a0a2baf3fbeb6c7d75f56ef0af9a7cff1c8c7f297d72eae7982164e50a89" +
"d450698cf598d39343201094241d2d180a95882a7111e58f4a5bdbc5c125" +
"a967dd6ed9ec614c5853e88e4c71e8b682a7cf89cb1d82b6fe78cc865084" +
"c8c5dfbb50c939df2b839c977b0245bfa3615e0592b527b1013d5b675ecb" +
"44e6b355c1df581f50997175166eef39";
public final static String RSA_PRIME1 =
"00fe759c4f0ce8b763880215e82767e7a937297668f4e4b1e119c6b22a3c" +
"a2c7b06c547d88d0aa45f645d7d3aeadaf7f8bc594deae0978529592977c" +
"b1ff890f05033a9e9e15551cad9fbf9c41d12139ccd99c1c3ac7b2197eff" +
"350d236bb900c1440953b64956e0a058ef824a2e16894af175177c77dbe1" +
"fef7d8b532608d2513";
public final static String RSA_PRIME2 =
"00c99a45878737a4cf73f9896680b75487f1b669b7686a6ba07103856f31" +
"db668c2c440c44cdd116f708f631c37a9adf119f5b5cb58ffe3dc62e20af" +
"af72693d936dc6bb3c5194996468389c1f094079b81522e94572b4ad7d39" +
"529178e9b8ebaeb1f0fdd83b8731c5223f1dea125341d1d64917f6b1a6ae" +
"c18d320510d79f859f";
public final static String RSA_EXPONENT1 =
"029febf0d4cd41b7011c2465b4a259bd6118486464c247236f44a169d61e" +
"47b9062508f674508d5031003ceabc57e714e600d71b2c75d5443db2da52" +
"6bb45a374f0537c5a1aab3150764ce93cf386c84346a6bd01f6732e42075" +
"c7a0e9e78a9e73b934e7d871d0f75673820089e129a1604438edcbbeb4e2" +
"106467da112ce389";
public final static String RSA_EXPONENT2 =
"00827e76650c946afcd170038d32e1f8386ab00d6be78d830efe382e45d4" +
"7ad4bd04e6231ee22e66740efbf52838134932c9f8c460cdccdec58a1424" +
"4427859192fd6ab6c58b74e97941b0eaf577f2a11713af5e5952af3ae124" +
"9a9a892e98410dfa2628d9af668a43b5302fb7d496c9b2fec69f595292b6" +
"e997f079b0f6314eb7";
public final static String RSA_COEFFICIENT =
"00e6b62add350f1a2a8968903ff76c31cf703b0d7326c4a620aef01225b7" +
"1640b3f2ec375208c5f7299863f6005b7799b6e529bb1133c8435bf5fdb5" +
"a786f6cd8a19ee7094a384e6557c600a38845a0960ddbfd1df18d0af5740" +
"001853788f1b5ccbf9affb4c52c9d2efdb8aab0183d86735b32737fb4e79" +
"2b8a9c7d91c7d175ae";
}

View File

@ -0,0 +1,51 @@
/*
* $HeadURL$
* $Revision$
* $Date$
* ====================================================================
*
* Copyright 1999-2006 The Apache Software Foundation
*
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.conn.ssl;
import junit.framework.*;
public class TestAllSSL extends TestCase {
public TestAllSSL(String testName) {
super(testName);
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(TestHostnameVerifier.suite());
suite.addTest(TestSSLSocketFactory.suite());
return suite;
}
public static void main(String args[]) {
String[] testCaseName = { TestAllSSL.class.getName() };
junit.textui.TestRunner.main(testCaseName);
}
}

View File

@ -0,0 +1,221 @@
/*
* $HeadURL$
* $Revision$
* $Date$
*
* ====================================================================
*
* Copyright 1999-2006 The Apache Software Foundation
*
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.conn.ssl;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import javax.net.ssl.SSLException;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
/**
* Unit tests for {@link HostnameVerifier}.
*
* @author Julius Davies
* @since 11-Dec-2006
*/
public class TestHostnameVerifier extends TestCase
implements CertificatesToPlayWith {
public TestHostnameVerifier(String testName) {
super(testName);
}
public static void main(String args[]) throws Exception {
String[] testCaseName = { TestHostnameVerifier.class.getName() };
junit.textui.TestRunner.main(testCaseName);
}
public static Test suite() {
TestSuite ts = new TestSuite();
ts.addTestSuite(TestHostnameVerifier.class);
return ts;
}
public void testVerify() throws Exception {
HostnameVerifier DEFAULT = HostnameVerifier.DEFAULT;
HostnameVerifier STRICT = HostnameVerifier.STRICT;
HostnameVerifier ALLOW_ALL = HostnameVerifier.ALLOW_ALL;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream in;
X509Certificate x509;
in = new ByteArrayInputStream(X509_FOO);
x509 = (X509Certificate) cf.generateCertificate(in);
DEFAULT.verify("foo.com", x509);
STRICT.verify("foo.com", x509);
exceptionPlease(DEFAULT, "a.foo.com", x509);
exceptionPlease(STRICT, "a.foo.com", x509);
exceptionPlease(DEFAULT, "bar.com", x509);
exceptionPlease(STRICT, "bar.com", x509);
ALLOW_ALL.verify("foo.com", x509);
ALLOW_ALL.verify("a.foo.com", x509);
ALLOW_ALL.verify("bar.com", x509);
in = new ByteArrayInputStream(X509_HANAKO);
x509 = (X509Certificate) cf.generateCertificate(in);
DEFAULT.verify("\u82b1\u5b50.co.jp", x509);
STRICT.verify("\u82b1\u5b50.co.jp", x509);
exceptionPlease(DEFAULT, "a.\u82b1\u5b50.co.jp", x509);
exceptionPlease(STRICT, "a.\u82b1\u5b50.co.jp", x509);
in = new ByteArrayInputStream(X509_FOO_BAR);
x509 = (X509Certificate) cf.generateCertificate(in);
DEFAULT.verify("foo.com", x509);
STRICT.verify("foo.com", x509);
exceptionPlease(DEFAULT, "a.foo.com", x509);
exceptionPlease(STRICT, "a.foo.com", x509);
DEFAULT.verify("bar.com", x509);
STRICT.verify("bar.com", x509);
exceptionPlease(DEFAULT, "a.bar.com", x509);
exceptionPlease(STRICT, "a.bar.com", x509);
in = new ByteArrayInputStream(X509_FOO_BAR_HANAKO);
x509 = (X509Certificate) cf.generateCertificate(in);
DEFAULT.verify("foo.com", x509);
STRICT.verify("foo.com", x509);
exceptionPlease(DEFAULT, "a.foo.com", x509);
exceptionPlease(STRICT, "a.foo.com", x509);
DEFAULT.verify("bar.com", x509);
STRICT.verify("bar.com", x509);
exceptionPlease(DEFAULT, "a.bar.com", x509);
exceptionPlease(STRICT, "a.bar.com", x509);
/*
Java isn't extracting international subjectAlts properly. (Or
OpenSSL isn't storing them properly).
*/
// DEFAULT.verify("\u82b1\u5b50.co.jp", x509 );
// STRICT.verify("\u82b1\u5b50.co.jp", x509 );
exceptionPlease(DEFAULT, "a.\u82b1\u5b50.co.jp", x509);
exceptionPlease(STRICT, "a.\u82b1\u5b50.co.jp", x509);
in = new ByteArrayInputStream(X509_NO_CNS_FOO);
x509 = (X509Certificate) cf.generateCertificate(in);
DEFAULT.verify("foo.com", x509);
STRICT.verify("foo.com", x509);
exceptionPlease(DEFAULT, "a.foo.com", x509);
exceptionPlease(STRICT, "a.foo.com", x509);
in = new ByteArrayInputStream(X509_NO_CNS_FOO);
x509 = (X509Certificate) cf.generateCertificate(in);
DEFAULT.verify("foo.com", x509);
STRICT.verify("foo.com", x509);
exceptionPlease(DEFAULT, "a.foo.com", x509);
exceptionPlease(STRICT, "a.foo.com", x509);
in = new ByteArrayInputStream(X509_THREE_CNS_FOO_BAR_HANAKO);
x509 = (X509Certificate) cf.generateCertificate(in);
exceptionPlease(DEFAULT, "foo.com", x509);
exceptionPlease(STRICT, "foo.com", x509);
exceptionPlease(DEFAULT, "a.foo.com", x509);
exceptionPlease(STRICT, "a.foo.com", x509);
exceptionPlease(DEFAULT, "bar.com", x509);
exceptionPlease(STRICT, "bar.com", x509);
exceptionPlease(DEFAULT, "a.bar.com", x509);
exceptionPlease(STRICT, "a.bar.com", x509);
DEFAULT.verify("\u82b1\u5b50.co.jp", x509);
STRICT.verify("\u82b1\u5b50.co.jp", x509);
exceptionPlease(DEFAULT, "a.\u82b1\u5b50.co.jp", x509);
exceptionPlease(STRICT, "a.\u82b1\u5b50.co.jp", x509);
in = new ByteArrayInputStream(X509_WILD_FOO);
x509 = (X509Certificate) cf.generateCertificate(in);
exceptionPlease(DEFAULT, "foo.com", x509);
exceptionPlease(STRICT, "foo.com", x509);
DEFAULT.verify("www.foo.com", x509);
STRICT.verify("www.foo.com", x509);
DEFAULT.verify("\u82b1\u5b50.foo.com", x509);
STRICT.verify("\u82b1\u5b50.foo.com", x509);
DEFAULT.verify("a.b.foo.com", x509);
exceptionPlease(STRICT, "a.b.foo.com", x509);
in = new ByteArrayInputStream(X509_WILD_CO_JP);
x509 = (X509Certificate) cf.generateCertificate(in);
// Silly test because no-one would ever be able to lookup an IP address
// using "*.co.jp".
DEFAULT.verify("*.co.jp", x509);
STRICT.verify("*.co.jp", x509);
exceptionPlease(DEFAULT, "foo.co.jp", x509);
exceptionPlease(STRICT, "foo.co.jp", x509);
exceptionPlease(DEFAULT, "\u82b1\u5b50.co.jp", x509);
exceptionPlease(STRICT, "\u82b1\u5b50.co.jp", x509);
in = new ByteArrayInputStream(X509_WILD_FOO_BAR_HANAKO);
x509 = (X509Certificate) cf.generateCertificate(in);
// try the foo.com variations
exceptionPlease(DEFAULT, "foo.com", x509);
exceptionPlease(STRICT, "foo.com", x509);
DEFAULT.verify("www.foo.com", x509);
STRICT.verify("www.foo.com", x509);
DEFAULT.verify("\u82b1\u5b50.foo.com", x509);
STRICT.verify("\u82b1\u5b50.foo.com", x509);
DEFAULT.verify("a.b.foo.com", x509);
exceptionPlease(STRICT, "a.b.foo.com", x509);
// try the bar.com variations
exceptionPlease(DEFAULT, "bar.com", x509);
exceptionPlease(STRICT, "bar.com", x509);
DEFAULT.verify("www.bar.com", x509);
STRICT.verify("www.bar.com", x509);
DEFAULT.verify("\u82b1\u5b50.bar.com", x509);
STRICT.verify("\u82b1\u5b50.bar.com", x509);
DEFAULT.verify("a.b.bar.com", x509);
exceptionPlease(STRICT, "a.b.bar.com", x509);
// try the \u82b1\u5b50.co.jp variations
/*
Java isn't extracting international subjectAlts properly. (Or
OpenSSL isn't storing them properly).
*/
//exceptionPlease( DEFAULT, "\u82b1\u5b50.co.jp", x509 );
//exceptionPlease( STRICT, "\u82b1\u5b50.co.jp", x509 );
//DEFAULT.verify("www.\u82b1\u5b50.co.jp", x509 );
//STRICT.verify("www.\u82b1\u5b50.co.jp", x509 );
//DEFAULT.verify("\u82b1\u5b50.\u82b1\u5b50.co.jp", x509 );
//STRICT.verify("\u82b1\u5b50.\u82b1\u5b50.co.jp", x509 );
//DEFAULT.verify("a.b.\u82b1\u5b50.co.jp", x509 );
//exceptionPlease(STRICT,"a.b.\u82b1\u5b50.co.jp", x509 );
}
private void exceptionPlease(HostnameVerifier hv, String host,
X509Certificate x509) {
try {
hv.verify(host, x509);
fail("HostnameVerifier shouldn't allow [" + host + "]");
}
catch(SSLException e) {
// whew! we're okay!
}
}
}

View File

@ -0,0 +1,215 @@
/*
* $HeadURL$
* $Revision$
* $Date$
*
* ====================================================================
*
* Copyright 1999-2006 The Apache Software Foundation
*
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.conn.ssl;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.http.impl.DefaultHttpParams;
import org.apache.http.params.HttpParams;
import javax.net.ServerSocketFactory;
import javax.net.ssl.SSLServerSocketFactory;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.RSAPrivateCrtKeySpec;
/**
* Unit tests for {@link SSLSocketFactory}.
*
* @author Julius Davies
* @since 8-Dec-2006
*/
public class TestSSLSocketFactory extends TestCase
implements CertificatesToPlayWith {
public TestSSLSocketFactory(String testName) {
super(testName);
}
public static void main(String args[]) throws Exception {
String[] testCaseName = { TestSSLSocketFactory.class.getName() };
junit.textui.TestRunner.main(testCaseName);
}
public static Test suite() {
TestSuite ts = new TestSuite();
ts.addTestSuite(TestSSLSocketFactory.class);
return ts;
}
public void testConstructor() {}
public void testCreateKeyManagers() {}
public void testCreateTrustManagers() {}
public void testHashCode() {}
public void testEquals() {}
public void testToString() {}
public void testCreateSocket() throws Exception {
HttpParams params = new DefaultHttpParams();
String password = "changeit";
char[] pwd = password.toCharArray();
RSAPrivateCrtKeySpec k;
k = new RSAPrivateCrtKeySpec(new BigInteger(RSA_PUBLIC_MODULUS, 16),
new BigInteger(RSA_PUBLIC_EXPONENT, 10),
new BigInteger(RSA_PRIVATE_EXPONENT, 16),
new BigInteger(RSA_PRIME1, 16),
new BigInteger(RSA_PRIME2, 16),
new BigInteger(RSA_EXPONENT1, 16),
new BigInteger(RSA_EXPONENT2, 16),
new BigInteger(RSA_COEFFICIENT, 16));
PrivateKey pk = KeyFactory.getInstance("RSA").generatePrivate(k);
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(null, null);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream in1, in2, in3;
in1 = new ByteArrayInputStream(X509_FOO);
in2 = new ByteArrayInputStream(X509_INTERMEDIATE_CA);
in3 = new ByteArrayInputStream(X509_ROOT_CA);
X509Certificate[] chain = new X509Certificate[3];
chain[0] = (X509Certificate) cf.generateCertificate(in1);
chain[1] = (X509Certificate) cf.generateCertificate(in2);
chain[2] = (X509Certificate) cf.generateCertificate(in3);
ks.setKeyEntry("RSA_KEY", pk, pwd, chain);
ks.setCertificateEntry("CERT", chain[2]); // Let's trust ourselves. :-)
File tempFile = File.createTempFile("junit", "jks");
try {
String path = tempFile.getCanonicalPath();
tempFile.deleteOnExit();
FileOutputStream fOut = new FileOutputStream(tempFile);
ks.store(fOut, pwd);
fOut.close();
System.setProperty("javax.net.ssl.keyStore", path);
System.setProperty("javax.net.ssl.keyStorePassword", password);
System.setProperty("javax.net.ssl.trustStore", path);
System.setProperty("javax.net.ssl.trustStorePassword", password);
ServerSocketFactory server = SSLServerSocketFactory.getDefault();
// Let the operating system just choose an available port:
ServerSocket serverSocket = server.createServerSocket(0);
serverSocket.setSoTimeout(30000);
int port = serverSocket.getLocalPort();
// System.out.println("\nlistening on port: " + port);
SSLSocketFactory ssf = new SSLSocketFactory();
ssf.setHostnameVerifier(HostnameVerifier.ALLOW_ALL);
// Test 1 - createSocket()
IOException[] e = new IOException[1];
boolean[] success = new boolean[1];
listen(serverSocket, e, success);
Socket s = ssf.createSocket("localhost", port, null, 0, params);
exerciseSocket(s, e, success);
// Test 2 - createSocket( Socket ), where we upgrade a plain socket
// to SSL.
success[0] = false;
listen(serverSocket, e, success);
s = new Socket("localhost", port);
s = ssf.createSocket(s, "localhost", port, true);
exerciseSocket(s, e, success);
}
finally {
tempFile.delete();
}
}
private static void listen(final ServerSocket ss,
final IOException[] e,
final boolean[] success) {
Runnable r = new Runnable() {
public void run() {
try {
Socket s = ss.accept();
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
out.write("server says hello\n".getBytes());
byte[] buf = new byte[4096];
in.read(buf);
out.close();
in.close();
s.close();
} catch(IOException ioe) {
e[0] = ioe;
} finally {
success[0] = true;
}
}
};
new Thread(r).start();
Thread.yield();
}
private static void exerciseSocket(Socket s, IOException[] e,
boolean[] success)
throws IOException {
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
out.write(42);
byte[] buf = new byte[4096];
in.read(buf);
out.close();
in.close();
s.close();
// String response = new String( buf, 0, c );
while(!success[0]) {
Thread.yield();
}
if(e[0] != null) {
throw e[0];
}
}
}

View File

@ -30,6 +30,7 @@ package org.apache.httpclient;
import org.apache.http.cookie.TestAllCookie;
import org.apache.http.cookie.impl.TestAllCookieImpl;
import org.apache.http.conn.ssl.TestAllSSL;
import org.apache.httpclient.impl.TestAllHttpClientImpl;
import junit.framework.*;
@ -45,6 +46,7 @@ public class TestAll extends TestCase {
suite.addTest(TestAllCookie.suite());
suite.addTest(TestAllCookieImpl.suite());
suite.addTest(TestAllHttpClientImpl.suite());
suite.addTest(TestAllSSL.suite());
return suite;
}