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