Crypto.java

  1.  /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *     http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  */
  18. package org.apache.commons.crypto;

  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.net.URL;
  22. import java.util.Properties;

  23. import org.apache.commons.crypto.cipher.CryptoCipher;
  24. import org.apache.commons.crypto.cipher.CryptoCipherFactory;
  25. import org.apache.commons.crypto.random.CryptoRandom;
  26. import org.apache.commons.crypto.random.CryptoRandomFactory;
  27. import org.apache.commons.crypto.utils.AES;

  28. /**
  29.  * Provides diagnostic information about Commons Crypto and keys for native
  30.  * class loading.
  31.  */
  32. public final class Crypto {

  33.     private static class ComponentPropertiesHolder {

  34.         static final Properties PROPERTIES = getComponentProperties();

  35.         /**
  36.          * Get component properties from component.properties.
  37.          *
  38.          * @return Properties contains project version.
  39.          */
  40.         private static Properties getComponentProperties() {
  41.             final URL url = Crypto.class.getResource("/org/apache/commons/crypto/component.properties");
  42.             final Properties versionData = new Properties();
  43.             if (url != null) {
  44.                 try (InputStream inputStream = url.openStream()) {
  45.                     versionData.load(inputStream);
  46.                 } catch (final IOException e) { // NOPMD
  47.                 }
  48.             }
  49.             return versionData;
  50.         }
  51.     }

  52.     /**
  53.      * The prefix of all crypto configuration keys.
  54.      */
  55.     public static final String CONF_PREFIX = "commons.crypto.";

  56.     /**
  57.      * The configuration key of the file name for loading crypto library.
  58.      */

  59.     public static final String LIB_NAME_KEY = Crypto.CONF_PREFIX + "lib.name";

  60.     // native lib related configuration keys
  61.     /**
  62.      * The configuration key of the path for loading crypto library.
  63.      */
  64.     public static final String LIB_PATH_KEY = Crypto.CONF_PREFIX + "lib.path";

  65.     /**
  66.      * The configuration key of temp directory for extracting crypto library.
  67.      * Defaults to "java.io.tempdir" if not found.
  68.      */
  69.     public static final String LIB_TEMPDIR_KEY = Crypto.CONF_PREFIX + "lib.tempdir";

  70.     private static boolean quiet = false;

  71.     /**
  72.      * Gets the component version of Apache Commons Crypto.
  73.      * <p>
  74.      * This implementation relies on the VERSION properties file which must be set
  75.      * up with the correct contents by the build process. This is done automatically
  76.      * by Maven.
  77.      * </p>
  78.      *
  79.      * @return the version; may be null if not found
  80.      */
  81.     public static String getComponentName() {
  82.         // Note: the component properties file allows the method to work without needing
  83.         // the jar
  84.         return ComponentPropertiesHolder.PROPERTIES.getProperty("NAME");
  85.     }

  86.     /**
  87.      * Gets the component version of Apache Commons Crypto.
  88.      * <p>
  89.      * This implementation relies on the VERSION properties file which must be set
  90.      * up with the correct contents by the build process. This is done automatically
  91.      * by Maven.
  92.      * </p>
  93.      *
  94.      * @return the version; may be null if not found
  95.      */
  96.     public static String getComponentVersion() {
  97.         // Note: the component properties file allows the method to work without needing
  98.         // the jar
  99.         return ComponentPropertiesHolder.PROPERTIES.getProperty("VERSION");
  100.     }

  101.     /**
  102.      * The loading error throwable, if loading failed.
  103.      *
  104.      * @return null, unless loading failed.
  105.      */
  106.     public static Throwable getLoadingError() {
  107.         return NativeCodeLoader.getLoadingError();
  108.     }

  109.     /**
  110.      * Logs info-level messages.
  111.      *
  112.      * @param format See {@link String#format(String, Object...)}.
  113.      * @param args   See {@link String#format(String, Object...)}.
  114.      */
  115.     private static void info(final String format, final Object... args) {
  116.         if (!quiet) { // suppress output for testing
  117.           System.out.println(String.format(format, args));
  118.         }
  119.     }

  120.     /**
  121.      * Checks whether the native code has been successfully loaded for the platform.
  122.      *
  123.      * @return true if the native code has been loaded successfully.
  124.      */
  125.     public static boolean isNativeCodeLoaded() {
  126.         return NativeCodeLoader.isNativeCodeLoaded();
  127.     }

  128.     /**
  129.      * The Main of Crypto.
  130.      *
  131.      * @param args Not used.
  132.      * @throws Exception if getCryptoRandom or getCryptoCipher get error.
  133.      */
  134.     public static void main(final String[] args) throws Exception {
  135.         quiet = args.length == 1 && args[0].equals("-q");
  136.         info("%s %s", getComponentName(), getComponentVersion());
  137.         if (isNativeCodeLoaded()) {
  138.             info("Native code loaded OK: %s", OpenSslInfoNative.NativeVersion());
  139.             info("Native name: %s", OpenSslInfoNative.NativeName());
  140.             info("Native built: %s", OpenSslInfoNative.NativeTimeStamp());
  141.             info("OpenSSL library loaded OK, version: 0x%s", Long.toHexString(OpenSslInfoNative.OpenSSL()));
  142.             info("OpenSSL library info: %s", OpenSslInfoNative.OpenSSLVersion(0));
  143.             info("DLL name: %s", OpenSslInfoNative.DLLName());
  144.             info("DLL path: %s", OpenSslInfoNative.DLLPath());
  145.             { // CryptoRandom
  146.                 final Properties props = new Properties();
  147.                 props.setProperty(CryptoRandomFactory.CLASSES_KEY, CryptoRandomFactory.RandomProvider.OPENSSL.getClassName());
  148.                 try (CryptoRandom cryptoRandom = CryptoRandomFactory.getCryptoRandom(props)) {
  149.                     info("Random instance created OK: %s", cryptoRandom);
  150.                 }
  151.             }
  152.             { // CryptoCipher
  153.                 final Properties props = new Properties();
  154.                 props.setProperty(CryptoCipherFactory.CLASSES_KEY, CryptoCipherFactory.CipherProvider.OPENSSL.getClassName());
  155.                 try (CryptoCipher cryptoCipher = CryptoCipherFactory.getCryptoCipher(AES.CTR_NO_PADDING, props)) {
  156.                     info("Cipher %s instance created OK: %s", AES.CTR_NO_PADDING, cryptoCipher);
  157.                 }
  158.             }
  159.             info("Additional OpenSSL_version(n) details:");
  160.             for (int j = 1; j < 6; j++) {
  161.                 info("%s: %s", j, OpenSslInfoNative.OpenSSLVersion(j));
  162.             }
  163.         } else {
  164.             info("Native load failed: %s", getLoadingError());
  165.         }
  166.     }

  167. }