View Javadoc
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  
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.net.URL;
23  import java.util.Properties;
24  
25  import org.apache.commons.crypto.cipher.CryptoCipher;
26  import org.apache.commons.crypto.cipher.CryptoCipherFactory;
27  import org.apache.commons.crypto.random.CryptoRandom;
28  import org.apache.commons.crypto.random.CryptoRandomFactory;
29  import org.apache.commons.crypto.utils.AES;
30  
31  /**
32   * Provides diagnostic information about Commons Crypto and keys for native
33   * class loading.
34   */
35  public final class Crypto {
36  
37      private static class ComponentPropertiesHolder {
38  
39          static final Properties PROPERTIES = getComponentProperties();
40  
41          /**
42           * Get component properties from component.properties.
43           *
44           * @return Properties contains project version.
45           */
46          private static Properties getComponentProperties() {
47              final URL url = Crypto.class.getResource("/org/apache/commons/crypto/component.properties");
48              final Properties versionData = new Properties();
49              if (url != null) {
50                  try (InputStream inputStream = url.openStream()) {
51                      versionData.load(inputStream);
52                  } catch (final IOException e) { // NOPMD
53                  }
54              }
55              return versionData;
56          }
57      }
58  
59      /**
60       * The prefix of all crypto configuration keys.
61       */
62      public static final String CONF_PREFIX = "commons.crypto.";
63  
64      /**
65       * The configuration key of the file name for loading crypto library.
66       */
67  
68      public static final String LIB_NAME_KEY = Crypto.CONF_PREFIX + "lib.name";
69  
70      // native lib related configuration keys
71      /**
72       * The configuration key of the path for loading crypto library.
73       */
74      public static final String LIB_PATH_KEY = Crypto.CONF_PREFIX + "lib.path";
75  
76      /**
77       * The configuration key of temp directory for extracting crypto library.
78       * Defaults to "java.io.tempdir" if not found.
79       */
80      public static final String LIB_TEMPDIR_KEY = Crypto.CONF_PREFIX + "lib.tempdir";
81  
82      private static boolean quiet = false;
83  
84      /**
85       * Gets the component version of Apache Commons Crypto.
86       * <p>
87       * This implementation relies on the VERSION properties file which must be set
88       * up with the correct contents by the build process. This is done automatically
89       * by Maven.
90       * </p>
91       *
92       * @return the version; may be null if not found
93       */
94      public static String getComponentName() {
95          // Note: the component properties file allows the method to work without needing
96          // the jar
97          return ComponentPropertiesHolder.PROPERTIES.getProperty("NAME");
98      }
99  
100     /**
101      * Gets the component version of Apache Commons Crypto.
102      * <p>
103      * This implementation relies on the VERSION properties file which must be set
104      * up with the correct contents by the build process. This is done automatically
105      * by Maven.
106      * </p>
107      *
108      * @return the version; may be null if not found
109      */
110     public static String getComponentVersion() {
111         // Note: the component properties file allows the method to work without needing
112         // the jar
113         return ComponentPropertiesHolder.PROPERTIES.getProperty("VERSION");
114     }
115 
116     /**
117      * The loading error throwable, if loading failed.
118      *
119      * @return null, unless loading failed.
120      */
121     public static Throwable getLoadingError() {
122         return NativeCodeLoader.getLoadingError();
123     }
124 
125     /**
126      * Logs info-level messages.
127      *
128      * @param format See {@link String#format(String, Object...)}.
129      * @param args   See {@link String#format(String, Object...)}.
130      */
131     private static void info(final String format, final Object... args) {
132         if (!quiet) { // suppress output for testing
133           System.out.println(String.format(format, args));
134         }
135     }
136 
137     /**
138      * Checks whether the native code has been successfully loaded for the platform.
139      *
140      * @return true if the native code has been loaded successfully.
141      */
142     public static boolean isNativeCodeLoaded() {
143         return NativeCodeLoader.isNativeCodeLoaded();
144     }
145 
146     /**
147      * The Main of Crypto.
148      *
149      * @param args Not used.
150      * @throws Exception if getCryptoRandom or getCryptoCipher get error.
151      */
152     public static void main(final String[] args) throws Exception {
153         quiet = args.length == 1 && args[0].equals("-q");
154         info("%s %s", getComponentName(), getComponentVersion());
155         if (isNativeCodeLoaded()) {
156             info("Native code loaded OK: %s", OpenSslInfoNative.NativeVersion());
157             info("Native name: %s", OpenSslInfoNative.NativeName());
158             info("Native built: %s", OpenSslInfoNative.NativeTimeStamp());
159             info("OpenSSL library loaded OK, version: 0x%s", Long.toHexString(OpenSslInfoNative.OpenSSL()));
160             info("OpenSSL library info: %s", OpenSslInfoNative.OpenSSLVersion(0));
161             info("DLL name: %s", OpenSslInfoNative.DLLName());
162             info("DLL path: %s", OpenSslInfoNative.DLLPath());
163             { // CryptoRandom
164                 final Properties props = new Properties();
165                 props.setProperty(CryptoRandomFactory.CLASSES_KEY, CryptoRandomFactory.RandomProvider.OPENSSL.getClassName());
166                 try (CryptoRandom cryptoRandom = CryptoRandomFactory.getCryptoRandom(props)) {
167                     info("Random instance created OK: %s", cryptoRandom);
168                 }
169             }
170             { // CryptoCipher
171                 final Properties props = new Properties();
172                 props.setProperty(CryptoCipherFactory.CLASSES_KEY, CryptoCipherFactory.CipherProvider.OPENSSL.getClassName());
173                 try (CryptoCipher cryptoCipher = CryptoCipherFactory.getCryptoCipher(AES.CTR_NO_PADDING, props)) {
174                     info("Cipher %s instance created OK: %s", AES.CTR_NO_PADDING, cryptoCipher);
175                 }
176             }
177             info("Additional OpenSSL_version(n) details:");
178             for (int j = 1; j < 6; j++) {
179                 info("%s: %s", j, OpenSslInfoNative.OpenSSLVersion(j));
180             }
181         } else {
182             info("Native load failed: %s", getLoadingError());
183         }
184     }
185 
186 }