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    }