001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.commons.crypto; 019 020import java.io.IOException; 021import java.io.InputStream; 022import java.net.URL; 023import java.util.Properties; 024 025import org.apache.commons.crypto.cipher.CryptoCipher; 026import org.apache.commons.crypto.cipher.CryptoCipherFactory; 027import org.apache.commons.crypto.random.CryptoRandom; 028import org.apache.commons.crypto.random.CryptoRandomFactory; 029import org.apache.commons.crypto.utils.AES; 030 031/** 032 * Provides diagnostic information about Commons Crypto and keys for native 033 * class loading. 034 */ 035public final class Crypto { 036 037 private static class ComponentPropertiesHolder { 038 039 static final Properties PROPERTIES = getComponentProperties(); 040 041 /** 042 * Get component properties from component.properties. 043 * 044 * @return Properties contains project version. 045 */ 046 private static Properties getComponentProperties() { 047 final URL url = Crypto.class.getResource("/org/apache/commons/crypto/component.properties"); 048 final Properties versionData = new Properties(); 049 if (url != null) { 050 try (InputStream inputStream = url.openStream()) { 051 versionData.load(inputStream); 052 } catch (final IOException e) { // NOPMD 053 } 054 } 055 return versionData; 056 } 057 } 058 059 /** 060 * The prefix of all crypto configuration keys. 061 */ 062 public static final String CONF_PREFIX = "commons.crypto."; 063 064 /** 065 * The configuration key of the file name for loading crypto library. 066 */ 067 068 public static final String LIB_NAME_KEY = Crypto.CONF_PREFIX + "lib.name"; 069 070 // native lib related configuration keys 071 /** 072 * The configuration key of the path for loading crypto library. 073 */ 074 public static final String LIB_PATH_KEY = Crypto.CONF_PREFIX + "lib.path"; 075 076 /** 077 * The configuration key of temp directory for extracting crypto library. 078 * Defaults to "java.io.tempdir" if not found. 079 */ 080 public static final String LIB_TEMPDIR_KEY = Crypto.CONF_PREFIX + "lib.tempdir"; 081 082 private static boolean quiet = false; 083 084 /** 085 * Gets the component version of Apache Commons Crypto. 086 * <p> 087 * This implementation relies on the VERSION properties file which must be set 088 * up with the correct contents by the build process. This is done automatically 089 * by Maven. 090 * </p> 091 * 092 * @return the version; may be null if not found 093 */ 094 public static String getComponentName() { 095 // Note: the component properties file allows the method to work without needing 096 // the jar 097 return ComponentPropertiesHolder.PROPERTIES.getProperty("NAME"); 098 } 099 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}