CryptoCipherFactory.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF 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 org.apache.commons.crypto.cipher;
- import java.security.GeneralSecurityException;
- import java.util.List;
- import java.util.Properties;
- import org.apache.commons.crypto.Crypto;
- import org.apache.commons.crypto.utils.ReflectionUtils;
- import org.apache.commons.crypto.utils.Utils;
- /**
- * Creates {@link CryptoCipher} instances.
- */
- public class CryptoCipherFactory {
- /**
- * Defines the internal CryptoCipher implementations.
- * <p>
- * Usage:
- * </p>
- * <blockquote><pre>
- * props.setProperty(CryptoCipherFactory.CLASSES_KEY, CipherProvider.OPENSSL.getClassName());
- * props.setProperty(...); // if required by the implementation
- * cipher = CryptoCipherFactory.getInstance(transformation, props);
- * </pre></blockquote>
- */
- public enum CipherProvider {
- /**
- * The OpenSSL cipher implementation (using JNI)
- * <p>
- * This implementation does not use any properties
- * </p>
- */
- // Please ensure the property description agrees with the implementation
- OPENSSL(OpenSslCipher.class),
- /**
- * The JCE cipher implementation from the JVM
- * <p>
- * uses the property {@link #JCE_PROVIDER_KEY}
- * to define the provider name, if present.
- * </p>
- */
- // Please ensure the property description agrees with the implementation
- JCE(JceCipher.class);
- private final Class<? extends CryptoCipher> klass;
- private final String className;
- /**
- * The private constructor.
- * @param klass the Class of CryptoCipher
- */
- CipherProvider(final Class<? extends CryptoCipher> klass) {
- this.klass = klass;
- this.className = klass.getName();
- }
- /**
- * Gets the class name of the provider.
- *
- * @return the fully qualified name of the provider class
- */
- public String getClassName() {
- return className;
- }
- /**
- * Gets the implementation class of the provider.
- *
- * @return the implementation class of the provider
- */
- public Class<? extends CryptoCipher> getImplClass() {
- return klass;
- }
- }
- /**
- * The configuration key of the provider class for JCE cipher.
- */
- public static final String JCE_PROVIDER_KEY = Crypto.CONF_PREFIX + "cipher.jce.provider";
- /**
- * The configuration key of the CryptoCipher implementation class.
- * <p>
- * The value of CLASSES_KEY needs to be the full name of a
- * class that implements the
- * {@link org.apache.commons.crypto.cipher.CryptoCipher CryptoCipher} interface
- * The internal classes are listed in the enum
- * {@link CipherProvider CipherProvider}
- * which can be used to obtain the full class name.
- * </p>
- * <p>
- * The value can also be a comma-separated list of class names in
- * order of descending priority.
- * </p>
- */
- public static final String CLASSES_KEY = Crypto.CONF_PREFIX + "cipher.classes";
- /**
- * For AES, the algorithm block is fixed size of 128 bits.
- *
- * @see <a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">
- * http://en.wikipedia.org/wiki/Advanced_Encryption_Standard</a>
- */
- public static final int AES_BLOCK_SIZE = 16;
- /**
- * The default value (OPENSSL,JCE) for crypto cipher.
- */
- private static final String CLASSES_DEFAULT =
- CipherProvider.OPENSSL.getClassName()
- .concat(",")
- .concat(CipherProvider.JCE.getClassName());
- /**
- * Gets the cipher class.
- *
- * @param props The {@code Properties} class represents a set of
- * properties.
- * @return the cipher class based on the props.
- */
- private static String getCipherClassString(final Properties props) {
- String cipherClassString = props.getProperty(CryptoCipherFactory.CLASSES_KEY, CLASSES_DEFAULT);
- if (cipherClassString.isEmpty()) { // TODO does it make sense to treat the empty string as the default?
- cipherClassString = CLASSES_DEFAULT;
- }
- return cipherClassString;
- }
- /**
- * Gets a cipher for algorithm/mode/padding in config value
- * commons.crypto.cipher.transformation
- *
- * @param transformation the name of the transformation, e.g.,
- * <i>AES/CBC/PKCS5Padding</i>.
- * See the Java Cryptography Architecture Standard Algorithm Name Documentation
- * for information about standard transformation names.
- * @return CryptoCipher the cipher object (defaults to OpenSslCipher if available, else JceCipher)
- * @throws GeneralSecurityException if JCE cipher initialize failed
- */
- public static CryptoCipher getCryptoCipher(final String transformation)
- throws GeneralSecurityException {
- return getCryptoCipher(transformation, new Properties());
- }
- /**
- * Gets a cipher instance for specified algorithm/mode/padding.
- *
- * @param properties the configuration properties - uses {@link #CLASSES_KEY}
- * @param transformation algorithm/mode/padding
- * @return CryptoCipher the cipher (defaults to OpenSslCipher)
- * @throws GeneralSecurityException if cipher initialize failed
- * @throws IllegalArgumentException if no classname(s) were provided
- */
- public static CryptoCipher getCryptoCipher(final String transformation, final Properties properties) throws GeneralSecurityException {
- final List<String> names = Utils.splitClassNames(getCipherClassString(properties), ",");
- if (names.isEmpty()) {
- throw new IllegalArgumentException("No classname(s) provided");
- }
- CryptoCipher cipher = null;
- Exception lastException = null;
- final StringBuilder errorMessage = new StringBuilder("CryptoCipher ");
- for (final String klass : names) {
- try {
- final Class<?> cls = ReflectionUtils.getClassByName(klass);
- cipher = ReflectionUtils.newInstance(cls.asSubclass(CryptoCipher.class), properties, transformation);
- break;
- } catch (final Exception e) {
- lastException = e;
- errorMessage.append("{" + klass + "}");
- }
- }
- if (cipher != null) {
- return cipher;
- }
- errorMessage.append(" is not available or transformation " + transformation + " is not supported.");
- throw new GeneralSecurityException(errorMessage.toString(), lastException);
- }
- /**
- * The private Constructor of {@link CryptoCipherFactory}.
- */
- private CryptoCipherFactory() {
- }
- }