/* * Copyright (c) 2020, 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.
*/
/* * SunJSSE does not support dynamic system properties, no way to re-use * system properties in samevm/agentvm mode. * For extra debugging output, add -Djavax.net.debug=ssl:handshake into the * run directive below.
*/
/* * @test * @bug 8166596 * @summary TLS support for the EdDSA signature algorithm * @library /javax/net/ssl/templates /test/lib * @run main/othervm TLSWithEdDSA
*/
/** * Checks to make sure the end-entity certificate presented by the * peer uses and Ed25519 key.
*/ finalstatic SessionChecker isPeerEd25519 = new SessionChecker() {
@Override publicvoid check(SSLSocket sock) { try {
SSLSession session = sock.getSession();
System.out.println("Peer certificate check for Ed25519:\n" +
sessionDump(session));
Certificate[] serverCertChain = session.getPeerCertificates();
X509Certificate tlsCert = (X509Certificate)serverCertChain[0];
keyCheck(tlsCert.getPublicKey(), "EdDSA", "Ed25519");
} catch (SSLPeerUnverifiedException sslpe) { thrownew RuntimeException(sslpe);
}
}
};
/** * Checks to make sure the end-entity certificate presented by the * peer uses and Ed448 key.
*/ finalstatic SessionChecker isPeerEd448 = new SessionChecker() {
@Override publicvoid check(SSLSocket sock) { try {
SSLSession session = sock.getSession();
System.out.println("Peer certificate check for Ed448:\n" +
sessionDump(session));
Certificate[] serverCertChain = session.getPeerCertificates();
X509Certificate tlsCert = (X509Certificate)serverCertChain[0];
keyCheck(tlsCert.getPublicKey(), "EdDSA", "Ed448");
} catch (SSLPeerUnverifiedException sslpe) { thrownew RuntimeException(sslpe);
}
}
};
/** * Checks to make sure the end-entity certificate presented by the * peer uses an EC secp521r1 key.
*/ finalstatic SessionChecker isPeerP521 = new SessionChecker() {
@Override publicvoid check(SSLSocket sock) { try {
SSLSession session = sock.getSession();
System.out.println("Peer certificate check for secp521r1:\n" +
sessionDump(session));
Certificate[] serverCertChain = session.getPeerCertificates();
X509Certificate tlsCert = (X509Certificate)serverCertChain[0];
keyCheck(tlsCert.getPublicKey(), "EC", "secp521r1");
} catch (SSLPeerUnverifiedException sslpe) { thrownew RuntimeException(sslpe);
}
}
};
/** * Returns a String summary of an SSLSession object * * @param sess the SSLSession object to be dumped * * @return a String representation of the test-relevant portions of the * SSLSession object.
*/ privatestatic String sessionDump(SSLSession sess) {
StringBuilder sb = new StringBuilder();
sb.append("----- Session Info -----\n");
sb.append("Protocol: ").append(sess.getProtocol()).append("\n");
sb.append("Cipher Suite: ").append(sess.getCipherSuite());
Certificate[] localCerts = sess.getLocalCertificates(); if (localCerts != null) {
sb.append("\nLocal Certs:"); int i = 0; for (Certificate cert : localCerts) {
sb.append(String.format("\n [%d]: %s", i++,
((X509Certificate)cert).getSubjectX500Principal()));
}
} try {
Certificate[] peerCerts = sess.getPeerCertificates(); if (peerCerts != null) {
sb.append("\nPeer Certs:"); int i = 0; for (Certificate cert : peerCerts) {
sb.append(String.format("\n [%d]: %s", i++,
((X509Certificate)cert).getSubjectX500Principal()));
}
}
} catch (SSLPeerUnverifiedException sslex) { thrownew RuntimeException(sslex);
}
return sb.toString();
}
/** * Checks to make sure the public key conforms to the expected key type * and (where applicable) curve. * * @param pubKey the public key to be checked * @param expPkType the expected key type (RSA/DSA/EC/EdDSA) * @param expCurveName if an EC/EdDSA key, the expected curve
*/ privatestaticvoid keyCheck(PublicKey pubKey, String expPkType,
String expCurveName) {
String curveName = null;
String pubKeyAlg = pubKey.getAlgorithm(); if (!expPkType.equalsIgnoreCase(pubKeyAlg)) { thrownew RuntimeException("Expected " + expPkType + " key, got " +
pubKeyAlg);
}
/** * Creates an SSLContext for use with the client side of this test. This * uses parameters held in the static client parameters map. * * @return an initialized SSLContext for use with the client. * * @throws Exception if any downstream errors occur during key store * creation, key/trust manager factory creation or context * initialization.
*/
@Override protected SSLContext createClientSSLContext() throws Exception {
KeyStore clientKeyStore = createKeyStore(
clientParameters.getOrDefault(ParamType.KSENTRIES, ""),
PASSWD.toCharArray());
KeyStore clientTrustStore = createTrustStore(
clientParameters.getOrDefault(ParamType.TSENTRIES,
DEF_TRUST_ANCHORS)); return createCtxCommon(clientKeyStore,
clientParameters.get(ParamType.CERTALIAS), PASSWD.toCharArray(),
clientTrustStore, "jdk.tls.client.SignatureSchemes",
clientParameters.get(ParamType.SIGALGS));
}
/** * Creates an SSLContext for use with the server side of this test. This * uses parameters held in the static server parameters map. * * @return an initialized SSLContext for use with the server. * * @throws Exception if any downstream errors occur during key store * creation, key/trust manager factory creation or context * initialization.
*/
@Override protected SSLContext createServerSSLContext() throws Exception {
KeyStore serverKeyStore = createKeyStore(
serverParameters.getOrDefault(ParamType.KSENTRIES, ""),
PASSWD.toCharArray());
KeyStore serverTrustStore = createTrustStore(
serverParameters.getOrDefault(ParamType.TSENTRIES,
DEF_TRUST_ANCHORS)); return createCtxCommon(serverKeyStore,
serverParameters.get(ParamType.CERTALIAS), PASSWD.toCharArray(),
serverTrustStore, "jdk.tls.server.SignatureSchemes",
serverParameters.get(ParamType.SIGALGS));
}
/** * Create a trust store containing any CA certificates designated as * trust anchors. * * @return the trust store populated with the root CA certificate. * * @throws GeneralSecurityException if any certificates cannot be added to * the key store.
*/ privatestatic KeyStore createTrustStore(String certEnumNames) throws GeneralSecurityException {
KeyStore.Builder keyStoreBuilder =
KeyStore.Builder.newInstance("PKCS12", null, new KeyStore.PasswordProtection(PASSWD.toCharArray()));
KeyStore ks = keyStoreBuilder.getKeyStore(); for (String certName : certEnumNames.split(":")) { try {
SSLSocketTemplate.Cert cert =
SSLSocketTemplate.Cert.valueOf(certName);
ks.setCertificateEntry(certName, pem2Cert(cert.certStr));
} catch (IllegalArgumentException iae) {
System.out.println("Unable to find Cert enum entry for " +
certName + ", skipping");
}
} return ks;
}
/** * Create a key store containing any end-entity private keys/certs * specified in the parameters. * * @param certEnumNames a colon-delimited list of String values that are * the names of the SSLSocketTemplate.Cert enumeration entries. * @param pass the desired password for the resulting KeyStore object. * * @return a populated, loaded KeyStore ready for use. * * @throws GeneralSecurityException if any issues occur while setting * the private key or certificate entries.
*/ privatestatic KeyStore createKeyStore(String certEnumNames, char[] pass) throws GeneralSecurityException {
KeyStore.Builder keyStoreBuilder =
KeyStore.Builder.newInstance("PKCS12", null, new KeyStore.PasswordProtection(pass));
KeyStore ks = keyStoreBuilder.getKeyStore(); if (certEnumNames != null && !certEnumNames.isEmpty()) { for (String certName : certEnumNames.split(":")) { try {
SSLSocketTemplate.Cert cert =
SSLSocketTemplate.Cert.valueOf(certName);
ks.setKeyEntry(certName,
pem2PrivKey(cert.privKeyStr, cert.keyAlgo), pass, new Certificate[] { pem2Cert(cert.certStr) });
} catch (IllegalArgumentException iae) {
System.out.println("Unable to find Cert enum entry for " +
certName + ", skipping");
}
}
}
return ks;
}
/** * Covert a PEM-encoded certificate into a X509Certificate object. * * @param certPem the PEM encoding for the certificate. * * @return the corresponding X509Certificate object for the provided PEM. * * @throws CertificateException if any decoding errors occur.
*/ privatestatic X509Certificate pem2Cert(String certPem) throws CertificateException { return (X509Certificate)certFac.generateCertificate( new ByteArrayInputStream(certPem.getBytes(
Charset.forName("UTF-8"))));
}
/** * Covert a PEM-encoded PKCS8 private key into a PrivateKey object. * * @param keyPem the PEM encoding for the certificate. * @param keyAlg the algorithm for the private key contained in the PKCS8 * ` encoding. * * @return the corresponding PrivateKey object for the provided PEM. * * @throws GeneralSecurityException if any decoding errors occur.
*/ privatestatic PrivateKey pem2PrivKey(String keyPem, String keyAlg) throws GeneralSecurityException {
PKCS8EncodedKeySpec p8Spec = new PKCS8EncodedKeySpec(
Base64.getMimeDecoder().decode(keyPem));
KeyFactory keyFac = KeyFactory.getInstance(keyAlg); return keyFac.generatePrivate(p8Spec);
}
/** * Create an SSLContext for use with the client or server sides of this * test. * * @param keys the key store object for this SSLContext. * @param alias optional alias specifier to exclusively use that alias for * TLS connections. * @param pass the key store password * @param trust the trust store object * @param sigAlgProp the signature algorithm property name to set * (reserved for future use pending the fix for JDK-8255867) * @param sigAlgVal the property value to be applied. * * @return an initialized SSLContext object. * * @throws IOException if any IOExceptions during manager factory creation * take place * @throws GeneralSecurityException any other failure during SSLContext * creation/initialization
*/ privatestatic SSLContext createCtxCommon(KeyStore keys, String alias, char[] pass, KeyStore trust, String sigAlgProp, String sigAlgVal) throws IOException, GeneralSecurityException {
SSLContext ctx; if (sigAlgVal != null && !sigAlgVal.isEmpty()) {
System.setProperty(sigAlgProp, sigAlgVal);
}
// If an alias is specified use our local AliasKeyManager
KeyManager[] kms = (alias != null && !alias.isEmpty()) ? new KeyManager[] { new AliasKeyManager(keys, pass, alias) } :
createKeyManagerFactory(keys, pass).getKeyManagers();
/** * Creates a KeyManagerFactory for use during SSLContext initialization. * * @param ks the KeyStore forming the base of the KeyManagerFactory * @param passwd the password to use for the key store * * @return the initialized KeyManagerFactory * * @throws IOException any IOExceptions during key manager factory * initialization. * @throws GeneralSecurityException if any failures during instantiation * take place.
*/ privatestatic KeyManagerFactory createKeyManagerFactory(KeyStore ks, char[] passwd) throws IOException, GeneralSecurityException {
KeyManagerFactory kmf;
kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, passwd);
/** * Creates a TrustManagerFactory for use during SSLContext initialization. * * @param trustStrore the KeyStore forming the base of the * TrustManagerFactory * * @return the initialized TrustManagerFactory * * @throws IOException any IOExceptions during trust manager factory * initialization. * @throws GeneralSecurityException if any failures during instantiation * take place.
*/ privatestatic TrustManagerFactory createTrustManagerFactory(
KeyStore trustStore) throws IOException, GeneralSecurityException {
TrustManagerFactory tmf;
PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(trustStore, new X509CertSelector());
pkixParams.setRevocationEnabled(false);
tmf = TrustManagerFactory.getInstance("PKIX");
tmf.init(new CertPathTrustManagerParameters(pkixParams)); return tmf;
}
/* * Configure the client side socket.
*/
@Override protectedvoid configureClientSocket(SSLSocket socket) {
String pVal; if ((pVal = clientParameters.get(ParamType.PROTOS)) != null) {
socket.setEnabledProtocols(pVal.split(":"));
}
if ((pVal = clientParameters.get(ParamType.CIPHERS)) != null) {
socket.setEnabledCipherSuites(pVal.split(":"));
}
}
/* * Configure the server side socket.
*/
@Override protectedvoid configureServerSocket(SSLServerSocket socket) {
String pVal; try {
socket.setReuseAddress(true); if ((pVal = serverParameters.get(ParamType.PROTOS)) != null) {
socket.setEnabledProtocols(pVal.split(":"));
}
if ((pVal = serverParameters.get(ParamType.CIPHERS)) != null) {
socket.setEnabledCipherSuites(pVal.split(":"));
}
/** * A Custom KeyManager that allows the user to specify a key/certificate * by alias to be used for any TLS authentication actions.
*/ staticclass AliasKeyManager implements X509KeyManager { privatefinal String alias; privatefinal KeyStore keystore; privatefinalchar[] pass;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.