[xmlsectool] branch main updated: XSTJ82 - Revise --pkcs11Config handling under Java 11
Ian Young
ian at iay.org.uk
Wed Sep 30 14:07:01 UTC 2020
This is an automated email from the git hooks/post-receive script.
iay pushed a commit to branch main
in repository xmlsectool.
View the commit online:
http://git.shibboleth.net/view/?p=xmlsectool.git;a=commit;h=69d3c45cf8041bb8c33e0a7817a25db48e51064c
The following commit(s) were added to refs/heads/main by this push:
new 69d3c45 XSTJ82 - Revise --pkcs11Config handling under Java 11
69d3c45 is described below
commit 69d3c45cf8041bb8c33e0a7817a25db48e51064c
Author: Ian Young <ian at iay.org.uk>
AuthorDate: Wed Sep 30 15:06:36 2020 +0100
XSTJ82 - Revise --pkcs11Config handling under Java 11
https://issues.shibboleth.net/jira/browse/XSTJ-82
---
.../tool/xmlsectool/CommandLineArguments.java | 5 -
.../tool/xmlsectool/CredentialHelper.java | 81 ++++++++------
.../net/shibboleth/tool/xmlsectool/XSTJ82Test.java | 93 ++++++++++++++++
.../net/shibboleth/tool/xmlsectool/XSTJ82-in.xml | 119 +++++++++++++++++++++
.../net/shibboleth/tool/xmlsectool/softhsm.cfg | 8 ++
5 files changed, 270 insertions(+), 36 deletions(-)
diff --git a/src/main/java/net/shibboleth/tool/xmlsectool/CommandLineArguments.java b/src/main/java/net/shibboleth/tool/xmlsectool/CommandLineArguments.java
index 2e484a0..897a01d 100644
--- a/src/main/java/net/shibboleth/tool/xmlsectool/CommandLineArguments.java
+++ b/src/main/java/net/shibboleth/tool/xmlsectool/CommandLineArguments.java
@@ -684,11 +684,6 @@ public class CommandLineArguments {
out.println(String.format(" --%-20s %s", KEY_ARG,
"Specifies the key alias for the signing key is read."));
out.println(String.format(" --%-20s %s", KEY_PASSWORD_ARG, "Specifies the pin for the signing key."));
- out.println(String.format(
- " --%-20s %s",
- KEYSTORE_PROVIDER_ARG,
- "The fully qualified class name of the PKCS#11 keystore provider implementation. "
- + "(e.g., sun.security.pkcs11.SunPKCS11)"));
out.println();
out.println("Signature verification algorithm blacklist options:");
diff --git a/src/main/java/net/shibboleth/tool/xmlsectool/CredentialHelper.java b/src/main/java/net/shibboleth/tool/xmlsectool/CredentialHelper.java
index 11a7c56..a228260 100644
--- a/src/main/java/net/shibboleth/tool/xmlsectool/CredentialHelper.java
+++ b/src/main/java/net/shibboleth/tool/xmlsectool/CredentialHelper.java
@@ -20,20 +20,21 @@ package net.shibboleth.tool.xmlsectool;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-import java.lang.reflect.Constructor;
import java.security.GeneralSecurityException;
import java.security.KeyException;
import java.security.KeyStore;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.KeyStore.TrustedCertificateEntry;
import java.security.KeyStoreException;
-import java.security.Provider;
+import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collection;
+import javax.annotation.Nonnull;
+
import org.opensaml.security.crypto.KeySupport;
import org.opensaml.security.x509.BasicX509Credential;
import org.opensaml.security.x509.X509Support;
@@ -129,53 +130,71 @@ public final class CredentialHelper {
}
/**
- * Reads in the X509 credentials from a PKCS11 source.
+ * Dump the list of available security providers for diagnostic purposes.
+ *
+ * @param message heading message to use before the list of providers
+ */
+ private static void dumpSecurityProviders(@Nonnull final String message) {
+ if (LOG.isDebugEnabled() ) {
+ LOG.debug(message);
+ for (final var provider : Security.getProviders()) {
+ LOG.debug(" available security provider: {}", provider.getName());
+ }
+ }
+ }
+
+ /**
+ * Reads in an X.509 credential from a PKCS11 source.
*
- * @param keystoreProvider keystore provider class
- * @param pkcs11Config PKCS11 configuration file used by the keystore provider
+ * @param keystoreProvider keystore provider class (legacy: should now be <code>null</code>)
+ * @param pkcs11Config configuration file used by the PKCS#11 provider
* @param keyAlias private key keystore alias
* @param keyPassword private key password, may not be null
*
- * @return the credentials
+ * @return the credential
*
* @throws IOException if it is not possible to read the keystore
* @throws GeneralSecurityException if there is a problem loading the keystore, or loading the credential from it
*/
protected static BasicX509Credential getPKCS11Credential(final String keystoreProvider, final String pkcs11Config,
final String keyAlias, final String keyPassword) throws IOException, GeneralSecurityException {
- LOG.debug("Install PKCS11 provider");
- KeyStore keystore = null;
+ // Warn about the legacy use of --keystoreProvider
+ if (keystoreProvider != null) {
+ LOG.warn("The --keystoreProvider option is now ignored when used with --pkcs11Config; remove it");
+ }
+
+ dumpSecurityProviders("Acquiring PKCS11 keystore");
+
+ // Head off legacy use of --pkcs11Config DUMMY
+ if (!new File(pkcs11Config).exists()) {
+ LOG.error("PKCS#11 configuration file '{}' does not exist", pkcs11Config);
+ throw new IOException("PKCS#11 configuration file '" + pkcs11Config + "' does not exist");
+ }
+
try {
- if (keystoreProvider != null) {
- LOG.debug("Creating PKCS11 keystore with provider {} and configuration file {}", keystoreProvider,
- pkcs11Config);
- final Class<Provider> providerClass =
- (Class<Provider>) CredentialHelper.class.getClassLoader().loadClass(keystoreProvider);
- final Constructor<Provider> providerConstructor = providerClass.getConstructor(String.class);
- final Provider pkcs11Provider = providerConstructor.newInstance(pkcs11Config);
- pkcs11Provider.load(new FileInputStream(pkcs11Config));
- Security.addProvider(pkcs11Provider);
- keystore = KeyStore.getInstance("PKCS11", pkcs11Provider);
- } else {
- LOG.debug("Creating PKCS11 keystore with system wide provider and configuration file");
- keystore = KeyStore.getInstance("PKCS11");
+ LOG.debug("Creating PKCS11 keystore with configuration file {}", pkcs11Config);
+
+ final var baseProvider = Security.getProvider("SunPKCS11");
+ if (baseProvider == null) {
+ throw new NoSuchProviderException("could not acquire unconfigured PKCS#11 provider");
}
- } catch (final ClassNotFoundException e) {
- LOG.error((new StringBuilder("Unable to load keystore provider class: ")).append(keystoreProvider)
- .toString());
- throw new Terminator(ReturnCode.RC_INIT);
- } catch (final NoSuchMethodException e) {
- LOG.error("Keystore provider class does not provide a String-argument constructor");
- throw new Terminator(ReturnCode.RC_INIT);
+ LOG.debug("Unconfigured PKCS#11 provider: " + baseProvider.getName());
+ final var pkcs11Provider = baseProvider.configure(pkcs11Config);
+ LOG.debug("Configured PKCS#11 provider: " + pkcs11Provider.getName());
+
+ Security.addProvider(pkcs11Provider);
+
+ final var keystore = KeyStore.getInstance("PKCS11", pkcs11Provider);
+ LOG.debug("Initializing PKCS11 keystore");
+ keystore.load(null, keyPassword.toCharArray());
+ return getCredentialFromKeystore(keystore, keyAlias, keyPassword);
+
} catch (final Exception e) {
LOG.error("Unable to read PKCS11 keystore: {}", e.getMessage());
throw new IOException("Unable to read PKCS11 keystore", e);
}
- LOG.debug("Initializing PKCS11 keystore");
- keystore.load(null, keyPassword.toCharArray());
- return getCredentialFromKeystore(keystore, keyAlias, keyPassword);
}
/**
diff --git a/src/test/java/net/shibboleth/tool/xmlsectool/XSTJ82Test.java b/src/test/java/net/shibboleth/tool/xmlsectool/XSTJ82Test.java
new file mode 100644
index 0000000..b76ce8b
--- /dev/null
+++ b/src/test/java/net/shibboleth/tool/xmlsectool/XSTJ82Test.java
@@ -0,0 +1,93 @@
+package net.shibboleth.tool.xmlsectool;
+
+import java.security.interfaces.RSAPublicKey;
+import java.util.List;
+
+import javax.xml.transform.dom.DOMSource;
+
+import org.opensaml.xmlsec.signature.KeyInfo;
+import org.opensaml.xmlsec.signature.KeyValue;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import net.shibboleth.utilities.java.support.xml.ElementSupport;
+import net.shibboleth.utilities.java.support.xml.SchemaBuilder.SchemaLanguage;
+
+/**
+ * Test for <code>--pkcs11Config</code> option under Java 11+.
+ *
+ * <p>
+ * It's really hard to provide tests for this bean that will run anywhere, because
+ * by definition it requires access to a PKCS#11 token, which is not something you'll
+ * find on any street corner.
+ * </p>
+ *
+ * <p>
+ * The approach taken here is to have a number of (by default <em>disabled</em> tests
+ * exercising specific scenarios with specific tokens.
+ * </p>
+ */
+public class XSTJ82Test extends BaseTest {
+
+ XSTJ82Test() {
+ super(XSTJ82Test.class);
+ }
+
+ @Test(enabled = false)
+ public void xstj82() throws Exception {
+ // Locate the PKCS#11 configuration file
+ final var configFile = packageRelativeFile("softhsm.cfg");
+
+ // build command-line arguments
+ final String[] args = {
+ "--sign",
+ "--inFile", "in.xml",
+ "--outFile", "out.xml",
+ "--pkcs11Config", configFile.getAbsolutePath(),
+ "--keystoreProvider", "dummy",
+ "--keyPassword", "1234",
+ "--key", "key2048",
+ };
+ final CommandLineArguments cli = new CommandLineArguments();
+ cli.parseCommandLineArguments(args);
+ XMLSecTool.initLogging(cli);
+
+ // Deep unit test on the CredentialHelper's credential acquisition method
+ var cred = CredentialHelper.getPKCS11Credential(cli.getKeystoreProvider(), cli.getPkcs11Config(),
+ cli.getKey(), cli.getKeyPassword());
+ Assert.assertNotNull(cred);
+
+ var pubKey = cred.getPublicKey();
+ Assert.assertNotNull(pubKey);
+ Assert.assertEquals(pubKey.getAlgorithm(), "RSA");
+ Assert.assertTrue(pubKey instanceof RSAPublicKey);
+ var rsaPubKey = (RSAPublicKey) pubKey;
+ Assert.assertEquals(rsaPubKey.getModulus().bitLength(), 2048);
+
+ // acquire a document to sign
+ final Document xml = readXMLDocument("in.xml");
+
+ // perform signature operation
+ XMLSecTool.sign(cli, cred, xml);
+
+ // verify the signature using our own code for consistency
+ XMLSecTool.verifySignature(cli, cred, xml);
+
+ // take a careful look at the signature
+ final Element signatureElement = XMLSecTool.getSignatureElement(xml);
+ final Element keyInfoElement = ElementSupport.getFirstChildElement(signatureElement,
+ KeyInfo.DEFAULT_ELEMENT_NAME);
+ final List<Element> keyInfoChildren = ElementSupport.getChildElements(keyInfoElement);
+ Assert.assertFalse(keyInfoChildren.isEmpty());
+ final List<Element> keyValues = ElementSupport.getChildElements(keyInfoElement, KeyValue.DEFAULT_ELEMENT_NAME);
+ for (final Element keyValue : keyValues) {
+ Assert.assertNotNull(ElementSupport.getFirstChildElement(keyValue), "empty KeyValue element");
+ }
+
+ // validate the resulting XML; this will also show up any error
+ final SchemaValidator validator = new SchemaValidator(SchemaLanguage.XML, getSchemaDirectory());
+ validator.validate(new DOMSource(xml));
+ }
+}
diff --git a/src/test/resources/net/shibboleth/tool/xmlsectool/XSTJ82-in.xml b/src/test/resources/net/shibboleth/tool/xmlsectool/XSTJ82-in.xml
new file mode 100644
index 0000000..cd3c3f0
--- /dev/null
+++ b/src/test/resources/net/shibboleth/tool/xmlsectool/XSTJ82-in.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+ xmlns:ukfedlabel="http://ukfederation.org.uk/2006/11/label"
+ xmlns:shibmd="urn:mace:shibboleth:metadata:1.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:oasis:names:tc:SAML:2.0:metadata ../xml/saml-schema-metadata-2.0.xsd
+ urn:oasis:names:tc:SAML:metadata:algsupport ../xml/sstc-saml-metadata-algsupport-v1.0.xsd
+ urn:oasis:names:tc:SAML:metadata:ui ../xml/sstc-saml-metadata-ui-v1.0.xsd
+ urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol ../xml/sstc-saml-idp-discovery.xsd
+ urn:oasis:names:tc:SAML:profiles:SSO:request-init ../xml/sstc-request-initiation.xsd
+ urn:mace:shibboleth:metadata:1.0 ../xml/shibboleth-metadata-1.0.xsd
+ http://ukfederation.org.uk/2006/11/label ../xml/uk-fed-label.xsd
+ http://www.w3.org/2001/04/xmlenc# ../xml/xenc-schema.xsd
+ http://www.w3.org/2000/09/xmldsig# ../xml/xmldsig-core-schema.xsd"
+ ID="uk001480" entityID="https://idp.shibboleth.net/idp/shibboleth">
+ <!--
+ This is a shibboleth.net Shibboleth 2 IdP for the JISC Services Management Company Ltd.
+ -->
+ <Extensions>
+ <shibmd:Scope regexp="false">shibboleth.net</shibmd:Scope>
+ <ukfedlabel:UKFederationMember/>
+ <ukfedlabel:ExportOptIn date="2011-12-07"/>
+ <ukfedlabel:Software fullVersion="2.3.8" version="2" name="Shibboleth" date="2012-12-07"/>
+ <alg:DigestMethod xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport"
+ Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/>
+ <alg:DigestMethod xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport"
+ Algorithm="http://www.w3.org/2001/04/xmldsig-more#sha384"/>
+ <alg:DigestMethod xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport"
+ Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
+ <alg:DigestMethod xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport"
+ Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <alg:SigningMethod xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport"
+ Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"/>
+ <alg:SigningMethod xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport"
+ Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"/>
+ <alg:SigningMethod xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport"
+ Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
+ <alg:SigningMethod xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport"
+ Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+ </Extensions>
+ <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+ <Extensions>
+ <shibmd:Scope regexp="false">shibboleth.net</shibmd:Scope>
+ <mdui:UIInfo xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui">
+ <mdui:DisplayName xml:lang="en">Shibboleth.net</mdui:DisplayName>
+ <mdui:Description xml:lang="en">An identity provider hosted and used by the
+ developers of Shibboleth.</mdui:Description>
+ <mdui:Logo height="82" width="64">https://shibboleth.net/images/gryphon_64x82.png</mdui:Logo>
+ </mdui:UIInfo>
+ </Extensions>
+ <KeyDescriptor>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>
+ MIIDNDCCAhygAwIBAgIVAKyBWnv1/h1U11C7kHvV33FIrEsJMA0GCSqGSIb3DQEB
+ BQUAMB0xGzAZBgNVBAMTEmlkcC5zaGliYm9sZXRoLm5ldDAeFw0xMDEyMjkwMDA5
+ MTlaFw0zMDEyMjkwMDA5MTlaMB0xGzAZBgNVBAMTEmlkcC5zaGliYm9sZXRoLm5l
+ dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKjWAdpUx/82FUzrRMfA
+ M63PkZZYCm3RnT3eiL+DeJcbGdcEJx/o+32vgHXJgJOBt14YdVam5GErIYgk4SGq
+ 5Z5RYl0PpQn6HQG/9prGnYCu6p5zfb0557o51Eh8TcVehS6Y2ruyCjAF0jgVMwh5
+ /0Oh8EE9wG93pSpm70DAiiaTVCb8WoT1aZYtxbBmmuH10bU+wge/NMmaHuVAe599
+ pyezFIL4FoI2g+1Q6nG4Yl1Z07I81tTApXKVMWRt/4/M3m2D7PUMOQ9qsxthp2L/
+ LovIeNo0bTyeW290T2Y/JRZhKOgeDqkhuu82DPri2Vm5G/unB69KfRB7CF9QWIc3
+ y80CAwEAAaNrMGkwSAYDVR0RBEEwP4ISaWRwLnNoaWJib2xldGgubmV0hilodHRw
+ czovL2lkcC5zaGliYm9sZXRoLm5ldC9pZHAvc2hpYmJvbGV0aDAdBgNVHQ4EFgQU
+ 3uZ32tKXJBzPCTp2dtHSLV0FvGgwDQYJKoZIhvcNAQEFBQADggEBAAYXYuzp0UTj
+ 3yLRvUCbEtaw9b80+weOELkVv3WFY3QAG8pIKEblrMMtzrzLFWZwYwwMZDab/HnH
+ egmgjZBthrOedEmoJ+OHRmIiS8zdZxVGEadJhTUaeIkO6kwK7Ht3nQePoiXV7TI5
+ +A9SpmZGoukC85Za4wGDw4xWGs5t5l6tBuuV+1s0oC6T8ih5n/NyThfpbihSW0d7
+ iBfSUickgpoM2BLM3FCnbO8HOsX1rGV4ypG9ZGDDvr2jrzalXXmc05gSlL2qd9ce
+ Q1M+9vavusPCqlj2zZf2/HfzhyiFcb/OgA0oTFWW2ynXji6UarIV5QaPoi/XmGmx
+ BXD36HfGBXk=
+ </ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
+ <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes192-cbc"/>
+ <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
+ <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
+ <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>
+ </KeyDescriptor>
+ <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
+ <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
+ Location="https://shibboleth.net/idp/profile/SAML2/POST/SSO"/>
+ <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
+ Location="https://shibboleth.net/idp/profile/SAML2/POST-SimpleSign/SSO"/>
+ <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
+ Location="https://shibboleth.net/idp/profile/SAML2/Redirect/SSO"/>
+ </IDPSSODescriptor>
+ <Organization>
+ <OrganizationName xml:lang="en">JISC Services Management Company Ltd</OrganizationName>
+ <OrganizationDisplayName xml:lang="en">Shibboleth.net</OrganizationDisplayName>
+ <OrganizationURL xml:lang="en">http://www.shibboleth.net/</OrganizationURL>
+ </Organization>
+ <ContactPerson contactType="support">
+ <GivenName>Shibboleth.Net Technical Support</GivenName>
+ <EmailAddress>mailto:contact at shibboleth.net</EmailAddress>
+ </ContactPerson>
+ <ContactPerson contactType="technical">
+ <GivenName>Scott</GivenName>
+ <SurName>Cantor</SurName>
+ <EmailAddress>mailto:cantor.2 at osu.edu</EmailAddress>
+ </ContactPerson>
+ <ContactPerson contactType="technical">
+ <GivenName>Ian</GivenName>
+ <SurName>Young</SurName>
+ <EmailAddress>mailto:ukfed at iay.org.uk</EmailAddress>
+ </ContactPerson>
+ <ContactPerson contactType="administrative">
+ <GivenName>Scott</GivenName>
+ <SurName>Cantor</SurName>
+ <EmailAddress>mailto:cantor.2 at osu.edu</EmailAddress>
+ </ContactPerson>
+ <ContactPerson contactType="administrative">
+ <GivenName>Ian</GivenName>
+ <SurName>Young</SurName>
+ <EmailAddress>mailto:ian at iay.org.uk</EmailAddress>
+ </ContactPerson>
+</EntityDescriptor>
diff --git a/src/test/resources/net/shibboleth/tool/xmlsectool/softhsm.cfg b/src/test/resources/net/shibboleth/tool/xmlsectool/softhsm.cfg
new file mode 100644
index 0000000..3ca23ff
--- /dev/null
+++ b/src/test/resources/net/shibboleth/tool/xmlsectool/softhsm.cfg
@@ -0,0 +1,8 @@
+#
+# PKCS#11 provider configuration for SoftHSM running under macOS.
+#
+# Note: this configuration assumes that SoftHSM has been installed using
+# the MacPorts system.
+#
+name = SoftHSM-resource
+library = /opt/local/lib/softhsm/libsofthsm2.so
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list