http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/com/intel/chimera/stream/output/StreamOutput.java ---------------------------------------------------------------------- diff --git a/src/main/java/com/intel/chimera/stream/output/StreamOutput.java b/src/main/java/com/intel/chimera/stream/output/StreamOutput.java deleted file mode 100644 index fdf0f03..0000000 --- a/src/main/java/com/intel/chimera/stream/output/StreamOutput.java +++ /dev/null @@ -1,101 +0,0 @@ -/** - * 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 com.intel.chimera.stream.output; - -import java.io.IOException; -import java.io.OutputStream; -import java.nio.ByteBuffer; - -/** - * The StreamOutput class takes a <code>OutputStream</code> object and wraps it as - * <code>Output</code> object acceptable by <code>CryptoOutputStream</code> as the output target. - */ -public class StreamOutput implements Output { - private byte[] buf; - private int bufferSize; - protected OutputStream out; - - /** - * Constructs a {@link com.intel.chimera.stream.output.StreamOutput}. - * - * @param out the OutputStream object. - * @param bufferSize the buffersize. - */ - public StreamOutput(OutputStream out, int bufferSize) { - this.out = out; - this.bufferSize = bufferSize; - } - - /** - * Overrides the {@link com.intel.chimera.stream.output.Output#write(ByteBuffer)}. - * Writes a sequence of bytes to this output from the given buffer. - * - * @param src - * The buffer from which bytes are to be retrieved. - * - * @return The number of bytes written, possibly zero. - * @throws IOException if an I/O error occurs. - */ - @Override - public int write(ByteBuffer src) throws IOException { - final int len = src.remaining(); - final byte[] buf = getBuf(); - - int remaining = len; - while(remaining > 0) { - final int n = Math.min(remaining, bufferSize); - src.get(buf, 0, n); - out.write(buf, 0, n); - remaining = src.remaining(); - } - - return len; - } - - /** - * Overrides the {@link Output#flush()}. - * Flushes this output and forces any buffered output bytes - * to be written out if the under layer output method support. - * - * @throws IOException if an I/O error occurs. - */ - @Override - public void flush() throws IOException { - out.flush(); - } - - /** - * Overrides the {@link Output#close()}. - * Closes this output and releases any system resources associated - * with the under layer output. - * - * @throws IOException if an I/O error occurs. - */ - @Override - public void close() throws IOException { - out.close(); - } - - private byte[] getBuf() { - if (buf == null) { - buf = new byte[bufferSize]; - } - return buf; - } - -}
http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/com/intel/chimera/utils/IOUtils.java ---------------------------------------------------------------------- diff --git a/src/main/java/com/intel/chimera/utils/IOUtils.java b/src/main/java/com/intel/chimera/utils/IOUtils.java deleted file mode 100644 index 05986fb..0000000 --- a/src/main/java/com/intel/chimera/utils/IOUtils.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * 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 com.intel.chimera.utils; - -import java.io.IOException; -import java.io.InputStream; - -import com.intel.chimera.stream.input.Input; -import org.apache.commons.logging.Log; - -/** - * General utility methods for working with IO. - */ -public class IOUtils { - - /** - * Does the readFully based on the Input read. - * - * @param in the input stream of bytes. - * @param buf the buffer to be read. - * @param off the start offset in array buffer. - * @param len the maximum number of bytes to read. - * @throws IOException if an I/O error occurs. - */ - public static void readFully(InputStream in, byte buf[], - int off, int len) throws IOException { - int toRead = len; - while (toRead > 0) { - int ret = in.read(buf, off, toRead); - if (ret < 0) { - throw new IOException( "Premature EOF from inputStream"); - } - toRead -= ret; - off += ret; - } - } - - /** - * Does the readFully based on Input's positioned read. - * This does not change the current offset of the stream and is thread-safe. - * - * @param in the input source. - * @param position the given position. - * @param buffer the buffer to be read. - * @param length the maximum number of bytes to read. - * @param offset the start offset in array buffer. - * @throws IOException if an I/O error occurs. - */ - public static void readFully(Input in, long position, - byte[] buffer, int offset, int length) throws IOException { - int nread = 0; - while (nread < length) { - int nbytes = in.read(position+nread, buffer, offset+nread, length-nread); - if (nbytes < 0) { - throw new IOException("End of stream reached before reading fully."); - } - nread += nbytes; - } - } - - /** - * Closes the Closeable objects and <b>ignore</b> any {@link IOException} or - * null pointers. Must only be used for cleanup in exception handlers. - * - * @param log the log to record problems to at debug level. Can be null. - * @param closeables the objects to close. - */ - public static void cleanup(Log log, java.io.Closeable... closeables) { - for (java.io.Closeable c : closeables) { - if (c != null) { - try { - c.close(); - } catch(Throwable e) { - if (log != null && log.isDebugEnabled()) { - log.debug("Exception in closing " + c, e); - } - } - } - } - } -} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/com/intel/chimera/utils/NativeCodeLoader.java ---------------------------------------------------------------------- diff --git a/src/main/java/com/intel/chimera/utils/NativeCodeLoader.java b/src/main/java/com/intel/chimera/utils/NativeCodeLoader.java deleted file mode 100644 index 224750a..0000000 --- a/src/main/java/com/intel/chimera/utils/NativeCodeLoader.java +++ /dev/null @@ -1,279 +0,0 @@ -/** - * 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 com.intel.chimera.utils; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Properties; -import java.util.UUID; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - - -/** - * A helper to load the native code i.e. libchimera.so. - * This handles the fallback to either the bundled libchimera-Linux-i386-32.so - * or the default java implementations where appropriate. - */ -public class NativeCodeLoader { - - private static final Log LOG = - LogFactory.getLog(NativeCodeLoader.class); - - private static boolean nativeCodeLoaded = false; - - static { - // Try to load native library and set fallback flag appropriately - if(LOG.isDebugEnabled()) { - LOG.debug("Trying to load the custom-built native-chimera library..."); - } - - try { - File nativeLibFile = findNativeLibrary(); - if (nativeLibFile != null) { - // Load extracted or specified native library. - System.load(nativeLibFile.getAbsolutePath()); - } else { - // Load preinstalled library (in the path -Djava.library.path) - System.loadLibrary("chimera"); - } - LOG.debug("Loaded the native library"); - nativeCodeLoaded = true; - } catch (Throwable t) { - // Ignore failure to load - if(LOG.isDebugEnabled()) { - LOG.debug("Failed to load native library with error: " + t); - LOG.debug("java.library.path=" + - System.getProperty("java.library.path")); - } - } - - if (!nativeCodeLoaded) { - LOG.warn("Unable to load native library for the platform... " + - "using builtin-java classes where applicable"); - } - } - - static File findNativeLibrary() { - // Try to load the library in chimera.lib.path */ - String nativeLibraryPath = Utils - .getLibPath(); - String nativeLibraryName = Utils - .getLibName(); - - // Resolve the library file name with a suffix (e.g., dll, .so, etc.) - if (nativeLibraryName == null) - nativeLibraryName = System.mapLibraryName("chimera"); - - if (nativeLibraryPath != null) { - File nativeLib = new File(nativeLibraryPath, - nativeLibraryName); - if (nativeLib.exists()) - return nativeLib; - } - - // Load an OS-dependent native library inside a jar file - nativeLibraryPath = "/com/intel/chimera/native/" - + OSInfo.getNativeLibFolderPathForCurrentOS(); - boolean hasNativeLib = hasResource(nativeLibraryPath + "/" - + nativeLibraryName); - if(!hasNativeLib) { - if (OSInfo.getOSName().equals("Mac")) { - // Fix for openjdk7 for Mac - String altName = "libchimera.jnilib"; - if (hasResource(nativeLibraryPath + "/" + altName)) { - nativeLibraryName = altName; - hasNativeLib = true; - } - } - } - - if (!hasNativeLib) { - String errorMessage = String.format( - "no native library is found for os.name=%s and os.arch=%s", - OSInfo.getOSName(), OSInfo.getArchName()); - throw new RuntimeException(errorMessage); - } - - // Temporary folder for the native lib. Use the value of - // chimera.tempdir or java.io.tmpdir - String tempFolder = new File(Utils.getTmpDir()) - .getAbsolutePath(); - - // Extract and load a native library inside the jar file - return extractLibraryFile(nativeLibraryPath, - nativeLibraryName, tempFolder); - } - - /** - * Extracts the specified library file to the target folder. - * - * @param libFolderForCurrentOS the library in chimera.lib.path. - * @param libraryFileName the library name. - * @param targetFolder Target folder for the native lib. Use the value of - * chimera.tempdir or java.io.tmpdir. - * @return the library file. - */ - private static File extractLibraryFile(String libFolderForCurrentOS, - String libraryFileName, String targetFolder) { - String nativeLibraryFilePath = libFolderForCurrentOS + "/" - + libraryFileName; - - // Attach UUID to the native library file to ensure multiple class loaders - // can read the libchimera multiple times. - String uuid = UUID.randomUUID().toString(); - String extractedLibFileName = String.format("chimera-%s-%s-%s", getVersion(), uuid, - libraryFileName); - File extractedLibFile = new File(targetFolder, extractedLibFileName); - - InputStream reader = null; - try { - // Extract a native library file into the target directory - reader = NativeCodeLoader.class.getResourceAsStream(nativeLibraryFilePath); - FileOutputStream writer = new FileOutputStream(extractedLibFile); - try { - byte[] buffer = new byte[8192]; - int bytesRead; - while ((bytesRead = reader.read(buffer)) != -1) { - writer.write(buffer, 0, bytesRead); - } - } finally { - // Delete the extracted lib file on JVM exit. - extractedLibFile.deleteOnExit(); - - if (writer != null){ - writer.close(); - } - - if (reader != null) { - reader.close(); - reader = null; - } - } - - // Set executable (x) flag to enable Java to load the native library - if (!extractedLibFile.setReadable(true) || !extractedLibFile.setExecutable(true) - || !extractedLibFile.setWritable(true, true)) { - throw new RuntimeException("Invalid path for library path"); - } - - // Check whether the contents are properly copied from the resource folder - { - InputStream nativeIn = null; - InputStream extractedLibIn = null; - try { - nativeIn = - NativeCodeLoader.class.getResourceAsStream(nativeLibraryFilePath); - extractedLibIn = new FileInputStream(extractedLibFile); - if (!contentsEquals(nativeIn, extractedLibIn)) - throw new RuntimeException(String.format( - "Failed to write a native library file at %s", - extractedLibFile)); - } finally { - if (nativeIn != null) - nativeIn.close(); - if (extractedLibIn != null) - extractedLibIn.close(); - } - } - - return new File(targetFolder, extractedLibFileName); - } catch (IOException e) { - e.printStackTrace(System.err); - return null; - } finally{ - if(reader != null){ - try { - reader.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - - /** - * Gets the version by reading pom.properties embedded in jar. - * This version data is used as a suffix of a dll file extracted from the - * jar. - * - * @return the version string - */ - public static String getVersion() { - URL versionFile = NativeCodeLoader.class - .getResource("/META-INF/maven/com.intel.chimera/chimera/pom.properties"); - if (versionFile == null) - versionFile = NativeCodeLoader.class - .getResource("/com/intel/chimera/VERSION"); - - String version = "unknown"; - try { - if (versionFile != null) { - Properties versionData = new Properties(); - versionData.load(versionFile.openStream()); - version = versionData.getProperty("version", version); - if (version.equals("unknown")) - version = versionData.getProperty("VERSION", version); - version = version.trim().replaceAll("[^0-9M\\.]", ""); - } - } catch (IOException e) { - System.err.println(e); - } - return version; - } - - private static boolean contentsEquals(InputStream in1, InputStream in2) - throws IOException { - if (!(in1 instanceof BufferedInputStream)) { - in1 = new BufferedInputStream(in1); - } - if (!(in2 instanceof BufferedInputStream)) { - in2 = new BufferedInputStream(in2); - } - - int ch = in1.read(); - while (ch != -1) { - int ch2 = in2.read(); - if (ch != ch2) - return false; - ch = in1.read(); - } - int ch2 = in2.read(); - return ch2 == -1; - } - - private static boolean hasResource(String path) { - return NativeCodeLoader.class.getResource(path) != null; - } - - /** - * Checks whether native code is loaded for this platform. - * - * @return <code>true</code> if native is loaded, - * else <code>false</code>. - */ - public static boolean isNativeCodeLoaded() { - return nativeCodeLoaded; - } -} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/com/intel/chimera/utils/OSInfo.java ---------------------------------------------------------------------- diff --git a/src/main/java/com/intel/chimera/utils/OSInfo.java b/src/main/java/com/intel/chimera/utils/OSInfo.java deleted file mode 100644 index c979599..0000000 --- a/src/main/java/com/intel/chimera/utils/OSInfo.java +++ /dev/null @@ -1,190 +0,0 @@ -/** - * 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 com.intel.chimera.utils; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Locale; - -/** - * Provides OS name and architecture name. - */ -public class OSInfo { - private static HashMap<String, String> archMapping = new HashMap<String, String>(); - - /** - * The constant string represents for X86 architecture, the value is: {@value #X86}.*/ - public static final String X86 = "x86"; - - /** - * The constant string represents for X86_64 architecture, the value is:{@value #X86_64}.*/ - public static final String X86_64 = "x86_64"; - - /** - * The constant string represents for IA64_32 architecture, the value is:{@value #IA64_32}.*/ - public static final String IA64_32 = "ia64_32"; - - /** - * The constant string represents for IA64 architecture, the value is:{@value #IA64}.*/ - public static final String IA64 = "ia64"; - - /** - * The constant string represents for PPC architecture, the value is:{@value #PPC}.*/ - public static final String PPC = "ppc"; - - /** - * The constant string represents for PPC64 architecture, the value is:{@value #PPC64}.*/ - public static final String PPC64 = "ppc64"; - - static { - // x86 mappings - archMapping.put(X86, X86); - archMapping.put("i386", X86); - archMapping.put("i486", X86); - archMapping.put("i586", X86); - archMapping.put("i686", X86); - archMapping.put("pentium", X86); - - // x86_64 mappings - archMapping.put(X86_64, X86_64); - archMapping.put("amd64", X86_64); - archMapping.put("em64t", X86_64); - archMapping.put("universal", X86_64); // Needed for openjdk7 in Mac - - // Itenium 64-bit mappings - archMapping.put(IA64, IA64); - archMapping.put("ia64w", IA64); - - // Itenium 32-bit mappings, usually an HP-UX construct - archMapping.put(IA64_32, IA64_32); - archMapping.put("ia64n", IA64_32); - - // PowerPC mappings - archMapping.put(PPC, PPC); - archMapping.put("power", PPC); - archMapping.put("powerpc", PPC); - archMapping.put("power_pc", PPC); - archMapping.put("power_rs", PPC); - - // TODO: PowerPC 64bit mappings - archMapping.put(PPC64, PPC64); - archMapping.put("power64", PPC64); - archMapping.put("powerpc64", PPC64); - archMapping.put("power_pc64", PPC64); - archMapping.put("power_rs64", PPC64); - } - - public static void main(String[] args) { - if (args.length >= 1) { - if ("--os".equals(args[0])) { - System.out.print(getOSName()); - return; - } else if ("--arch".equals(args[0])) { - System.out.print(getArchName()); - return; - } - } - - System.out.print(getNativeLibFolderPathForCurrentOS()); - } - - /** - * Gets the native lib folder. - * - * @return the current OS's native lib folder. - */ - public static String getNativeLibFolderPathForCurrentOS() { - return getOSName() + "/" + getArchName(); - } - - /** - * Gets the OS name. - * - * @return the OS name. - */ - public static String getOSName() { - return translateOSNameToFolderName(System.getProperty("os.name")); - } - - /** - * Gets the architecture name. - * - * @return the architecture name. - */ - public static String getArchName() { - // if running Linux on ARM, need to determine ABI of JVM - String osArch = System.getProperty("os.arch"); - if (osArch.startsWith("arm") - && System.getProperty("os.name").contains("Linux")) { - String javaHome = System.getProperty("java.home"); - try { - // determine if first JVM found uses ARM hard-float ABI - String[] cmdarray = { - "/bin/sh", - "-c", - "find '" + javaHome - + "' -name 'libjvm.so' | head -1 | xargs readelf -A | " - + "grep 'Tag_ABI_VFP_args: VFP registers'" }; - int exitCode = Runtime.getRuntime().exec(cmdarray).waitFor(); - if (exitCode == 0) - return "armhf"; - } catch (IOException e) { - // ignored: fall back to "arm" arch (soft-float ABI) - } catch (InterruptedException e) { - // ignored: fall back to "arm" arch (soft-float ABI) - } - } else { - String lc = osArch.toLowerCase(Locale.US); - if (archMapping.containsKey(lc)) - return archMapping.get(lc); - } - return translateArchNameToFolderName(osArch); - } - - /** - * Translates the OS name to folder name. - * - * @param osName the OS name. - * @return the folder name. - */ - static String translateOSNameToFolderName(String osName) { - if (osName.contains("Windows")) { - return "Windows"; - } else if (osName.contains("Mac")) { - return "Mac"; - } else if (osName.contains("Linux")) { - return "Linux"; - } else if (osName.contains("AIX")) { - return "AIX"; - } - - else { - return osName.replaceAll("\\W", ""); - } - } - - /** - * Translates the architecture name to folder name. - * - * @param archName the architecture name. - * @return the folder name. - */ - static String translateArchNameToFolderName(String archName) { - return archName.replaceAll("\\W", ""); - } -} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/com/intel/chimera/utils/ReflectionUtils.java ---------------------------------------------------------------------- diff --git a/src/main/java/com/intel/chimera/utils/ReflectionUtils.java b/src/main/java/com/intel/chimera/utils/ReflectionUtils.java deleted file mode 100644 index d40937a..0000000 --- a/src/main/java/com/intel/chimera/utils/ReflectionUtils.java +++ /dev/null @@ -1,204 +0,0 @@ -/** - * 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 com.intel.chimera.utils; - -import java.lang.ref.WeakReference; -import java.lang.reflect.Constructor; -import java.util.Collections; -import java.util.Map; -import java.util.WeakHashMap; - -import com.intel.chimera.cipher.Cipher; - -/** - * General utility methods for working with reflection. - */ -public class ReflectionUtils { - - private static final Map<ClassLoader, Map<String, WeakReference<Class<?>>>> - CACHE_CLASSES = new WeakHashMap<ClassLoader, Map<String, WeakReference<Class<?>>>>(); - - private static ClassLoader classLoader; - static { - classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = Cipher.class.getClassLoader(); - } - } - - /** - * Sentinel value to store negative cache results in {@link #CACHE_CLASSES}. - */ - private static final Class<?> NEGATIVE_CACHE_SENTINEL = - NegativeCacheSentinel.class; - - /** - * A unique class which is used as a sentinel value in the caching - * for getClassByName. {@link Cipher#getClassByNameOrNull(String)}. - */ - private static abstract class NegativeCacheSentinel {} - - /** - * Uses the constructor represented by this {@code Constructor} object to - * create and initialize a new instance of the constructor's - * declaring class, with the specified initialization parameters. - * - * @param klass the Class object. - * @param args array of objects to be passed as arguments to - * the constructor call. - * @return a new object created by calling the constructor - * this object represents. - */ - @SuppressWarnings("rawtypes") - public static <T> T newInstance(Class<T> klass, Object ... args) { - try { - Constructor<T> ctor = null; - - if (args.length == 0) { - ctor = klass.getDeclaredConstructor(new Class[] {}); - } else { - Class[] argClses = new Class[args.length]; - for (int i = 0; i < args.length; i++) { - argClses[i] = args[i].getClass(); - } - ctor = klass.getDeclaredConstructor(argClses); - } - ctor.setAccessible(true); - return ctor.newInstance(args); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Gets the value of the <code>name</code> property as a <code>Class</code> - * implementing the interface specified by <code>xface</code>. - * If no such property is specified, then <code>defaultValue</code> is - * returned.An exception is thrown if the returned class does not - * implement the named interface. - * - * @param name the class name of default implementation. - * @param defaultValue default value. - * @param xface the interface implemented by the named class. - * @return property value as a <code>Class</code>, - * or <code>defaultValue</code>. - */ - public static <U> Class<? extends U> getClass(String name, - Class<? extends U> defaultValue, - Class<U> xface) { - try { - Class<?> theClass = null; - if (name != null && !name.isEmpty()) { - theClass = getClassByName(name); - } - if (theClass == null) { - theClass = defaultValue; - } - if (theClass != null && !xface.isAssignableFrom(theClass)) - throw new RuntimeException(theClass+" not "+xface.getName()); - else if (theClass != null) - return theClass.asSubclass(xface); - else - return null; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Gets the value of the <code>name</code> property as a <code>Class</code>. - * If no such property is specified, then <code>defaultValue</code> is - * returned. - * - * @param name the class name. - * @param defaultValue default value. - * @return property value as a <code>Class</code>, - * or <code>defaultValue</code>. - */ - public static Class<?> getClass(String name, Class<?> defaultValue) { - String valueString = System.getProperty(name); - if (valueString == null) - return defaultValue; - try { - return getClassByName(valueString); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - /** - * Loads a class by name. - * - * @param name the class name. - * @return the class object. - * @throws ClassNotFoundException if the class is not found. - */ - public static Class<?> getClassByName(String name) - throws ClassNotFoundException { - Class<?> ret = getClassByNameOrNull(name); - if (ret == null) { - throw new ClassNotFoundException("Class " + name + " not found"); - } - return ret; - } - - /** - * Loads a class by name, returning null rather than throwing an exception - * if it couldn't be loaded. This is to avoid the overhead of creating - * an exception. - * - * @param name the class name. - * @return the class object, or null if it could not be found. - */ - private static Class<?> getClassByNameOrNull(String name) { - Map<String, WeakReference<Class<?>>> map; - - synchronized (CACHE_CLASSES) { - map = CACHE_CLASSES.get(classLoader); - if (map == null) { - map = Collections.synchronizedMap( - new WeakHashMap<String, WeakReference<Class<?>>>()); - CACHE_CLASSES.put(classLoader, map); - } - } - - Class<?> clazz = null; - WeakReference<Class<?>> ref = map.get(name); - if (ref != null) { - clazz = ref.get(); - } - - if (clazz == null) { - try { - clazz = Class.forName(name, true, classLoader); - } catch (ClassNotFoundException e) { - // Leave a marker that the class isn't found - map.put(name, new WeakReference<Class<?>>(NEGATIVE_CACHE_SENTINEL)); - return null; - } - // two putters can race here, but they'll put the same class - map.put(name, new WeakReference<Class<?>>(clazz)); - return clazz; - } else if (clazz == NEGATIVE_CACHE_SENTINEL) { - return null; // not found - } else { - // cache hit - return clazz; - } - } -} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/com/intel/chimera/utils/Utils.java ---------------------------------------------------------------------- diff --git a/src/main/java/com/intel/chimera/utils/Utils.java b/src/main/java/com/intel/chimera/utils/Utils.java deleted file mode 100644 index ae0eecc..0000000 --- a/src/main/java/com/intel/chimera/utils/Utils.java +++ /dev/null @@ -1,362 +0,0 @@ -/** - * 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 com.intel.chimera.utils; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.security.GeneralSecurityException; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; -import java.util.Properties; - -import com.intel.chimera.cipher.Cipher; -import com.intel.chimera.cipher.CipherFactory; -import com.intel.chimera.cipher.CipherTransformation; - -import static com.intel.chimera.conf.ConfigurationKeys.CHIMERA_CRYPTO_STREAM_BUFFER_SIZE_DEFAULT; -import static com.intel.chimera.conf.ConfigurationKeys.CHIMERA_CRYPTO_STREAM_BUFFER_SIZE_KEY; -import static com.intel.chimera.conf.ConfigurationKeys.CHIMERA_CRYPTO_CIPHER_CLASSES_DEFAULT; -import static com.intel.chimera.conf.ConfigurationKeys.CHIMERA_CRYPTO_CIPHER_CLASSES_KEY; -import static com.intel.chimera.conf.ConfigurationKeys.CHIMERA_CRYPTO_CIPHER_JCE_PROVIDER_KEY; -import static com.intel.chimera.conf.ConfigurationKeys.CHIMERA_CRYPTO_LIB_NAME_KEY; -import static com.intel.chimera.conf.ConfigurationKeys.CHIMERA_CRYPTO_LIB_PATH_KEY; -import static com.intel.chimera.conf.ConfigurationKeys.CHIMERA_CRYPTO_SECURE_RANDOM_DEVICE_FILE_PATH_DEFAULT; -import static com.intel.chimera.conf.ConfigurationKeys.CHIMERA_CRYPTO_SECURE_RANDOM_DEVICE_FILE_PATH_KEY; -import static com.intel.chimera.conf.ConfigurationKeys.CHIMERA_SYSTEM_PROPERTIES_FILE; -import static com.intel.chimera.conf.ConfigurationKeys.CHIMERA_CRYPTO_LIB_TEMPDIR_KEY; - -/** - * General utility methods. - */ -public class Utils { - private static final int MIN_BUFFER_SIZE = 512; - - protected static final CipherTransformation AES_CTR_NOPADDING = CipherTransformation.AES_CTR_NOPADDING; - - /** - * For AES, the algorithm block is fixed size of 128 bits. - * @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard - */ - private static final int AES_BLOCK_SIZE = AES_CTR_NOPADDING.getAlgorithmBlockSize(); - - static { - loadChimeraSystemProperties(); - } - - /** - * loads system properties when configuration file of the name - * {@link #CHIMERA_SYSTEM_PROPERTIES_FILE} is found. - */ - private static void loadChimeraSystemProperties() { - try { - InputStream is = Thread.currentThread().getContextClassLoader() - .getResourceAsStream(CHIMERA_SYSTEM_PROPERTIES_FILE); - - if (is == null) - return; // no configuration file is found - - // Load property file - Properties props = new Properties(); - props.load(is); - is.close(); - Enumeration<?> names = props.propertyNames(); - while (names.hasMoreElements()) { - String name = (String) names.nextElement(); - if (name.startsWith("chimera.")) { - if (System.getProperty(name) == null) { - System.setProperty(name, props.getProperty(name)); - } - } - } - } catch (Throwable ex) { - System.err.println("Could not load '" - + CHIMERA_SYSTEM_PROPERTIES_FILE + "' from classpath: " - + ex.toString()); - } - } - - /** - * Forcibly free the direct buffer. - * - * @param buffer the bytebuffer to be freed. - */ - public static void freeDirectBuffer(ByteBuffer buffer) { - if (buffer instanceof sun.nio.ch.DirectBuffer) { - final sun.misc.Cleaner bufferCleaner = - ((sun.nio.ch.DirectBuffer) buffer).cleaner(); - bufferCleaner.clean(); - } - } - - /** - * Reads crypto buffer size. - * - * @param props The <code>Properties</code> class represents a set of - * properties. - * @return the buffer size. - * */ - public static int getBufferSize(Properties props) { - String bufferSizeStr = props.getProperty( - CHIMERA_CRYPTO_STREAM_BUFFER_SIZE_KEY); - if (bufferSizeStr == null || bufferSizeStr.isEmpty()) { - bufferSizeStr = System - .getProperty(CHIMERA_CRYPTO_STREAM_BUFFER_SIZE_KEY); - } - if (bufferSizeStr == null || bufferSizeStr.isEmpty()) { - return CHIMERA_CRYPTO_STREAM_BUFFER_SIZE_DEFAULT; - } else { - return Integer.parseInt(bufferSizeStr); - } - } - - /** - * Gets the cipher class. - * - * @param props The <code>Properties</code> class represents a set of - * properties. - * @return the cipher class based on the props. - */ - public static String getCipherClassString(Properties props) { - final String configName = CHIMERA_CRYPTO_CIPHER_CLASSES_KEY; - return props.getProperty(configName) != null ? props.getProperty(configName) : System - .getProperty(configName, CHIMERA_CRYPTO_CIPHER_CLASSES_DEFAULT); - } - - /** - * Gets the Jce provider. - * - * @param props The <code>Properties</code> class represents a set of - * properties. - * @return the jce provider based on the props. - */ - public static String getJCEProvider(Properties props) { - return props.getProperty(CHIMERA_CRYPTO_CIPHER_JCE_PROVIDER_KEY) != null ? - props.getProperty(CHIMERA_CRYPTO_CIPHER_JCE_PROVIDER_KEY) : - System.getProperty(CHIMERA_CRYPTO_CIPHER_JCE_PROVIDER_KEY); - } - - /** - * Gets the random device path. - * - * @param props The <code>Properties</code> class represents a set of - * properties. - * @return the random device path based on the props. - */ - public static String getRandomDevPath(Properties props) { - String devPath = props.getProperty( - CHIMERA_CRYPTO_SECURE_RANDOM_DEVICE_FILE_PATH_KEY); - if (devPath == null) { - devPath = System.getProperty( - CHIMERA_CRYPTO_SECURE_RANDOM_DEVICE_FILE_PATH_KEY, - CHIMERA_CRYPTO_SECURE_RANDOM_DEVICE_FILE_PATH_DEFAULT); - } - return devPath; - } - - /** - * Gets path of native library. - * - * @return the path of native library. - */ - public static String getLibPath() { - return System.getProperty(CHIMERA_CRYPTO_LIB_PATH_KEY); - } - - /** - * Gets the file name of native library. - * - * @return the file name of native library. - */ - public static String getLibName() { - return System.getProperty(CHIMERA_CRYPTO_LIB_NAME_KEY); - } - - /** - * Gets the temp directory for extracting crypto library. - * - * @return the temp directory. - */ - public static String getTmpDir() { - return System.getProperty(CHIMERA_CRYPTO_LIB_TEMPDIR_KEY, - System.getProperty("java.io.tmpdir")); - } - - /** - * Checks whether the cipher is supported streaming. - * - * @param cipher the {@link com.intel.chimera.cipher.Cipher} instance. - * @throws IOException if an I/O error occurs. - */ - public static void checkStreamCipher(Cipher cipher) throws IOException { - if (cipher.getTransformation() != CipherTransformation.AES_CTR_NOPADDING) { - throw new IOException("AES/CTR/NoPadding is required"); - } - } - - /** - * Checks and floors buffer size. - * - * @param cipher the {@link com.intel.chimera.cipher.Cipher} instance. - * @param bufferSize the buffer size. - * @return the remaining buffer size. - */ - public static int checkBufferSize(Cipher cipher, int bufferSize) { - checkArgument(bufferSize >= MIN_BUFFER_SIZE, - "Minimum value of buffer size is " + MIN_BUFFER_SIZE + "."); - return bufferSize - bufferSize % cipher.getTransformation() - .getAlgorithmBlockSize(); - } - - /** - * This method is only for Counter (CTR) mode. Generally the Cipher calculates the - * IV and maintain encryption context internally.For example a - * {@link javax.crypto.Cipher} will maintain its encryption context internally - * when we do encryption/decryption using the Cipher#update interface. - * <p/> - * Encryption/Decryption is not always on the entire file. For example, - * in Hadoop, a node may only decrypt a portion of a file (i.e. a split). - * In these situations, the counter is derived from the file position. - * <p/> - * The IV can be calculated by combining the initial IV and the counter with - * a lossless operation (concatenation, addition, or XOR). - * @see http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_.28CTR.29 - * - * @param initIV initial IV - * @param counter counter for input stream position - * @param IV the IV for input stream position - */ - public static void calculateIV(byte[] initIV, long counter, byte[] IV) { - checkArgument(initIV.length == AES_BLOCK_SIZE); - checkArgument(IV.length == AES_BLOCK_SIZE); - - int i = IV.length; // IV length - int j = 0; // counter bytes index - int sum = 0; - while (i-- > 0) { - // (sum >>> Byte.SIZE) is the carry for addition - sum = (initIV[i] & 0xff) + (sum >>> Byte.SIZE); - if (j++ < 8) { // Big-endian, and long is 8 bytes length - sum += (byte) counter & 0xff; - counter >>>= 8; - } - IV[i] = (byte) sum; - } - } - - /** - * Helper method to create a Cipher instance and throws only IOException. - * - * @param props The <code>Properties</code> class represents a set of - * properties. - * @param transformation the CipherTransformation instance. - * @return the Cipher instance. - * @throws IOException if an I/O error occurs. - */ - public static Cipher getCipherInstance(CipherTransformation transformation, - Properties props) throws IOException { - try { - return CipherFactory.getInstance(transformation, props); - } catch (GeneralSecurityException e) { - throw new IOException(e); - } - } - - /** - * Ensures the truth of an expression involving one or more parameters to - * the calling method. - * - * @param expression a boolean expression. - * @throws IllegalArgumentException if expression is false. - */ - public static void checkArgument(boolean expression) { - if(!expression) { - throw new IllegalArgumentException(); - } - } - - /** - * Checks the truth of an expression. - * - * @param expression a boolean expression. - * @param errorMessage the exception message to use if the check fails; - * will be converted to a string using <code>String - * .valueOf(Object)</code>. - * @throws IllegalArgumentException if expression is false. - */ - public static void checkArgument(boolean expression, Object errorMessage) { - if (!expression) { - throw new IllegalArgumentException(String.valueOf(errorMessage)); - } - } - - /** - * Ensures that an object reference passed as a parameter to the calling - * method is not null. - * - * @param reference an object reference. - * @return the non-null reference that was validated. - * @throws NullPointerException if reference is null. - */ - public static <T> T checkNotNull(T reference) { - if(reference == null) { - throw new NullPointerException(); - } else { - return reference; - } - } - - /** - * Ensures the truth of an expression involving the state of the calling - * instance, but not involving any parameters to the calling method. - * - * @param expression a boolean expression. - * @throws IllegalStateException if expression is false. - */ - public static void checkState(boolean expression) { - if(!expression) { - throw new IllegalStateException(); - } - } - - /** - * Splits class names sequence into substrings, Trim each substring into an - * entry,and returns an list of the entries. - * - * @param clazzNames a string consist of a list of the entries joined by a - * delimiter. - * @param separator a delimiter for the input string. - * @return a list of class entries. - */ - public static List<String> splitClassNames(String clazzNames, - String separator) { - List<String> res = new ArrayList<String>(); - if (clazzNames == null || clazzNames.isEmpty()) { - return res; - } - - for (String clazzName : clazzNames.split(separator)) { - clazzName = clazzName.trim(); - if (!clazzName.isEmpty()) { - res.add(clazzName); - } - } - return res; - } -} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/com/intel/chimera/utils/package-info.java ---------------------------------------------------------------------- diff --git a/src/main/java/com/intel/chimera/utils/package-info.java b/src/main/java/com/intel/chimera/utils/package-info.java deleted file mode 100644 index d1d9483..0000000 --- a/src/main/java/com/intel/chimera/utils/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * 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. - */ -/** - * Utils classes - */ -package com.intel.chimera.utils; http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/VERSION ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/crypto/VERSION b/src/main/java/org/apache/commons/crypto/VERSION new file mode 100644 index 0000000..baca170 --- /dev/null +++ b/src/main/java/org/apache/commons/crypto/VERSION @@ -0,0 +1 @@ +VERSION=1.0.0-SNAPSHOT http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/cipher/Cipher.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/crypto/cipher/Cipher.java b/src/main/java/org/apache/commons/crypto/cipher/Cipher.java new file mode 100644 index 0000000..5f0f42b --- /dev/null +++ b/src/main/java/org/apache/commons/crypto/cipher/Cipher.java @@ -0,0 +1,155 @@ +/** + * 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.io.Closeable; +import java.nio.ByteBuffer; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.util.Properties; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.ShortBufferException; + +/** + * The interface of cryptographic cipher for encryption and decryption. + */ +public interface Cipher extends Closeable { + + /** + * A constant representing encrypt mode. The mode constant to be used + * when calling init method of the Cipher. + */ + int ENCRYPT_MODE = 1; + + /** + * A constant representing decrypt mode. The mode constant to be used + * when calling init method of the Cipher. + */ + int DECRYPT_MODE = 0; + + /** + * Gets the CipherTransformation for this cipher. + * + * @return the CipherTransformation for this cipher. + */ + CipherTransformation getTransformation(); + + /** + * Gets the properties for this cipher. + * + * @return the properties for this cipher. + */ + Properties getProperties(); + + /** + * Initializes the cipher with mode, key and iv. + * + * @param mode {@link #ENCRYPT_MODE} or {@link #DECRYPT_MODE} + * @param key crypto key for the cipher + * @param iv Initialization vector for the cipher + * @throws InvalidKeyException if the given key is inappropriate for + * initializing this cipher, or its keysize exceeds the maximum allowable + * keysize (as determined from the configured jurisdiction policy files). + * @throws InvalidAlgorithmParameterException if the given algorithm + * parameters are inappropriate for this cipher, or this cipher requires + * algorithm parameters and <code>params</code> is null, or the given + * algorithm parameters imply a cryptographic strength that would exceed + * the legal limits (as determined from the configured jurisdiction + * policy files). + */ + void init(int mode, byte[] key, byte[] iv) + throws InvalidKeyException, InvalidAlgorithmParameterException; + + /** + * Continues a multiple-part encryption/decryption operation. The data + * is encrypted or decrypted, depending on how this cipher was initialized. + * + * @param inBuffer the input ByteBuffer + * @param outBuffer the output ByteBuffer + * @return int number of bytes stored in <code>output</code> + * @throws ShortBufferException if there is insufficient space + * in the output buffer + */ + int update(ByteBuffer inBuffer, ByteBuffer outBuffer) + throws ShortBufferException; + + /** + * Continues a multiple-part encryption/decryption operation. The data + * is encrypted or decrypted, depending on how this cipher was initialized. + * + * @param input the input byte array + * @param inputOffset the offset in input where the input starts + * @param inputLen the input length + * @param output the byte array for the result + * @param outputOffset the offset in output where the result is stored + * @return the number of bytes stored in output + * @throws ShortBufferException if there is insufficient space in the output byte array + */ + int update(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) + throws ShortBufferException; + + /** + * Encrypts or decrypts data in a single-part operation, or finishes a + * multiple-part operation. + * + * @param inBuffer the input ByteBuffer + * @param outBuffer the output ByteBuffer + * @return int number of bytes stored in <code>output</code> + * @throws BadPaddingException if this cipher is in decryption mode, + * and (un)padding has been requested, but the decrypted data is not + * bounded by the appropriate padding bytes + * @throws IllegalBlockSizeException if this cipher is a block cipher, + * no padding has been requested (only in encryption mode), and the total + * input length of the data processed by this cipher is not a multiple of + * block size; or if this encryption algorithm is unable to + * process the input data provided. + * @throws ShortBufferException if the given output buffer is too small + * to hold the result + */ + int doFinal(ByteBuffer inBuffer, ByteBuffer outBuffer) + throws ShortBufferException, IllegalBlockSizeException, + BadPaddingException; + + /** + * Encrypts or decrypts data in a single-part operation, or finishes a + * multiple-part operation. + * + * @param input the input byte array + * @param inputOffset the offset in input where the input starts + * @param inputLen the input length + * @param output the byte array for the result + * @param outputOffset the offset in output where the result is stored + * @return the number of bytes stored in output + * @throws ShortBufferException if the given output byte array is too small + * to hold the result + * @throws BadPaddingException if this cipher is in decryption mode, + * and (un)padding has been requested, but the decrypted data is not + * bounded by the appropriate padding bytes + * @throws IllegalBlockSizeException if this cipher is a block cipher, + * no padding has been requested (only in encryption mode), and the total + * input length of the data processed by this cipher is not a multiple of + * block size; or if this encryption algorithm is unable to + * process the input data provided. + */ + int doFinal(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) + throws ShortBufferException, IllegalBlockSizeException, BadPaddingException; +} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/cipher/CipherFactory.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/crypto/cipher/CipherFactory.java b/src/main/java/org/apache/commons/crypto/cipher/CipherFactory.java new file mode 100644 index 0000000..c8272a6 --- /dev/null +++ b/src/main/java/org/apache/commons/crypto/cipher/CipherFactory.java @@ -0,0 +1,105 @@ +/** + * 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.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.commons.crypto.utils.ReflectionUtils; +import org.apache.commons.crypto.utils.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This is the factory class used for creating cipher class + */ +public class CipherFactory { + + /** LOG instance for {@CipherFactory} */ + public final static Logger LOG = LoggerFactory.getLogger(CipherFactory.class); + + /** + * Gets a cipher instance for specified algorithm/mode/padding. + * + * @param props + * the configuration properties + * @param transformation + * algorithm/mode/padding + * @return Cipher the cipher. Null value will be returned if no + * cipher classes with transformation configured. + */ + public static Cipher getInstance(CipherTransformation transformation, + Properties props) throws GeneralSecurityException { + List<Class<? extends Cipher>> klasses = getCipherClasses(props); + Cipher cipher = null; + if (klasses != null) { + for (Class<? extends Cipher> klass : klasses) { + try { + cipher = ReflectionUtils.newInstance(klass, props, transformation); + if (cipher != null) { + LOG.debug("Using cipher {} for transformation {}.", klass.getName(), + transformation.getName()); + break; + } + } catch (Exception e) { + LOG.error("Cipher {} is not available or transformation {} is not " + + "supported.", klass.getName(), transformation.getName()); + } + } + } + + return (cipher == null) ? new JceCipher(props, transformation) : cipher; + } + + /** + * Gets a cipher for algorithm/mode/padding in config value + * chimera.crypto.cipher.transformation + * + * @return Cipher the cipher object Null value will be returned if no + * cipher classes with transformation configured. + */ + public static Cipher getInstance(CipherTransformation transformation) + throws GeneralSecurityException { + return getInstance(transformation, null); + } + + private static List<Class<? extends Cipher>> getCipherClasses(Properties props) { + List<Class<? extends Cipher>> result = new ArrayList<Class<? extends + Cipher>>(); + String cipherClassString = Utils.getCipherClassString(props); + if (cipherClassString == null) { + LOG.debug("No cipher classes configured."); + return null; + } + for (String c : Utils.splitClassNames(cipherClassString, ",")) { + try { + Class<?> cls = ReflectionUtils.getClassByName(c); + result.add(cls.asSubclass(Cipher.class)); + } catch (ClassCastException e) { + LOG.error("Class {} is not a Cipher.", c); + } catch (ClassNotFoundException e) { + LOG.error("Cipher {} not found.", c); + } + } + + return result; + } + +} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/cipher/CipherTransformation.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/crypto/cipher/CipherTransformation.java b/src/main/java/org/apache/commons/crypto/cipher/CipherTransformation.java new file mode 100644 index 0000000..4bf0883 --- /dev/null +++ b/src/main/java/org/apache/commons/crypto/cipher/CipherTransformation.java @@ -0,0 +1,96 @@ +/** + * 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; + +/** + * Defines properties of a CipherTransformation. Modeled after the ciphers in + * {@link javax.crypto.Cipher}. + */ +public enum CipherTransformation { + + /** A crypto transformation representing AES/CTR/NoPadding */ + AES_CTR_NOPADDING("AES/CTR/NoPadding", 16), + /** A crypto transformation representing AES/CBC/NoPadding */ + AES_CBC_NOPADDING("AES/CBC/NoPadding", 16), + /** A crypto transformation representing AES/CBC/PKCS5Padding */ + AES_CBC_PKCS5PADDING("AES/CBC/PKCS5Padding", 16); + + private final String name; + private final int algorithmBlockSize; + + /** + * Constructor for CipherTransformation. Initalizes the cipher with algorithm + * name and block size of the algorithm. + * + * @param name the name of cipher algorithm + * @param algorithmBlockSize the blockSize of cipher algorithm + */ + CipherTransformation(String name, int algorithmBlockSize) { + this.name = name; + this.algorithmBlockSize = algorithmBlockSize; + } + + /** + * Gets the algorithm name of cipher. + * + * @return name of cipher transformation, as in {@link javax.crypto.Cipher} + */ + public String getName() { + return name; + } + + /** + * Gets the algorithm block size of cipher. + * + * @return size of an algorithm block in bytes. + */ + public int getAlgorithmBlockSize() { + return algorithmBlockSize; + } + + /** + * Overrides {@link java.lang.Enum#toString()} + * + * @return the name of cipher algorithm and blocksize. + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder("{"); + builder.append("name: " + name); + builder.append(", algorithmBlockSize: " + algorithmBlockSize); + builder.append("}"); + return builder.toString(); + } + + /** + * Converts to CipherTransformation from name, {@link #algorithmBlockSize} + * is fixed for certain cipher transformation, just need to compare the name. + * + * @param name cipher transformation name + * @return CipherTransformation cipher transformation + */ + public static CipherTransformation fromName(String name) { + CipherTransformation[] transformations = CipherTransformation.values(); + for (CipherTransformation transformation : transformations) { + if (transformation.getName().equals(name)) { + return transformation; + } + } + throw new IllegalArgumentException("Invalid transformation name: " + name); + } +} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/cipher/JceCipher.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/crypto/cipher/JceCipher.java b/src/main/java/org/apache/commons/crypto/cipher/JceCipher.java new file mode 100644 index 0000000..99a70bd --- /dev/null +++ b/src/main/java/org/apache/commons/crypto/cipher/JceCipher.java @@ -0,0 +1,207 @@ +/** + * 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.nio.ByteBuffer; +import java.security.GeneralSecurityException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.util.Properties; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.ShortBufferException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.crypto.utils.Utils; + +/** + * Implements the {@link org.apache.commons.crypto.cipher.Cipher} using JCE provider. + */ +public class JceCipher implements Cipher { + private final Properties props; + private final CipherTransformation transformation; + private final javax.crypto.Cipher cipher; + + /** + * Constructs a {@link org.apache.commons.crypto.cipher.Cipher} based on JCE + * Cipher {@link javax.crypto.Cipher}. + * @param props properties for JCE cipher + * @param transformation transformation for JCE cipher + * @throws GeneralSecurityException if JCE cipher initialize failed + */ + public JceCipher(Properties props, CipherTransformation transformation) + throws GeneralSecurityException { + this.props = props; + this.transformation = transformation; + + String provider = Utils.getJCEProvider(props); + if (provider == null || provider.isEmpty()) { + cipher = javax.crypto.Cipher.getInstance(transformation.getName()); + } else { + cipher = javax.crypto.Cipher.getInstance(transformation.getName(), provider); + } + } + + /** + * Gets the CipherTransformation for the jce cipher. + * + * @return the CipherTransformation for this cipher + */ + @Override + public CipherTransformation getTransformation() { + return transformation; + } + + /** + * Gets the properties for the jce cipher. + * + * @return the properties for this cipher. + */ + @Override + public Properties getProperties() { + return props; + } + + /** + * Initializes the cipher with mode, key and iv. + * + * @param mode {@link #ENCRYPT_MODE} or {@link #DECRYPT_MODE} + * @param key crypto key for the cipher + * @param iv Initialization vector for the cipher + * @throws InvalidAlgorithmParameterException if the given algorithm + * parameters are inappropriate for this cipher, or this cipher requires + * algorithm parameters and <code>params</code> is null, or the given + * algorithm parameters imply a cryptographic strength that would exceed + * the legal limits (as determined from the configured jurisdiction + * policy files). + */ + @Override + public void init(int mode, byte[] key, byte[] iv) + throws InvalidKeyException, InvalidAlgorithmParameterException { + Utils.checkNotNull(key); + Utils.checkNotNull(iv); + + int cipherMode = javax.crypto.Cipher.DECRYPT_MODE; + if (mode == ENCRYPT_MODE) + cipherMode = javax.crypto.Cipher.ENCRYPT_MODE; + + cipher.init(cipherMode, new SecretKeySpec(key, "AES"), + new IvParameterSpec(iv)); + } + + /** + * Continues a multiple-part encryption/decryption operation. The data + * is encrypted or decrypted, depending on how this cipher was initialized. + * + * @param inBuffer the input ByteBuffer + * @param outBuffer the output ByteBuffer + * @return int number of bytes stored in <code>output</code> + * @throws ShortBufferException if there is insufficient space + * in the output buffer + */ + @Override + public int update(ByteBuffer inBuffer, ByteBuffer outBuffer) + throws ShortBufferException { + return cipher.update(inBuffer, outBuffer); + } + + /** + * Continues a multiple-part encryption/decryption operation. The data + * is encrypted or decrypted, depending on how this cipher was initialized. + * + * @param input the input byte array + * @param inputOffset the offset in input where the input starts + * @param inputLen the input length + * @param output the byte array for the result + * @param outputOffset the offset in output where the result is stored + * @return the number of bytes stored in output + * @throws ShortBufferException if there is insufficient space in the output byte array + */ + @Override + public int update(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) + throws ShortBufferException { + return cipher.update(input, inputOffset, inputLen, + output, outputOffset); + } + + /** + * Encrypts or decrypts data in a single-part operation, or finishes a + * multiple-part operation. The data is encrypted or decrypted, depending + * on how this cipher was initialized. + * + * @param inBuffer the input ByteBuffer + * @param outBuffer the output ByteBuffer + * @return int number of bytes stored in <code>output</code> + * @throws BadPaddingException if this cipher is in decryption mode, + * and (un)padding has been requested, but the decrypted data is not + * bounded by the appropriate padding bytes + * @throws IllegalBlockSizeException if this cipher is a block cipher, + * no padding has been requested (only in encryption mode), and the total + * input length of the data processed by this cipher is not a multiple of + * block size; or if this encryption algorithm is unable to + * process the input data provided. + * @throws ShortBufferException if the given output buffer is too small + * to hold the result + */ + @Override + public int doFinal(ByteBuffer inBuffer, ByteBuffer outBuffer) + throws ShortBufferException, IllegalBlockSizeException, + BadPaddingException { + return cipher.doFinal(inBuffer, outBuffer); + } + + /** + * Encrypts or decrypts data in a single-part operation, or finishes a + * multiple-part operation. + * + * @param input the input byte array + * @param inputOffset the offset in input where the input starts + * @param inputLen the input length + * @param output the byte array for the result + * @param outputOffset the offset in output where the result is stored + * @return the number of bytes stored in output + * @throws ShortBufferException if the given output byte array is too small + * to hold the result + * @throws BadPaddingException if this cipher is in decryption mode, + * and (un)padding has been requested, but the decrypted data is not + * bounded by the appropriate padding bytes + * @throws IllegalBlockSizeException if this cipher is a block cipher, + * no padding has been requested (only in encryption mode), and the total + * input length of the data processed by this cipher is not a multiple of + * block size; or if this encryption algorithm is unable to + * process the input data provided. + */ + @Override + public int doFinal(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) + throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { + return cipher.doFinal(input, inputOffset, inputLen, + output, outputOffset); + } + + /** + * Closes Jce cipher. + */ + @Override + public void close() { + // Do nothing + } +} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/cipher/Openssl.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/crypto/cipher/Openssl.java b/src/main/java/org/apache/commons/crypto/cipher/Openssl.java new file mode 100644 index 0000000..9365859 --- /dev/null +++ b/src/main/java/org/apache/commons/crypto/cipher/Openssl.java @@ -0,0 +1,320 @@ +/** + * 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.nio.ByteBuffer; +import java.security.NoSuchAlgorithmException; +import java.util.StringTokenizer; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.ShortBufferException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.commons.crypto.utils.NativeCodeLoader; +import org.apache.commons.crypto.utils.Utils; + +/** + * OpenSSL cryptographic wrapper using JNI. + * Currently only AES-CTR is supported. It's flexible to add + * other crypto algorithms/modes. + */ +public final class Openssl { + private static final Log LOG = LogFactory.getLog(Openssl.class.getName()); + + // Mode constant defined by Openssl JNI + public static final int ENCRYPT_MODE = 1; + public static final int DECRYPT_MODE = 0; + + /** Currently only support AES/CTR/NoPadding. */ + private static enum AlgorithmMode { + AES_CTR, + AES_CBC; + + static int get(String algorithm, String mode) + throws NoSuchAlgorithmException { + try { + return AlgorithmMode.valueOf(algorithm + "_" + mode).ordinal(); + } catch (Exception e) { + throw new NoSuchAlgorithmException("Doesn't support algorithm: " + + algorithm + " and mode: " + mode); + } + } + } + + private static enum Padding { + NoPadding, + PKCS5Padding; + + static int get(String padding) throws NoSuchPaddingException { + try { + return Padding.valueOf(padding).ordinal(); + } catch (Exception e) { + throw new NoSuchPaddingException("Doesn't support padding: " + padding); + } + } + } + + private long context = 0; + private final int algorithm; + private final int padding; + + private static final String loadingFailureReason; + + static { + String loadingFailure = null; + try { + if (NativeCodeLoader.isNativeCodeLoaded()) { + OpensslNative.initIDs(); + } + } catch (Throwable t) { + loadingFailure = t.getMessage(); + LOG.debug("Failed to load OpenSSL Cipher.", t); + } finally { + loadingFailureReason = loadingFailure; + } + } + + /** + * Gets the failure reason when loading Openssl native. + * @return the failure reason. + */ + public static String getLoadingFailureReason() { + return loadingFailureReason; + } + + private Openssl(long context, int algorithm, int padding) { + this.context = context; + this.algorithm = algorithm; + this.padding = padding; + } + + /** + * Return an <code>OpensslCipher<code> object that implements the specified + * transformation. + * + * @param transformation the name of the transformation, e.g., + * AES/CTR/NoPadding. + * @return OpensslCipher an <code>OpensslCipher<code> object + * @throws NoSuchAlgorithmException if <code>transformation</code> is null, + * empty, in an invalid format, or if Openssl doesn't implement the + * specified algorithm. + * @throws NoSuchPaddingException if <code>transformation</code> contains + * a padding scheme that is not available. + */ + public static final Openssl getInstance(String transformation) + throws NoSuchAlgorithmException, NoSuchPaddingException { + Transform transform = tokenizeTransformation(transformation); + int algorithmMode = AlgorithmMode.get(transform.algorithm, transform.mode); + int padding = Padding.get(transform.padding); + long context = OpensslNative.initContext(algorithmMode, padding); + return new Openssl(context, algorithmMode, padding); + } + + /** Nested class for algorithm, mode and padding. */ + private static class Transform { + final String algorithm; + final String mode; + final String padding; + + public Transform(String algorithm, String mode, String padding) { + this.algorithm = algorithm; + this.mode = mode; + this.padding = padding; + } + } + + private static Transform tokenizeTransformation(String transformation) + throws NoSuchAlgorithmException { + if (transformation == null) { + throw new NoSuchAlgorithmException("No transformation given."); + } + + /* + * Array containing the components of a Cipher transformation: + * + * index 0: algorithm (e.g., AES) + * index 1: mode (e.g., CTR) + * index 2: padding (e.g., NoPadding) + */ + String[] parts = new String[3]; + int count = 0; + StringTokenizer parser = new StringTokenizer(transformation, "/"); + while (parser.hasMoreTokens() && count < 3) { + parts[count++] = parser.nextToken().trim(); + } + if (count != 3 || parser.hasMoreTokens()) { + throw new NoSuchAlgorithmException("Invalid transformation format: " + + transformation); + } + return new Transform(parts[0], parts[1], parts[2]); + } + + /** + * Initialize this cipher with a key and IV. + * + * @param mode {@link #ENCRYPT_MODE} or {@link #DECRYPT_MODE} + * @param key crypto key + * @param iv crypto iv + */ + public void init(int mode, byte[] key, byte[] iv) { + context = OpensslNative.init(context, mode, algorithm, padding, key, iv); + } + + /** + * Continues a multiple-part encryption or decryption operation. The data + * is encrypted or decrypted, depending on how this cipher was initialized. + * <p/> + * + * All <code>input.remaining()</code> bytes starting at + * <code>input.position()</code> are processed. The result is stored in + * the output buffer. + * <p/> + * + * Upon return, the input buffer's position will be equal to its limit; + * its limit will not have changed. The output buffer's position will have + * advanced by n, when n is the value returned by this method; the output + * buffer's limit will not have changed. + * <p/> + * + * If <code>output.remaining()</code> bytes are insufficient to hold the + * result, a <code>ShortBufferException</code> is thrown. + * + * @param input the input ByteBuffer + * @param output the output ByteBuffer + * @return int number of bytes stored in <code>output</code> + * @throws ShortBufferException if there is insufficient space in the + * output buffer + */ + public int update(ByteBuffer input, ByteBuffer output) + throws ShortBufferException { + checkState(); + Utils.checkArgument(input.isDirect() && output.isDirect(), + "Direct buffers are required."); + int len = OpensslNative.update(context, input, input.position(), + input.remaining(), output, output.position(), output.remaining()); + input.position(input.limit()); + output.position(output.position() + len); + return len; + } + + /** + * Continues a multiple-part encryption/decryption operation. The data + * is encrypted or decrypted, depending on how this cipher was initialized. + * + * @param input the input byte array + * @param inputOffset the offset in input where the input starts + * @param inputLen the input length + * @param output the byte array for the result + * @param outputOffset the offset in output where the result is stored + * @return the number of bytes stored in output + * @throws ShortBufferException if there is insufficient space in the output byte array + */ + public int update(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) + throws ShortBufferException { + checkState(); + return OpensslNative.updateByteArray(context, input, inputOffset, inputLen, + output, outputOffset, output.length - outputOffset); + } + + /** + * Finishes a multiple-part operation. The data is encrypted or decrypted, + * depending on how this cipher was initialized. + * <p/> + * + * The result is stored in the output buffer. Upon return, the output buffer's + * position will have advanced by n, where n is the value returned by this + * method; the output buffer's limit will not have changed. + * <p/> + * + * If <code>output.remaining()</code> bytes are insufficient to hold the result, + * a <code>ShortBufferException</code> is thrown. + * <p/> + * + * Upon finishing, this method resets this cipher object to the state it was + * in when previously initialized. That is, the object is available to encrypt + * or decrypt more data. + * <p/> + * + * If any exception is thrown, this cipher object need to be reset before it + * can be used again. + * + * @param output the output ByteBuffer + * @return int number of bytes stored in <code>output</code> + * @throws ShortBufferException + * @throws IllegalBlockSizeException + * @throws BadPaddingException + */ + public int doFinal(ByteBuffer output) + throws ShortBufferException, IllegalBlockSizeException, + BadPaddingException { + checkState(); + Utils.checkArgument(output.isDirect(), "Direct buffer is required."); + int len = OpensslNative.doFinal(context, output, output.position(), output.remaining()); + output.position(output.position() + len); + return len; + } + + /** + * Encrypts or decrypts data in a single-part operation, or finishes a + * multiple-part operation. + * + * @param output the byte array for the result + * @param outputOffset the offset in output where the result is stored + * @return the number of bytes stored in output + * @throws ShortBufferException if the given output byte array is too small + * to hold the result + * @throws BadPaddingException if this cipher is in decryption mode, + * and (un)padding has been requested, but the decrypted data is not + * bounded by the appropriate padding bytes + * @throws IllegalBlockSizeException if this cipher is a block cipher, + * no padding has been requested (only in encryption mode), and the total + * input length of the data processed by this cipher is not a multiple of + * block size; or if this encryption algorithm is unable to + * process the input data provided. + */ + public int doFinal(byte[] output, int outputOffset) + throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { + checkState(); + return OpensslNative.doFinalByteArray(context, + output, outputOffset, output.length - outputOffset); + } + + /** Forcibly clean the context. */ + public void clean() { + if (context != 0) { + OpensslNative.clean(context); + context = 0; + } + } + + /** Checks whether context is initialized. */ + private void checkState() { + Utils.checkState(context != 0); + } + + @Override + protected void finalize() throws Throwable { + clean(); + } + +} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/cipher/OpensslCipher.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/crypto/cipher/OpensslCipher.java b/src/main/java/org/apache/commons/crypto/cipher/OpensslCipher.java new file mode 100644 index 0000000..52b2bf3 --- /dev/null +++ b/src/main/java/org/apache/commons/crypto/cipher/OpensslCipher.java @@ -0,0 +1,196 @@ +/** + * 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.io.IOException; +import java.nio.ByteBuffer; +import java.security.GeneralSecurityException; +import java.util.Properties; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.ShortBufferException; + +import org.apache.commons.crypto.utils.Utils; + +/** + * Implements the Cipher using JNI into OpenSSL. + */ +public class OpensslCipher implements Cipher { + private final Properties props; + private final CipherTransformation transformation; + private final Openssl cipher; + + /** + * Constructs a {@link org.apache.commons.crypto.cipher.Cipher} using JNI into OpenSSL + * + * @param props properties for OpenSSL cipher + * @param transformation transformation for OpenSSL cipher + * @throws GeneralSecurityException if OpenSSL cipher initialize failed + */ + public OpensslCipher(Properties props, CipherTransformation transformation) + throws GeneralSecurityException { + this.props = props; + this.transformation = transformation; + + String loadingFailureReason = Openssl.getLoadingFailureReason(); + if (loadingFailureReason != null) { + throw new RuntimeException(loadingFailureReason); + } + + cipher = Openssl.getInstance(transformation.getName()); + } + + /** + * Gets the CipherTransformation for the openssl cipher. + * + * @return the CipherTransformation for this cipher + */ + @Override + public CipherTransformation getTransformation() { + return transformation; + } + + /** + * Gets the properties for the openssl cipher. + * + * @return the properties for this cipher. + */ + @Override + public Properties getProperties() { + return props; + } + + /** + * Initializes the cipher with mode, key and iv. + * @param mode {@link #ENCRYPT_MODE} or {@link #DECRYPT_MODE} + * @param key crypto key for the cipher + * @param iv Initialization vector for the cipher + * @throws IOException if cipher initialize fails + */ + @Override + public void init(int mode, byte[] key, byte[] iv) { + Utils.checkNotNull(key); + Utils.checkNotNull(iv); + + int cipherMode = Openssl.DECRYPT_MODE; + if (mode == ENCRYPT_MODE) + cipherMode = Openssl.ENCRYPT_MODE; + + cipher.init(cipherMode, key, iv); + } + + /** + * Continues a multiple-part encryption/decryption operation. The data + * is encrypted or decrypted, depending on how this cipher was initialized. + * @param inBuffer the input ByteBuffer + * @param outBuffer the output ByteBuffer + * @return int number of bytes stored in <code>output</code> + * @throws ShortBufferException if there is insufficient space + * in the output buffer + */ + @Override + public int update(ByteBuffer inBuffer, ByteBuffer outBuffer) + throws ShortBufferException { + return cipher.update(inBuffer, outBuffer); + } + + /** + * Continues a multiple-part encryption/decryption operation. The data + * is encrypted or decrypted, depending on how this cipher was initialized. + * + * @param input the input byte array + * @param inputOffset the offset in input where the input starts + * @param inputLen the input length + * @param output the byte array for the result + * @param outputOffset the offset in output where the result is stored + * @return the number of bytes stored in output + * @throws ShortBufferException if there is insufficient space in the output byte array + */ + @Override + public int update(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) + throws ShortBufferException { + return cipher.update(input, inputOffset, inputLen, + output, outputOffset); + } + + /** + * Encrypts or decrypts data in a single-part operation, or finishes a + * multiple-part operation. The data is encrypted or decrypted, depending + * on how this cipher was initialized. + * @param inBuffer the input ByteBuffer + * @param outBuffer the output ByteBuffer + * @return int number of bytes stored in <code>output</code> + * @throws BadPaddingException if this cipher is in decryption mode, + * and (un)padding has been requested, but the decrypted data is not + * bounded by the appropriate padding bytes + * @throws IllegalBlockSizeException if this cipher is a block cipher, + * no padding has been requested (only in encryption mode), and the total + * input length of the data processed by this cipher is not a multiple of + * block size; or if this encryption algorithm is unable to + * process the input data provided. + * @throws ShortBufferException if the given output buffer is too small + * to hold the result + */ + @Override + public int doFinal(ByteBuffer inBuffer, ByteBuffer outBuffer) + throws ShortBufferException, IllegalBlockSizeException, + BadPaddingException { + int n = cipher.update(inBuffer, outBuffer); + return n + cipher.doFinal(outBuffer); + } + + /** + * Encrypts or decrypts data in a single-part operation, or finishes a + * multiple-part operation. + * + * @param input the input byte array + * @param inputOffset the offset in input where the input starts + * @param inputLen the input length + * @param output the byte array for the result + * @param outputOffset the offset in output where the result is stored + * @return the number of bytes stored in output + * @throws ShortBufferException if the given output byte array is too small + * to hold the result + * @throws BadPaddingException if this cipher is in decryption mode, + * and (un)padding has been requested, but the decrypted data is not + * bounded by the appropriate padding bytes + * @throws IllegalBlockSizeException if this cipher is a block cipher, + * no padding has been requested (only in encryption mode), and the total + * input length of the data processed by this cipher is not a multiple of + * block size; or if this encryption algorithm is unable to + * process the input data provided. + */ + @Override + public int doFinal(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) + throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { + int n = cipher.update(input, inputOffset, inputLen, + output, outputOffset); + return n + cipher.doFinal(output, outputOffset + n); + } + + /** + * Closes the OpenSSL cipher. Clean the Openssl native context. + */ + @Override + public void close() { + cipher.clean(); + } +}