diff --git a/src/share/classes/javax/net/ssl/HostnameVerifier.java b/src/share/classes/javax/net/ssl/HostnameVerifier.java --- a/src/share/classes/javax/net/ssl/HostnameVerifier.java +++ b/src/share/classes/javax/net/ssl/HostnameVerifier.java @@ -41,6 +41,7 @@ * * @author Brad R. Wetmore * @since 1.4 + * @see HostnameVerifierFactory */ public interface HostnameVerifier { diff --git a/src/share/classes/javax/net/ssl/HostnameVerifierFactory.java b/src/share/classes/javax/net/ssl/HostnameVerifierFactory.java new file mode 100644 --- /dev/null +++ b/src/share/classes/javax/net/ssl/HostnameVerifierFactory.java @@ -0,0 +1,237 @@ +/* + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.net.ssl; + +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.Security; + +import sun.security.jca.GetInstance; + +/** + * This class provides a factory for host name verifiers. + * + * The algorithm for host name verification varies slightly among + * application layer protocols. A single factory can create host name + * verifiers for different verification algorithms. + * + * + *

Standard host name verification algorithms

+ * + * The {@link #getInstance(String)}, {@link #getInstance(String, String)}, + * and {@link #getInstance(String, Provider)} methods support at least the + * following host name verification algorithms. + * + * + * + * The rules above cover TLS session authenticated by an X.509 certificate. + * If the TLS session uses Kerberos authentication, both algorithm + * compare the host name in a case-insensitive manner, without wildcard + * matching. + * + * @since 1.8 + * @see HostnameVerifier + */ +public class HostnameVerifierFactory { + private final HostnameVerifierFactorySpi factorySpi; + private final Provider provider; + private final String algorithm; + + /** + * Creates a HostNameVerifierFactory object. + * + * @param factorySpi the delegate + * @param provider the provider + * @param algorithm the algorithm + */ + protected HostnameVerifierFactory(HostnameVerifierFactorySpi factorySpi, + Provider provider, String algorithm) { + this.factorySpi = factorySpi; + this.provider = provider; + this.algorithm = algorithm; + } + + /** + * Returns the algorithm name of this HostnameVerifierFactory + * object. + * + *

This is the same name that was specified in one of the + * getInstance calls that created this + * HostnameVerifierFactory object. + * + * @return the algorithm name of this HostnameVerifierFactory + * object. + */ + public final String getAlgorithm() { + return this.algorithm; + } + + /** + * Returns a HostnameVerifierFactory object that acts as a + * factory for host name verifiers. + * + *

This method traverses the list of registered security Providers, + * starting with the most preferred Provider. + * A new HostnameVerifierFactory object encapsulating the + * HostnameVerifierFactorySpi implementation from the first + * Provider that supports the specified algorithm is returned. + * + *

Note that the list of registered providers may be retrieved via + * the {@link Security#getProviders() Security.getProviders()} method. + * + * @param algorithm the name of the requested algorithm. See + * Standard host name verification algorithms. + * + * @return the new HostnameVerifierFactory object. + * + * @exception NoSuchAlgorithmException if no Provider supports a + * HostnameVerifierFactorySpi implementation for the + * specified algorithm. + * @exception NullPointerException if algorithm is null. + * + * @see java.security.Provider + */ + public static final HostnameVerifierFactory getInstance(String algorithm) + throws NoSuchAlgorithmException { + GetInstance.Instance instance = GetInstance.getInstance + ("HostnameVerifierFactory", HostnameVerifierFactorySpi.class, + algorithm); + return new HostnameVerifierFactory( + (HostnameVerifierFactorySpi)instance.impl, + instance.provider, algorithm); + } + + /** + * Returns a HostnameVerifierFactory object that acts as a + * factory for host name verifier. + * + *

A new HostnameVerifierFactory object encapsulating the + * HostnameVerifierFactorySpi implementation from the specified provider + * is returned. The specified provider must be registered + * in the security provider list. + * + *

Note that the list of registered providers may be retrieved via + * the {@link Security#getProviders() Security.getProviders()} method. + + * @param algorithm the name of the requested algorithm. See + * Standard host name verification algorithms. + + * @param provider the name of the provider. + * + * @return the new HostnameVerifierFactory object. + * + * @throws NoSuchAlgorithmException if a HostnameVerifierFactorySpi + * implementation for the specified algorithm is not + * available from the specified provider. + * + * @throws NoSuchProviderException if the specified provider is not + * registered in the security provider list. + * + * @throws IllegalArgumentException if the provider name is null or empty. + * @throws NullPointerException if algorithm is null. + * + * @see java.security.Provider + */ + public static final HostnameVerifierFactory getInstance(String algorithm, + String provider) throws NoSuchAlgorithmException, + NoSuchProviderException { + GetInstance.Instance instance = GetInstance.getInstance + ("HostnameVerifierFactory", HostnameVerifierFactorySpi.class, + algorithm, provider); + return new HostnameVerifierFactory( + (HostnameVerifierFactorySpi)instance.impl, + instance.provider, algorithm); + } + + /** + * Returns a HostnameVerifierFactory object that acts as a + * factory for host name verifiers. + * + *

A new HostnameVerifierFactory object encapsulating the + * HostnameVerifierFactorySpi implementation from the specified Provider + * object is returned. Note that the specified Provider object + * does not have to be registered in the provider list. + * + * @param algorithm the name of the requested algorithm. See + * Standard host name verification algorithms. + + * @param provider an instance of the provider. + * + * @return the new HostnameVerifierFactory object. + * + * @throws NoSuchAlgorithmException if a HostnameVerifierFactorySpi + * implementation for the specified algorithm is not available + * from the specified Provider object. + * + * @throws IllegalArgumentException if provider is null. + * @throws NullPointerException if algorithm is null. + * + * @see java.security.Provider + */ + public static final HostnameVerifierFactory getInstance(String algorithm, + Provider provider) throws NoSuchAlgorithmException { + GetInstance.Instance instance = GetInstance.getInstance + ("HostnameVerifierFactory", HostnameVerifierFactorySpi.class, + algorithm, provider); + return new HostnameVerifierFactory( + (HostnameVerifierFactorySpi)instance.impl, + instance.provider, algorithm); + } + + /** + * Returns the provider of this HostnameVerifierFactory + * object. + * + * @return the provider of this HostnameVerifierFactory object + */ + public final Provider getProvider() { + return this.provider; + } + + /** + * Returns a host name verifier for the specified algorithm. + * + * @return the host name verifier + */ + public final HostnameVerifier getHostnameVerifier() { + return factorySpi.engineGetHostnameVerifier(); + } +} diff --git a/src/share/classes/javax/net/ssl/HostnameVerifierFactorySpi.java b/src/share/classes/javax/net/ssl/HostnameVerifierFactorySpi.java new file mode 100644 --- /dev/null +++ b/src/share/classes/javax/net/ssl/HostnameVerifierFactorySpi.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.net.ssl; + +/** + * This class defines the Service Provider Interface (SPI) + * for the HostnameVerifierFactory class. + * + *

All the abstract methods in this class must be implemented by each + * cryptographic service provider who wishes to supply the implementation + * of a particular host name verifier factory. + * + * @since 1.8 + * @see HostnameVerifierFactory + * @see HostnameVerifier + */ +public abstract class HostnameVerifierFactorySpi { + /** + * Returns a host name verifier. + * + * @return the host name verifier + * @see HostnameVerifierFactory#getHostnameVerifier() + */ + public abstract HostnameVerifier engineGetHostnameVerifier(); +} diff --git a/src/share/classes/sun/security/ssl/HostnameVerifierFactoryImpl.java b/src/share/classes/sun/security/ssl/HostnameVerifierFactoryImpl.java new file mode 100644 --- /dev/null +++ b/src/share/classes/sun/security/ssl/HostnameVerifierFactoryImpl.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.ssl; + +import java.security.Principal; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HostnameVerifierFactorySpi; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.security.auth.kerberos.KerberosPrincipal; + +import sun.security.util.HostnameChecker; + +/** + * Factory for host name verifiers. + * + * @see HostnameVerifier + */ +class HostnameVerifierFactoryImpl extends HostnameVerifierFactorySpi { + private final byte type; + + HostnameVerifierFactoryImpl(byte type) { + this.type = type; + } + + @Override + public HostnameVerifier engineGetHostnameVerifier() { + return new Verifier(type); + } + + public static class HTTP extends HostnameVerifierFactoryImpl { + public HTTP() { + super(HostnameChecker.TYPE_TLS); + } + } + + public static class LDAP extends HostnameVerifierFactoryImpl { + public LDAP() { + super(HostnameChecker.TYPE_LDAP); + } + } + + static class Verifier implements HostnameVerifier { + private final HostnameChecker checker; + + Verifier(byte type) { + checker = HostnameChecker.getInstance(type); + } + + @Override + public boolean verify(String hostname, SSLSession session) { + // Try Kerberos first. + Principal peerPrincipal; + try { + peerPrincipal = session.getPeerPrincipal(); + } catch (SSLPeerUnverifiedException e) { + return false; + } + if (peerPrincipal instanceof KerberosPrincipal) { + return HostnameChecker.match(hostname, peerPrincipal); + } + + // Not Kerberos, so try X.509. + java.security.cert.Certificate peer; + try { + peer = session.getPeerCertificates()[0]; + } catch (SSLPeerUnverifiedException e) { + return false; + } + if (peer instanceof java.security.cert.X509Certificate) { + try { + checker.match(hostname, (X509Certificate) peer); + return true; + } catch (CertificateException e) { + return false; + } + } + return false; + } + } +} diff --git a/src/share/classes/sun/security/ssl/SunJSSE.java b/src/share/classes/sun/security/ssl/SunJSSE.java --- a/src/share/classes/sun/security/ssl/SunJSSE.java +++ b/src/share/classes/sun/security/ssl/SunJSSE.java @@ -226,6 +226,11 @@ */ put("KeyStore.PKCS12", "sun.security.pkcs12.PKCS12KeyStore"); + + put("HostnameVerifierFactory.HTTP", + "sun.security.ssl.HostnameVerifierFactoryImpl$HTTP"); + put("HostnameVerifierFactory.LDAP", + "sun.security.ssl.HostnameVerifierFactoryImpl$LDAP"); } private void subclassCheck() { diff --git a/test/sun/security/krb5/auto/SSL.java b/test/sun/security/krb5/auto/SSL.java --- a/test/sun/security/krb5/auto/SSL.java +++ b/test/sun/security/krb5/auto/SSL.java @@ -56,6 +56,8 @@ // 0-Not started, 1-Start OK, 2-Failure private static volatile int serverState = 0; + private static String error; + public static void main(String[] args) throws Exception { krb5Cipher = args[0]; @@ -157,6 +159,10 @@ c.startAsClient("host/" + server, GSSUtil.GSS_KRB5_MECH_OID); c.doAs(new JsseClientAction(), null); + if (error != null) { + throw new Exception(error); + } + // Revoke the old key /*Thread.sleep(2000); ktab = KeyTab.create(OneKDC.KTAB); @@ -207,6 +213,16 @@ Principal peer = sslSocket.getSession().getPeerPrincipal(); System.out.println("Server is: " + peer.toString()); + HostnameVerifier verifier = + HostnameVerifierFactory.getInstance("HTTP") + .getHostnameVerifier(); + if (!verifier.verify(server, sslSocket.getSession())) { + error = "host name verification failed unexpectedly"; + } + if (verifier.verify("x" + server, sslSocket.getSession())) { + error = "host name verification succeded unexpectedly"; + } + sslSocket.close(); // This line should not be needed. It's the server's duty to // forget the old key diff --git a/test/sun/security/ssl/javax/net/ssl/HostnameVerification.java b/test/sun/security/ssl/javax/net/ssl/HostnameVerification.java new file mode 100644 --- /dev/null +++ b/test/sun/security/ssl/javax/net/ssl/HostnameVerification.java @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary verify that host name verifiers work as expected + * @run main/othervm HostnameVerification TLSv1 + * @run main/othervm HostnameVerification TLSv1.1 + * @run main/othervm HostnameVerification TLSv1.2 + */ + +import java.math.BigInteger; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Principal; +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Date; +import java.util.HashSet; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HostnameVerifierFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.X509KeyManager; +import javax.net.ssl.X509TrustManager; + +import sun.security.x509.AlgorithmId; +import sun.security.x509.CertificateAlgorithmId; +import sun.security.x509.CertificateSerialNumber; +import sun.security.x509.CertificateValidity; +import sun.security.x509.CertificateVersion; +import sun.security.x509.CertificateX509Key; +import sun.security.x509.X500Name; +import sun.security.x509.X509CertImpl; +import sun.security.x509.X509CertInfo; + +public class HostnameVerification { + + private static final String[] testNames = { + "example.com", "www.example.com", "test.www.example.com", + "*.example.com", "*.www.example.com", "test.*.example.com", "www.*.com", + "example.net", "xn--rger-koa.example.com", "dummy-name", + }; + + private static final HashSet matchExceptions = + new HashSet<>(Arrays.asList(new String[] { + "HTTP: CN: [*.example.com] matches [www.example.com]", + "HTTP: CN: [*.example.com] matches [xn--rger-koa.example.com]", + "HTTP: CN: [www.*.com] matches [www.example.com]", + "HTTP: CN: [test.*.example.com] matches [test.www.example.com]", + "HTTP: CN: [*.www.example.com] matches [test.www.example.com]", + "LDAP: CN: [*.example.com] matches [www.example.com]", + "LDAP: CN: [*.example.com] matches [xn--rger-koa.example.com]", + "LDAP: CN: [*.www.example.com] matches [test.www.example.com]", + })); + + private static String protocol; + private static final SecureRandom random = new SecureRandom(); + private static KeyPair keyPair; + private static ServerSocket serverSocket; + + private static String matchProtocol; + private static HostnameVerifier verifier; + + private static int mismatches; + + public static void main(String[] args) throws Exception { + protocol = args[0]; + serverSocket = new ServerSocket(); + serverSocket.bind(new InetSocketAddress( + InetAddress.getLoopbackAddress(), 0)); + + KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA"); + keygen.initialize(1024, random); + keyPair = keygen.generateKeyPair(); + + matchProtocol = "HTTP"; + run(); + matchProtocol = "LDAP"; + run(); + if (mismatches != 0) { + throw new Exception(mismatches + " mismatches encountered"); + } + } + + private static void run() throws Exception { + HostnameVerifierFactory factory = + HostnameVerifierFactory.getInstance(matchProtocol); + verifier = factory.getHostnameVerifier(); + for (final String certName : testNames) { + X509Certificate cert = + createCertificate(new X500Name("CN=\"" + certName + '"')); + run(cert, new ProcessSession() { + @Override + public void operate(SSLSession sslSession) + throws Exception { + for (String hostName : testNames) { + tryMatch(sslSession, certName, hostName); + } + } + }); + } + } + + private static void tryMatch(SSLSession sslSession, + String certName, String hostName) throws Exception { + boolean match = verifier.verify(hostName, sslSession); + if (match == certName.equalsIgnoreCase(hostName)) { + return; + } + String matchString = match ? "matches" : "does not match"; + String matchException = String.format("%s: CN: [%s] %s [%s]", + matchProtocol, certName, matchString, hostName); + if (matchExceptions.contains(matchException)) { + return; + } + System.out.println(matchException); + ++mismatches; + } + + /** + * Callback invoked with a live TLS session. + */ + interface ProcessSession { + void operate(SSLSession session) throws Exception; + } + + /** + * Invoke the callback with a live TLS session for a peer + * authenticated by the X.509 certificate. + */ + private static void run(X509Certificate cert, ProcessSession op) + throws Exception { + SSLContext sslContext = SSLContext.getInstance(protocol); + sslContext.init(new X509KeyManager[] {new MyKeyManager(cert)}, + new X509TrustManager[] {new MyTrustManager()}, + random); + ServerThread serverThread = new ServerThread(sslContext); + serverThread.start(); + SSLSocketFactory factory = sslContext.getSocketFactory(); + try (SSLSocket clientEnd = (SSLSocket) factory.createSocket()) { + clientEnd.connect(serverSocket.getLocalSocketAddress()); + clientEnd.setTcpNoDelay(true); + clientEnd.startHandshake(); + op.operate(clientEnd.getSession()); + } + serverThread.join(); + if (!serverThread.good) { + throw new Exception("failure in server thread"); + } + } + + /** + * Key manager which returns our generated key. + */ + static class MyKeyManager implements X509KeyManager { + X509Certificate cert; + + MyKeyManager(X509Certificate cert) { + this.cert = cert; + } + + @Override + public String[] getClientAliases(String keyType, Principal[] issuers) { + return new String[0]; + } + + @Override + public String chooseClientAlias(String[] keyType, Principal[] issuers, + Socket socket) { + return ""; + } + + @Override + public String[] getServerAliases(String keyType, Principal[] issuers) { + return new String[0]; + } + + @Override + public String chooseServerAlias(String keyType, Principal[] issuers, + Socket socket) { + return ""; + } + + @Override + public X509Certificate[] getCertificateChain(String alias) { + return new X509Certificate[] {cert}; + } + + @Override + public PrivateKey getPrivateKey(String alias) { + return keyPair.getPrivate(); + } + } + + /** + * Trust manager which accepts all certificates. + */ + static class MyTrustManager implements X509TrustManager { + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, + String authType) { + } + + public void checkClientTrusted(X509Certificate[] chain, + String authType) { + } + } + + static class ServerThread extends Thread { + private SSLContext context; + boolean good = true; + + ServerThread(SSLContext context) { + this.context = context; + } + + @Override + public void run() { + SSLSocketFactory factory = context.getSocketFactory(); + try { + try (Socket serverEnd = serverSocket.accept(); + SSLSocket sslServerEnd = (SSLSocket) factory.createSocket( + serverEnd, "dummy-name", 0, false)) { + serverEnd.setTcpNoDelay(true); + sslServerEnd.setUseClientMode(false); + // Wait for the client to close the connection. + sslServerEnd.getInputStream().read(); + } + } catch (Throwable e) { + e.printStackTrace(); + good = false; + } + } + } + + /** + * Creates a self-signed certificate with the indicated + * subject/issuer DN. + */ + private static X509Certificate createCertificate(X500Name name) + throws Exception { + X509CertInfo info = new X509CertInfo(); + info.set(X509CertInfo.VERSION, + new CertificateVersion(CertificateVersion.V3)); + info.set(X509CertInfo.SERIAL_NUMBER, + new CertificateSerialNumber(BigInteger.ONE)); + info.set(X509CertInfo.ALGORITHM_ID, + new CertificateAlgorithmId(AlgorithmId.get("SHA1withRSA"))); + info.set(X509CertInfo.SUBJECT, name); + info.set(X509CertInfo.KEY, new CertificateX509Key(keyPair.getPublic())); + Date start = new Date(); + Date end = new Date(); + end.setTime(start.getTime() + 3600 * 1000); + info.set(X509CertInfo.VALIDITY, new CertificateValidity(start, end)); + info.set(X509CertInfo.ISSUER, name); + + X509CertImpl cert = new X509CertImpl(info); + cert.sign(keyPair.getPrivate(), "SHA1withRSA"); + return cert; + } + +}