[spring-extensions] branch master updated: JSE-20 - add PKCS11PrivateKeyFactoryBean
Ian Young
ian at iay.org.uk
Tue Oct 4 12:07:22 EDT 2016
This is an automated email from the git hooks/post-receive script.
iay pushed a commit to branch master
in repository spring-extensions.
View the commit online:
http://git.shibboleth.net/view/?p=spring-extensions.git;a=commit;h=7c60ba3f448a916a6231c90ce6bbf154f2ba4f50
The following commit(s) were added to refs/heads/master by this push:
new 7c60ba3 JSE-20 - add PKCS11PrivateKeyFactoryBean
7c60ba3 is described below
commit 7c60ba3f448a916a6231c90ce6bbf154f2ba4f50
Author: Ian Young <ian at iay.org.uk>
AuthorDate: Tue Oct 4 17:07:14 2016 +0100
JSE-20 - add PKCS11PrivateKeyFactoryBean
---
.../factory/PKCS11PrivateKeyFactoryBean.java | 190 +++++++++++++++++++++
1 file changed, 190 insertions(+)
diff --git a/src/main/java/net/shibboleth/ext/spring/factory/PKCS11PrivateKeyFactoryBean.java b/src/main/java/net/shibboleth/ext/spring/factory/PKCS11PrivateKeyFactoryBean.java
new file mode 100644
index 0000000..3625319
--- /dev/null
+++ b/src/main/java/net/shibboleth/ext/spring/factory/PKCS11PrivateKeyFactoryBean.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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.
+ */
+
+package net.shibboleth.ext.spring.factory;
+
+import java.lang.reflect.Constructor;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStore.PrivateKeyEntry;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.Security;
+
+import javax.annotation.Nonnull;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.FactoryBean;
+
+/**
+ * Spring bean factory for extracting a {@link PrivateKey} from a PKCS#11 keystore.
+ *
+ * This relies on the SunPKCS11 provider.
+ */
+public class PKCS11PrivateKeyFactoryBean implements FactoryBean<PrivateKey> {
+
+ /** The class name for the PKCS#11 provider class. */
+ private static final String PROVIDER_CLASS_NAME = "sun.security.pkcs11.SunPKCS11";
+
+ /** Singleton {@link Provider} for all instances of this factory. */
+ private static Provider provider;
+
+ /** Class logger. */
+ private final Logger log = LoggerFactory.getLogger(PKCS11PrivateKeyFactoryBean.class);
+
+ /** PKCS#11 provider parameter string. */
+ private String pkcs11Config;
+
+ /** Alias for the private key. */
+ private String keyAlias;
+
+ /** Password for the private key. */
+ private String keyPassword;
+
+ /** The singleton instance of the private key produced by this factory. */
+ private PrivateKey key;
+
+ /**
+ * Returns the PKCS#11 configuration.
+ *
+ * @return returns the PKCS#11 configuration.
+ */
+ public String getPkcs11Config() {
+ return pkcs11Config;
+ }
+
+ /**
+ * Sets the PKCS#11 configuration to use.
+ *
+ * @param config the PKCS#11 configuration to use
+ */
+ public void setPkcs11Config(@Nonnull final String config) {
+ pkcs11Config = config;
+ }
+
+ /**
+ * Gets the key alias in use.
+ *
+ * @return returns the key alias in use
+ */
+ public String getKeyAlias() {
+ return keyAlias;
+ }
+
+ /**
+ * Sets the key alias to use.
+ *
+ * @param alias the key alias to use
+ */
+ public void setKeyAlias(final String alias) {
+ keyAlias = alias;
+ }
+
+ /**
+ * Gets the key password in use.
+ *
+ * @return returns the key password in use
+ */
+ public String getKeyPassword() {
+ return keyPassword;
+ }
+
+ /**
+ * Set the key password to use.
+ *
+ * @param password the key password to use
+ */
+ public void setKeyPassword(@Nonnull final String password) {
+ keyPassword = password;
+ }
+
+ /**
+ * Gets the singleton PKCS#11 {@link Provider}.
+ *
+ * The constructed {@link Provider} is also added to the system's list of providers.
+ *
+ * @return the singleton {@link Provider}
+ * @throws Exception if something goes wrong building the {@link Provider}
+ */
+ @SuppressWarnings("unchecked")
+ private Provider getProvider() throws Exception {
+ if (provider == null) {
+ final ClassLoader loader = PKCS11PrivateKeyFactoryBean.class.getClassLoader();
+ try {
+ final Class<Provider> providerClass = (Class<Provider>) loader.loadClass(PROVIDER_CLASS_NAME);
+ final Constructor<Provider> providerConstructor = providerClass.getConstructor(String.class);
+ provider = providerConstructor.newInstance(pkcs11Config);
+ Security.addProvider(provider);
+ } catch (final ClassNotFoundException e) {
+ throw new NoSuchProviderException("unable to load keystore provider class " + PROVIDER_CLASS_NAME);
+ } catch (final NoSuchMethodException e) {
+ throw new NoSuchProviderException("keystore provider class " + PROVIDER_CLASS_NAME
+ + " does not provide a String-argument constructor ");
+ }
+ }
+ return provider;
+ }
+
+ /**
+ * Gets a PKCS#11 {@link KeyStore} from the {@link Provider}.
+ *
+ * @return the {@link KeyStore}
+ * @throws Exception if something goes wrong building the keystore
+ */
+ private KeyStore getKeyStore() throws Exception {
+ final KeyStore keystore = KeyStore.getInstance("PKCS11", getProvider());
+
+ log.debug("Initializing PKCS11 keystore");
+ keystore.load(null, keyPassword.toCharArray());
+ return keystore;
+ }
+
+ @Override
+ public PrivateKey getObject() throws Exception {
+ if (key == null) {
+ final KeyStore keystore = getKeyStore();
+
+ final KeyStore.Entry keyEntry = keystore.getEntry(keyAlias,
+ new KeyStore.PasswordProtection(keyPassword.toCharArray()));
+ if (keyEntry == null) {
+ throw new GeneralSecurityException("entry " + keyAlias + " not found");
+ }
+
+ if (keyEntry instanceof PrivateKeyEntry) {
+ final PrivateKeyEntry privKeyEntry = (PrivateKeyEntry) keyEntry;
+ key = privKeyEntry.getPrivateKey();
+ } else {
+ throw new GeneralSecurityException("entry " + keyAlias + " is not a private key entry");
+ }
+ }
+
+ return key;
+ }
+
+ @Override
+ @Nonnull public Class<?> getObjectType() {
+ return PrivateKey.class;
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return true;
+ }
+
+}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list