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 }