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/smime/ecc/SMimeV4BrainpoolDemo.java 3     12.02.25 17:59 Dbratko $
059    // $Revision: 3 $
060    //
061    
062    package demo.smime.ecc;
063    
064    import java.security.PrivateKey;
065    
066    import javax.activation.DataHandler;
067    import javax.mail.Session;
068    
069    import demo.DemoSMimeUtil;
070    import demo.DemoUtil;
071    import demo.cms.ecc.ECCDemoUtil;
072    import demo.cms.ecc.keystore.CMSEccKeyStore;
073    import iaik.asn1.structures.AlgorithmID;
074    import iaik.cms.CMSAlgorithmID;
075    import iaik.utils.KeyAndCertificate;
076    import iaik.x509.X509Certificate;
077    
078    /**
079     * This class demonstrates the usage of the IAIK S/MIME implementation. It shows how to create
080     * signed and/or (authenticated) encrypted S/MIMEv4 messages using ECC keys with Berainpool curves
081     * and how to parse them and verify the signatures and decrypt the content, respectively.
082     * <p>
083     * Although Brainpool curves may not be widely used with S/MIME applications they are, e.g., recommended 
084     * by the German Federal Office for Information Security (BSI) for their Technical Guideline BSI TR-03116
085     * defining cryptographic requirements for projects of the Federal Government.
086     * Note that whereas S/MIME in general uses AEAD cipher modes like GCM with the <code>AuthEnvelopedData</code>
087     * content type, BSI TR-03116 specifies GCM for use with the <code>EnvelopedData</code> type. For that 
088     * reason GCM is used with <code>EnvelopedData</code> in this demo (in difference to the parent 
089     * {@link SMimeV4EccDemo SMimeV4EccDemo} which uses GCM with the <code>AuthEnvelopedData</code> type.
090     *   
091     * <p>
092     * Additionally to <code>iaik_cms.jar</code> you also must have 
093     * <code>iaik_jce_(full).jar</code> (IAIK-JCE, <a href =
094     * "https://sic.tech/products/core-crypto-toolkits/jca-jce/" target="_blank">
095     * https://sic.tech/products/core-crypto-toolkits/jca-jce/</a>),
096     * and <code>iaik_eccelarate.jar</code> (IAIK-ECCelerate<sup><small>TM</small></sup>, <a href =
097     * "https://sic.tech/products/core-crypto-toolkits/eccelerate/" target="_blank">
098     * https://sic.tech/products/core-crypto-toolkits/eccelerate/</a>)
099     * in your classpath.
100     * <p>
101     * To run this demo the following packages are required:
102     * <ul>
103     *    <li>
104     *       <code>iaik_cms.jar</code>
105     *    </li>
106     *    <li>
107     *       <code>iaik_jce(_full).jar</code> (<a href="https://sic.tech/products/core-crypto-toolkits/jca-jce/" target="_blank">IAIK-JCE Core Crypto Library</a>).
108     *    </li>
109     *    <li>
110     *       <code>iaik_eccelerate.jar</code> (<a href="https://sic.tech/products/core-crypto-toolkits/eccelerate/" target="_blank">IAIK ECC Library</a>).
111     *    </li>   
112     *    <li>
113     *       <code>mail.jar</code> (<a href="http://www.oracle.com/technetwork/java/javamail/index.html" target="_blank">JavaMail API</a>).
114     *    </li>   
115     *    <li>
116     *       <code>activation.jar</code> (<a href="http://www.oracle.com/technetwork/java/javase/downloads/index-135046.html" target="_blank">Java Activation Framework</a>; required for JDK versions &lt; 1.6).
117     *    </li> 
118     * </ul>
119     * 
120     * This demo requires Java 7 or later.
121     */
122    public class SMimeV4BrainpoolDemo extends SMimeV4EccDemo {
123        
124     
125      /**
126       * Default constructor.
127       */
128      public SMimeV4BrainpoolDemo() {
129        
130        System.out.println();
131        System.out.println("********************************************************************************************");
132        System.out.println("*                                SMimeV4EccDemo demo                                       *");
133        System.out.println("* (shows how to create and parse (verify, decrypt) signed and encrypted S/MIMEv4 messages) *");
134        System.out.println("********************************************************************************************");
135        System.out.println();
136    
137      }
138      
139       
140      /**
141       * Starts the demo.
142       *
143       * @throws Exception if an error occurs
144       */
145      public void start() throws Exception {
146        
147        // get the default Session
148        Session session = DemoSMimeUtil.getSession();
149    
150        // Create a demo Multipart
151        DataHandler multipart = createMultipart();
152        
153        // get signer key and certs
154        KeyAndCertificate[] signerKeyAndCerts = {
155            // Brainpool P-224
156            new KeyAndCertificate(
157                CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA,
158                    CMSEccKeyStore.SZ_224_BRAINPOOL_SIGN),
159                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA,
160                    CMSEccKeyStore.SZ_224_BRAINPOOL_SIGN)),
161    
162            // Brainpool P-256
163            new KeyAndCertificate(
164                CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA,
165                    CMSEccKeyStore.SZ_256_BRAINPOOL_SIGN),
166                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA,
167                    CMSEccKeyStore.SZ_256_BRAINPOOL_SIGN)),
168            // Brainpool P-384
169            new KeyAndCertificate(
170                CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA,
171                    CMSEccKeyStore.SZ_384_BRAINPOOL_SIGN),
172                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA,
173                    CMSEccKeyStore.SZ_384_BRAINPOOL_SIGN)),
174            // Brainpool P-512
175            new KeyAndCertificate(
176                CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA,
177                    CMSEccKeyStore.SZ_512_BRAINPOOL_SIGN),
178                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA,
179                    CMSEccKeyStore.SZ_512_BRAINPOOL_SIGN)),
180    
181         };
182         
183         // the digest and signature algorithms to be used
184         AlgorithmID[][] digestAndSignatureAlgorithms = new AlgorithmID[][] {
185           { CMSAlgorithmID.sha224, CMSAlgorithmID.ecdsa_With_SHA224 },
186           { CMSAlgorithmID.sha256, CMSAlgorithmID.ecdsa_With_SHA256 },
187           { CMSAlgorithmID.sha384, CMSAlgorithmID.ecdsa_With_SHA384 },
188           { CMSAlgorithmID.sha512, CMSAlgorithmID.ecdsa_With_SHA512 },
189         };
190    
191        
192         /**************************************************************************/
193         /*                                                                        */
194         /*                               Signing Demo                             */
195         /*                                                                        */
196         /**************************************************************************/
197         
198         final int DIGEST_ALG = 0;
199         final int SIGNATURE_ALG = 1;
200         for (int i = 0; i < digestAndSignatureAlgorithms.length; i++) {
201           AlgorithmID digestAlg = digestAndSignatureAlgorithms[i][DIGEST_ALG];
202           AlgorithmID signatureAlg = digestAndSignatureAlgorithms[i][SIGNATURE_ALG];
203           PrivateKey signerKey = signerKeyAndCerts[i].getPrivateKey();
204           X509Certificate[] signerCerts = signerKeyAndCerts[i].getCertificateChain();
205           System.out.println("Running signing demo for " + signatureAlg.getName());
206           startSigningDemo(session, 
207                            multipart, 
208                            digestAlg, 
209                            signatureAlg, 
210                            signerKey,
211                            signerCerts);
212        }
213         
214        // (authenticated) encryption demos
215         
216        // get recipient certs
217        X509Certificate[] recipientCerts = {
218            // Brainpool P-224
219            CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
220                    CMSEccKeyStore.SZ_224_BRAINPOOL_CRYPT_1)[0],
221            CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
222                CMSEccKeyStore.SZ_224_BRAINPOOL_CRYPT_2)[0],
223           // Brainpool P-256
224           CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
225                   CMSEccKeyStore.SZ_256_BRAINPOOL_CRYPT_1)[0],
226           CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
227                   CMSEccKeyStore.SZ_256_BRAINPOOL_CRYPT_2)[0],
228           // Brainpool P-384
229           CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
230                   CMSEccKeyStore.SZ_384_BRAINPOOL_CRYPT_1)[0],
231           CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
232                   CMSEccKeyStore.SZ_384_BRAINPOOL_CRYPT_2)[0],
233           //Brainpool P-512
234           CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
235                   CMSEccKeyStore.SZ_512_BRAINPOOL_CRYPT_1)[0],
236           CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
237                   CMSEccKeyStore.SZ_512_BRAINPOOL_CRYPT_2)[0],
238           
239        };
240         
241        //  the key encryption algorithms to be used
242        AlgorithmID[] keyEAs = {
243            AlgorithmID.dhSinglePass_stdDH_sha224kdf_scheme, 
244            AlgorithmID.dhSinglePass_stdDH_sha256kdf_scheme, 
245            AlgorithmID.dhSinglePass_stdDH_sha384kdf_scheme, 
246            AlgorithmID.dhSinglePass_stdDH_hkdf_sha256_scheme, 
247            AlgorithmID.dhSinglePass_stdDH_hkdf_sha384_scheme,
248            AlgorithmID.dhSinglePass_stdDH_hkdf_sha512_scheme, 
249        };
250        // key wrap algorithms
251        AlgorithmID[] keyWrapAlgs = {
252            CMSAlgorithmID.cms_aes128_wrap, 
253            CMSAlgorithmID.cms_aes192_wrap, 
254            CMSAlgorithmID.cms_aes256_wrap, 
255        };
256        // whether to encrypt or authenticated encrypt
257        boolean[] doAuthEncrypt = { false, true };
258        for (int i = 0; i < keyEAs.length; i++) {
259          AlgorithmID[] contentEAs;
260          AlgorithmID keyEA = keyEAs[i];
261          for (int j = 0; j < keyWrapAlgs.length; j++) {
262            AlgorithmID keyWrapAlg = keyWrapAlgs[j];
263            int kekLength;
264            int keyLength;
265            if (keyWrapAlg.equals(CMSAlgorithmID.cms_aes192_wrap)) {
266              kekLength = 192;
267              keyLength = 192;
268              contentEAs = new AlgorithmID[]  { AlgorithmID.aes192_GCM, AlgorithmID.aes192_CCM };
269            } else if (keyWrapAlg.equals(CMSAlgorithmID.cms_aes128_wrap)) {
270              kekLength = 128;
271              keyLength = 128;
272              contentEAs = new AlgorithmID[]  { AlgorithmID.aes128_GCM, AlgorithmID.aes128_CCM  };
273            } else {
274              kekLength = 256;
275              keyLength = 256;
276              contentEAs = new AlgorithmID[]  { AlgorithmID.aes256_GCM, AlgorithmID.aes256_CCM, AlgorithmID.chacha20Poly1305 };
277            }
278            
279            for (int k = 0; k < contentEAs.length; k++) {
280              
281              /**************************************************************************/
282              /*                                                                        */
283              /*                  (Authenticated) Encryption Demo                       */
284              /*                                                                        */
285              /**************************************************************************/
286              
287              AlgorithmID contentEA = contentEAs[k];
288              // in practice we may not create one message for recipients with different strength;
289              // however, for simplicity we use all recipients here
290              System.out.println("Running encryption demo for " + 
291                                  keyEA.getName() + " with " + keyWrapAlg.getName() +" and " + contentEA.getName());
292              startEncryptionDemo(session,
293                                  contentEA, 
294                                  keyLength, 
295                                  keyEA,
296                                  keyWrapAlg,
297                                  kekLength,
298                                  false, 
299                                  recipientCerts);
300              
301              
302              /**************************************************************************/
303              /*                                                                        */
304              /*             Signing and (Authenticated) Encryption Demo                */
305              /*                                                                        */
306              /**************************************************************************/
307              
308              for (int l = 0; l < digestAndSignatureAlgorithms.length; l++) {
309                AlgorithmID digestAlg = digestAndSignatureAlgorithms[l][DIGEST_ALG];
310                AlgorithmID signatureAlg = digestAndSignatureAlgorithms[l][SIGNATURE_ALG];
311                PrivateKey signerKey = signerKeyAndCerts[l].getPrivateKey();
312                X509Certificate[] signerCerts = signerKeyAndCerts[l].getCertificateChain();
313                System.out.println("Running signing and encryption and demo for " + signatureAlg.getName());
314                startSigningAndEncryptionDemo(session,
315                    multipart,
316                    digestAlg,
317                    signatureAlg,
318                    contentEA, 
319                    keyLength, 
320                    keyEA,
321                    keyWrapAlg,
322                    kekLength,
323                    false,  
324                    signerKey, 
325                    signerCerts,
326                    recipientCerts);
327              }
328            }
329          }
330        }
331         
332      } 
333     
334      /**
335       * The main method.
336       */
337      public static void main(String[] argv) throws Exception {
338        
339        String jdkVersion = (String) System.getProperty("java.version");
340        if (jdkVersion.compareTo("1.7") >= 0) {
341          DemoSMimeUtil.initDemos();
342          //  add ECC provider    
343          ECCDemoUtil.installIaikEccProvider();
344          
345            (new SMimeV4BrainpoolDemo()).start();
346          System.out.println("\nReady!");
347        } else {
348          System.err.println("This demo requires Java 7 or later!");
349        }
350        DemoUtil.waitKey();
351      }
352    }