001// Copyright (C) 2002 IAIK 002// https://sic.tech/ 003// 004// Copyright (C) 2003 - 2025 Stiftung Secure Information and 005// Communication Technologies SIC 006// https://sic.tech/ 007// 008// All rights reserved. 009// 010// This source is provided for inspection purposes and recompilation only, 011// unless specified differently in a contract with IAIK. This source has to 012// be kept in strict confidence and must not be disclosed to any third party 013// under any circumstances. Redistribution in source and binary forms, with 014// or without modification, are <not> permitted in any case! 015// 016// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 017// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 018// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 019// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 020// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 021// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 022// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 023// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 024// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 025// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 026// SUCH DAMAGE. 027// 028// $Header: /IAIK-CMS/current/src/demo/DemoUtil.java 29 12.02.25 17:58 Dbratko $ 029// $Revision: 29 $ 030// 031 032package demo; 033 034import java.io.IOException; 035import java.security.AlgorithmParameters; 036import java.security.InvalidAlgorithmParameterException; 037import java.security.MessageDigest; 038import java.security.NoSuchAlgorithmException; 039import java.security.Provider; 040import java.security.Security; 041import java.security.spec.InvalidParameterSpecException; 042import java.util.Random; 043 044import iaik.asn1.ObjectID; 045import iaik.asn1.structures.AlgorithmID; 046import iaik.cms.SecurityProvider; 047import iaik.pkcs.pkcs1.MGF1ParameterSpec; 048import iaik.pkcs.pkcs1.MaskGenerationAlgorithm; 049import iaik.pkcs.pkcs1.RSAPssParameterSpec; 050import iaik.security.provider.IAIK; 051import iaik.security.random.MetaSeedGenerator; 052import iaik.security.random.SecRandom; 053import iaik.security.random.SeedGenerator; 054 055/** 056 * Some basic utility methods used by the demos. 057 */ 058public class DemoUtil { 059 060 /** Debug flag for all demos */ 061 public final static boolean DEMO_DEBUG = true; 062 063 /** 064 * Base OID for IAIK-CMS demos. 065 */ 066 public final static ObjectID IAIK_JAVA_SECURITY_DEMO_CMS_OID = new ObjectID("1.3.6.1.4.1.2706.2.2.4", "IAIK JavaSecurity CMS Demo"); 067 068 /** 069 * Greeting message. 070 */ 071 final static String[] GREETING = { 072 "* *", 073 "* Welcome to the IAIK-CMS/SMIMEv4 Demo Programs *", 074 "* *", 075 "* These simple programs show how to use the IAIK-CMS library. Please *", 076 "* see the documentation and the source code for more information. *", 077 "* *", 078 "* *", 079 "* NOTE that most of the demos require certificates to work, they are *", 080 "* taken from a keystore file (cms.keystore) located in your current *", 081 "* working directory. If yet not exist, the keystore can be generated *", 082 "* by calling demo.keystore.SetupCMSKeyStore. *", 083 "* *", 084 "", 085 }; 086 087 088 /** 089 * Whether to {@link demo.keystore.SetupCMSKeyStore create} a new demo keystore automatically 090 * if it is not present or to explicitly ask if to create it. 091 */ 092 public static boolean CREATE_DEMO_KEYSTORE_AUTOMATICAllY = false; 093 /** 094 * Initialization done? 095 */ 096 static boolean initialized_ = false; 097 098 /** 099 * Version number of the IAIK-JCE crypto provider. 100 */ 101 static double iaikProviderVersion_ = -1; 102 103 /** 104 * Empty constructor. 105 */ 106 DemoUtil() { 107 // empty 108 } 109 110 /** Perform a some initial setup to allow the demos to work */ 111 public synchronized static void initDemos() { 112 initDemos(true); 113 } 114 115 /** 116 * Perform a some initial setup to allow the demos to work 117 * 118 * @param quickStart whether to init the random generator with a 119 * (not strong) seed for quick start (ONLY FOR 120 * DEMO PURPOSES; NOT FOR PRODUCTION ENVIRONMENT!) 121 */ 122 public synchronized static void initDemos(boolean quickStart) { 123 124 if( initialized_ ) { 125 return; 126 } 127 initialized_ = true; 128 for( int i=0; i<GREETING.length; i++ ) { 129 System.out.println(GREETING[i]); 130 } 131 initRandom(quickStart); 132 addIaikProvider(); 133 } 134 135 136 /** 137 * Adds the IAIK JCE as a first security provider. 138 */ 139 public static void addIaikProvider() { 140 IAIK.addAsProvider(); 141 Provider iaikProv = Security.getProvider("IAIK"); 142 iaikProviderVersion_ = iaikProv.getVersion(); 143 } 144 145 /** 146 * Gets the version number of the IAIK-JCE provider used for this demos. 147 * 148 * @return the version number of the IAIK JCA/JCE provider 149 */ 150 public static double getIaikProviderVersion() { 151 if (iaikProviderVersion_ == -1) { 152 addIaikProvider(); 153 } 154 return iaikProviderVersion_; 155 } 156 157 /** 158 * Adds the cryptography provider with the given name. 159 * 160 * Note that it may <em>not</em> be enough to just add it as a provider; 161 * see the {@link iaik.cms.SecurityProvider SecurityProvider} class for more information. 162 * 163 * @param name the name of the provider to be added 164 */ 165 public static void addProvider(String name) { 166 try { 167 Class clazz = Class.forName(name); 168 Provider provider = (Provider)clazz.newInstance(); 169 Security.addProvider(provider); 170 } catch (ClassNotFoundException ex) { 171 System.out.println("Provider IAIK not found. Add iaik_jce.jar or iaik_jce_full.jar to your classpath."); 172 System.out.println("If you are going to use a different provider please take a look at Readme.html!"); 173 System.exit(0); 174 } catch (Exception ex) { 175 System.out.println("Error adding provider:"); 176 ex.printStackTrace(System.err); 177 System.exit(0); 178 } 179 } 180 181 /** 182 * Setup the random number generator for a quick start. 183 * THIS IS NOT SECURE AND SHOULD BE USED FOR DEMO PURPOSES ONLY. 184 * ANY CRYPTOGRAPHIC KEY DERIVED IN THIS WAY IS WEAK AND NO STRONGER THAN 20 BIT!!! 185 */ 186 public static void initRandom() { 187 System.out.println("Quick-starting random number generator (not for use in production systems!)..."); 188 Random random = new Random(); 189 byte[] seed = new byte[20]; 190 random.nextBytes(seed); 191 MetaSeedGenerator.setSeed(seed); 192 SeedGenerator.setDefault(MetaSeedGenerator.class); 193 } 194 195 /** 196 * Setup the random number generator for a quick start. 197 * THIS IS NOT SECURE AND SHOULD BE USED FOR DEMO PURPOSES ONLY. 198 * ANY CRYPTOGRAPHIC KEY DERIVED IN THIS WAY IS WEAK AND NO STRONGER THAN 20 BIT!!! 199 * 200 * @param quick whether to init the random generator with a (not strong) seed 201 * for quick start (only for demonstration purposes) 202 */ 203 public static void initRandom(boolean quick) { 204 if (quick) { 205 System.out.println("Quick-starting random number generator (not for use in production systems!)..."); 206 Random random = new Random(); 207 byte[] seed = new byte[20]; 208 random.nextBytes(seed); 209 MetaSeedGenerator.setSeed(seed); 210 SeedGenerator.setDefault(MetaSeedGenerator.class); 211 } else { 212 // create a new Thread which initializes the Secure Random Number generator 213 (new Thread() { 214 public void run() { 215 setPriority(Thread.MIN_PRIORITY); 216 SecRandom.getDefault().nextInt(); 217 } 218 }).start(); 219 } 220 } 221 222 /** 223 * Creates a RSA-PSS AlgorithmID with the supplied parameters (hash algorithm id, 224 * mask generation function, salt length). 225 * 226 * @param hashID the hash algorithm to be used 227 * @param mgfID the mask generation function to be used 228 * @param saltLength the salt length to be used 229 * 230 * @return the RSA-PSS algorithm id with the given parameters 231 * 232 * @throws InvalidAlgorithmParameterException if the parameters cannot be created/set 233 * @throws NoSuchAlgorithmException if there is no AlgorithmParameters implementation 234 * for RSA-PSS 235 */ 236 public static AlgorithmID createPssAlgorithmID(AlgorithmID hashID, AlgorithmID mgfID, int saltLength) 237 throws InvalidAlgorithmParameterException, NoSuchAlgorithmException { 238 239 SecurityProvider provider = SecurityProvider.getSecurityProvider(); 240 AlgorithmID rsaPssID = (AlgorithmID)AlgorithmID.rsassaPss.clone(); 241 mgfID.setParameter(hashID.toASN1Object()); 242 // create a RSAPssParameterSpec 243 RSAPssParameterSpec pssParamSpec = new RSAPssParameterSpec(hashID, mgfID, saltLength); 244 // optionally set hash and mgf engines 245 MessageDigest hashEngine = provider.getMessageDigest(hashID); 246 pssParamSpec.setHashEngine(hashEngine); 247 MaskGenerationAlgorithm mgfEngine = provider.getMaskGenerationAlgorithm(mgfID); 248 MGF1ParameterSpec mgf1Spec = new MGF1ParameterSpec(hashID); 249 mgf1Spec.setHashEngine(hashEngine); 250 mgfEngine.setParameters(mgf1Spec); 251 pssParamSpec.setMGFEngine(mgfEngine); 252 253 AlgorithmParameters pssParams = null; 254 try { 255 pssParams = provider.getAlgorithmParameters(SecurityProvider.IMPLEMENTATION_NAME_RSA_PSS); 256 pssParams.init(pssParamSpec); 257 258 259 } catch (InvalidParameterSpecException ex) { 260 throw new InvalidAlgorithmParameterException("Cannot init PSS params: " + ex.getMessage()); 261 } 262 263 rsaPssID.setAlgorithmParameters(pssParams); 264 return rsaPssID; 265 } 266 267 268 /** 269 * Wait for the user to press the return key on System.in. 270 */ 271 public static void waitKey() { 272 try { 273 System.out.println("Hit the <RETURN> key."); 274 do { 275 System.in.read(); 276 } while( System.in.available() > 0 ); 277 } catch( IOException e ) { 278 // ignore 279 } 280 } 281 282}