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/basic/SMimeV4Demo.java 8     12.02.25 17:59 Dbratko $
059    // $Revision: 8 $
060    //
061    
062    package demo.smime.basic;
063    
064    import java.io.ByteArrayInputStream;
065    import java.io.ByteArrayOutputStream;
066    import java.io.IOException;
067    import java.security.NoSuchAlgorithmException;
068    import java.security.PrivateKey;
069    import java.util.Date;
070    
071    import javax.activation.DataHandler;
072    import javax.activation.FileDataSource;
073    import javax.mail.Message;
074    import javax.mail.MessagingException;
075    import javax.mail.Multipart;
076    import javax.mail.Session;
077    import javax.mail.internet.InternetAddress;
078    import javax.mail.internet.MimeBodyPart;
079    import javax.mail.internet.MimeMessage;
080    import javax.mail.internet.MimeMultipart;
081    
082    import demo.DemoSMimeUtil;
083    import demo.DemoUtil;
084    import demo.keystore.CMSKeyStore;
085    import demo.smime.DumpMessage;
086    import iaik.asn1.ObjectID;
087    import iaik.asn1.structures.AlgorithmID;
088    import iaik.asn1.structures.Name;
089    import iaik.cms.CMSAlgorithmID;
090    import iaik.pkcs.PKCSException;
091    import iaik.pkcs.pkcs10.CertificateRequest;
092    import iaik.smime.AuthEncryptedContent;
093    import iaik.smime.CompressedContent;
094    import iaik.smime.EncryptedContent;
095    import iaik.smime.PKCS10Content;
096    import iaik.smime.SMimeBodyPart;
097    import iaik.smime.SMimeMultipart;
098    import iaik.smime.SMimeParameters;
099    import iaik.smime.SignedContent;
100    import iaik.x509.X509Certificate;
101    
102    /**
103     * This class demonstrates the usage of the IAIK S/MIME implementation. It shows how to create
104     * signed and/or encrypted S/MIMEv4 messages and how to parse them and verify the signatures 
105     * and decrypt the content, respectively.
106     * <p>
107     * To run this demo the following packages are required:
108     * <ul>
109     *    <li>
110     *       <code>iaik_cms.jar</code> (IAIK-CMS/SMIME)
111     *    </li>
112     *    <li>
113     *       <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>).
114     *    </li>
115     *    <li>
116     *       <code>mail.jar</code> (<a href="http://www.oracle.com/technetwork/java/javamail/index.html" target="_blank">JavaMail API</a>).
117     *    </li>   
118     *    <li>
119     *       <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).
120     *    </li> 
121     * </ul>
122     * You also will need the IAIK-JCE library, <code>iaik_jce(_full).jar</code>.
123     * <p>
124     * This demo uses RSA both for signing an encryption. Look at the demos in package <code>demo.smime.ecc</code> for
125     * examples based on elliptic curve cryptography.
126     * 
127     */
128    public class SMimeV4Demo {
129        
130      // whether to print dump all generates test messages to System.out
131      final static boolean PRINT_MESSAGES = false;   
132      
133    
134      String firstName_ = "John";
135      String lastName_ = "SMime";
136      String to_ = "smimetest@iaik.tugraz.at";     // email recipient
137      String from_ = "smimetest@iaik.tugraz.at";   // email sender
138      String host_ = "mailhost";                   // name of the mailhost
139    
140      X509Certificate[] signerCertificates_;       // list of certificates to include in the S/MIME message
141      X509Certificate signerCertificate_;          // certificate of the signer/sender
142      PrivateKey signerPrivateKey_;                // private key of the signer/sender
143      
144      X509Certificate senderCryptCertificate_;     // the encryption certificate of the signer/sender
145      
146      X509Certificate rsaRecipientCertificate_;    // RSA encryption cert and key of a recipient
147      
148      /**
149       * Default constructor. Reads certificates and keys from the demo keystore.
150       */
151      public SMimeV4Demo() {
152        
153        System.out.println();
154        System.out.println("********************************************************************************************");
155        System.out.println("*                                SMimeV4Demo demo                                          *");
156        System.out.println("* (shows how to create and parse (verify, decrypt) signed and encrypted S/MIMEv4 messages) *");
157        System.out.println("********************************************************************************************");
158        System.out.println();
159        
160        // get the certificates from the KeyStore
161        signerCertificates_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1);
162        signerPrivateKey_ = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1);
163        signerCertificate_ = signerCertificates_[0];
164        senderCryptCertificate_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1)[0];
165    
166        rsaRecipientCertificate_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2)[0];
167    
168      }
169      
170      /**
171       * Starts the demo.
172       *
173       * @throws IOException if an I/O related error occurs
174       */
175      public void start() throws IOException {
176    
177        // get the default Session
178            Session session = DemoSMimeUtil.getSession();
179    
180            try {
181          // Create a demo Multipart
182          MimeBodyPart mbp1 = new SMimeBodyPart();
183              mbp1.setText("This is a Test of the IAIK S/MIME implementation!\n\n");
184              // attachment
185          MimeBodyPart attachment = new SMimeBodyPart();
186          attachment.setDataHandler(new DataHandler(new FileDataSource("test.html")));
187          attachment.setFileName("test.html");
188    
189          Multipart mp = new SMimeMultipart();
190          mp.addBodyPart(mbp1);
191          mp.addBodyPart(attachment);
192          DataHandler multipart = new DataHandler(mp, mp.getContentType());
193    
194          Message msg;    // the message to send
195          ByteArrayOutputStream baos = new ByteArrayOutputStream(); // we write to a stream
196          ByteArrayInputStream bais;  // we read from a stream
197    
198          // This is a plain message
199          msg = createPlainMessage(session, multipart);
200          System.out.println("creating plain message...");
201              msg.saveChanges();
202              msg.writeTo(baos);
203              bais = new ByteArrayInputStream(baos.toByteArray());
204              msg = new MimeMessage(session, bais);
205              if (PRINT_MESSAGES) {
206            printMessage(msg);
207          }
208              DumpMessage.dumpMsg(msg);
209              
210              System.out.println("\n\n*****************************************\n\n");
211    
212          // This is an explicitly signed message
213          msg = createSignedMessage(session, multipart, false, AlgorithmID.sha256, AlgorithmID.rsaEncryption);
214          System.out.println("creating explicitly signed message...");
215          baos.reset();
216              msg.saveChanges();
217              msg.writeTo(baos);
218              bais = new ByteArrayInputStream(baos.toByteArray());
219              msg = new MimeMessage(session, bais);
220              if (PRINT_MESSAGES) {
221            printMessage(msg);
222          }
223              DumpMessage.dumpMsg(msg);
224              
225              System.out.println("\n\n*****************************************\n\n");
226    
227    
228          // This is an implicitly signed message
229          msg = createSignedMessage(session, multipart, true, AlgorithmID.sha256, AlgorithmID.rsaEncryption);
230          System.out.println("creating implicitly signed message...");
231              baos.reset();
232              msg.saveChanges();
233              msg.writeTo(baos);
234              bais = new ByteArrayInputStream(baos.toByteArray());
235              msg = new MimeMessage(session, bais);
236              if (PRINT_MESSAGES) {
237            printMessage(msg);
238          }
239              DumpMessage.dumpMsg(msg);
240              
241              System.out.println("\n\n*****************************************\n\n");
242    
243          // Now create encrypted messages with different content encryption algorithms
244              
245              msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_CBC.clone(), 128);
246          System.out.println("creating encrypted message [AES/128]...");
247          baos.reset();
248          msg.saveChanges();
249          msg.writeTo(baos);
250          bais = new ByteArrayInputStream(baos.toByteArray());
251          msg = new MimeMessage(session, bais);
252          if (PRINT_MESSAGES) {
253            printMessage(msg);
254          }
255          DumpMessage.dumpEncryptedMessage(msg);
256          
257          System.out.println("\n\n*****************************************\n\n");
258          
259          msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_CBC.clone(), 192);
260          System.out.println("creating encrypted message [AES/192]...");
261          baos.reset();
262          msg.saveChanges();
263          msg.writeTo(baos);
264          bais = new ByteArrayInputStream(baos.toByteArray());
265          msg = new MimeMessage(session, bais);
266          if (PRINT_MESSAGES) {
267            printMessage(msg);
268          }
269          DumpMessage.dumpEncryptedMessage(msg);
270            
271          System.out.println("\n\n*****************************************\n\n");
272            
273          msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_CBC.clone(), 256);
274          System.out.println("creating encrypted message [AES/256]...");
275          baos.reset();
276          msg.saveChanges();
277          msg.writeTo(baos);
278          bais = new ByteArrayInputStream(baos.toByteArray());
279          msg = new MimeMessage(session, bais);
280          if (PRINT_MESSAGES) {
281            printMessage(msg);
282          }
283          DumpMessage.dumpEncryptedMessage(msg);
284           
285          System.out.println("\n\n*****************************************\n\n");
286    
287          // Now create an implicitly signed and encrypted message with attachment
288          msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_CBC.clone(), 128, multipart, true, false);
289          System.out.println("creating implicitly signed and encrypted message [AES/128]...");
290          baos.reset();
291          msg.saveChanges();
292          msg.writeTo(baos);
293          bais = new ByteArrayInputStream(baos.toByteArray());
294          msg = new MimeMessage(session, bais);
295          if (PRINT_MESSAGES) {
296            printMessage(msg);
297          }
298          DumpMessage.dumpEncryptedMessage(msg);
299          
300          System.out.println("\n\n*****************************************\n\n");
301          
302          // Now create an implicitly signed and encrypted message with attachment
303          msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_CBC.clone(), 192, multipart, true, false);
304          System.out.println("creating implicitly signed and encrypted message [AES/192]...");
305          baos.reset();
306          msg.saveChanges();
307          msg.writeTo(baos);
308          bais = new ByteArrayInputStream(baos.toByteArray());
309          msg = new MimeMessage(session, bais);
310          if (PRINT_MESSAGES) {
311            printMessage(msg);
312          }
313          DumpMessage.dumpEncryptedMessage(msg);
314          
315          System.out.println("\n\n*****************************************\n\n");
316    
317          // Now create an explicitly signed and encrypted message with attachment
318          msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_CBC.clone(), 192, multipart, false, false);;
319          System.out.println("creating explicitly signed and encrypted message [AES/192]...");
320          baos.reset();
321          msg.saveChanges();
322          msg.writeTo(baos);
323          bais = new ByteArrayInputStream(baos.toByteArray());
324          msg = new MimeMessage(session, bais);
325          if (PRINT_MESSAGES) {
326            printMessage(msg);
327          }
328          DumpMessage.dumpEncryptedMessage(msg);
329          
330          System.out.println("\n\n*****************************************\n\n");
331    
332          // Now create an implicitly signed and encrypted message with attachment
333          msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_CBC.clone(), 256, multipart, true, false);
334          System.out.println("creating implicitly signed and encrypted message [AES/256]...");
335              baos.reset();
336              msg.saveChanges();
337              msg.writeTo(baos);
338              bais = new ByteArrayInputStream(baos.toByteArray());
339              msg = new MimeMessage(session, bais);
340              if (PRINT_MESSAGES) {
341            printMessage(msg);
342          }
343              DumpMessage.dumpEncryptedMessage(msg);
344              
345              System.out.println("\n\n*****************************************\n\n");
346    
347          // Now create an explicitly signed and encrypted message with attachment
348          msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_CBC.clone(), 256, multipart, false, false);;
349          System.out.println("creating explicitly signed and encrypted message [AES/256]...");
350              baos.reset();
351              msg.saveChanges();
352              msg.writeTo(baos);
353              bais = new ByteArrayInputStream(baos.toByteArray());
354              msg = new MimeMessage(session, bais);
355              if (PRINT_MESSAGES) {
356            printMessage(msg);
357          }
358              DumpMessage.dumpEncryptedMessage(msg);
359              
360              System.out.println("\n\n*****************************************\n\n");
361              
362              // Now create authenticated encrypted messages with different content encryption algorithms
363              if (DemoUtil.getIaikProviderVersion() >= 5.62) {
364                
365                msg = createAuthEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_GCM.clone(), 128);
366            System.out.println("creating authenticated encrypted message [AES-GCM/128]...");
367            baos.reset();
368            msg.saveChanges();
369            msg.writeTo(baos);
370            bais = new ByteArrayInputStream(baos.toByteArray());
371            msg = new MimeMessage(session, bais);
372            if (PRINT_MESSAGES) {
373              printMessage(msg);
374            }
375            DumpMessage.dumpEncryptedMessage(msg);
376             
377            System.out.println("\n\n*****************************************\n\n");
378            
379            msg = createAuthEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_GCM.clone(), 192);
380            System.out.println("creating authenticated encrypted message [AES-GCM/192]...");
381            baos.reset();
382            msg.saveChanges();
383            msg.writeTo(baos);
384            bais = new ByteArrayInputStream(baos.toByteArray());
385            msg = new MimeMessage(session, bais);
386            if (PRINT_MESSAGES) {
387              printMessage(msg);
388            }
389            DumpMessage.dumpEncryptedMessage(msg); 
390             
391            System.out.println("\n\n*****************************************\n\n");
392                
393                msg = createAuthEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_GCM.clone(), 256);
394                System.out.println("creating authenticated encrypted message [AES-GCM/256]...");
395                baos.reset();
396                msg.saveChanges();
397                msg.writeTo(baos);
398                bais = new ByteArrayInputStream(baos.toByteArray());
399                msg = new MimeMessage(session, bais);
400                if (PRINT_MESSAGES) {
401                  printMessage(msg);
402                }
403                DumpMessage.dumpEncryptedMessage(msg);
404                 
405                System.out.println("\n\n*****************************************\n\n");
406                
407                msg = createAuthEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_CCM.clone(), 128);
408            System.out.println("creating authenticated encrypted message [AES-CCM/128]...");
409            baos.reset();
410            msg.saveChanges();
411            msg.writeTo(baos);
412            bais = new ByteArrayInputStream(baos.toByteArray());
413            msg = new MimeMessage(session, bais);
414            if (PRINT_MESSAGES) {
415              printMessage(msg);
416            }
417            DumpMessage.dumpEncryptedMessage(msg);
418             
419            System.out.println("\n\n*****************************************\n\n");
420            
421            msg = createAuthEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_CCM.clone(), 192);
422            System.out.println("creating authenticated encrypted message [AES-CCM/192]...");
423            baos.reset();
424            msg.saveChanges();
425            msg.writeTo(baos);
426            bais = new ByteArrayInputStream(baos.toByteArray());
427            msg = new MimeMessage(session, bais);
428            if (PRINT_MESSAGES) {
429              printMessage(msg);
430            }
431            DumpMessage.dumpEncryptedMessage(msg); 
432            
433            msg = createAuthEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_CCM.clone(), 256);
434            System.out.println("creating authenticated encrypted message [AES-CCM/256]...");
435            baos.reset();
436            msg.saveChanges();
437            msg.writeTo(baos);
438            bais = new ByteArrayInputStream(baos.toByteArray());
439            msg = new MimeMessage(session, bais);
440            if (PRINT_MESSAGES) {
441              printMessage(msg);
442            }
443            DumpMessage.dumpEncryptedMessage(msg);
444             
445            System.out.println("\n\n*****************************************\n\n");
446            
447            msg = createAuthEncryptedMessage(session, (AlgorithmID)AlgorithmID.chacha20Poly1305.clone(), 256);
448            System.out.println("creating authenticated encrypted message [ChaChaPoly1305]...");
449            baos.reset();
450            msg.saveChanges();
451            msg.writeTo(baos);
452            bais = new ByteArrayInputStream(baos.toByteArray());
453            msg = new MimeMessage(session, bais);
454            if (PRINT_MESSAGES) {
455              printMessage(msg);
456            }
457            DumpMessage.dumpEncryptedMessage(msg);  
458             
459            System.out.println("\n\n*****************************************\n\n");
460            
461           // Create an implicitly signed and authenticated encrypted message with attachment
462            msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_GCM.clone(), 128, multipart, true, true);
463            System.out.println("creating implicitly signed and authenticated encrypted message [AES-GCM/128]...");
464            baos.reset();
465            msg.saveChanges();
466            msg.writeTo(baos);
467            bais = new ByteArrayInputStream(baos.toByteArray());
468            msg = new MimeMessage(session, bais);
469            if (PRINT_MESSAGES) {
470              printMessage(msg);
471            }
472            DumpMessage.dumpEncryptedMessage(msg);
473            
474            System.out.println("\n\n*****************************************\n\n");
475    
476            // Create an explicitly signed and authenticated encrypted message with attachment
477            msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_GCM.clone(), 128, multipart, true, true);
478            System.out.println("creating explicitly signed and authenticated encrypted message [AES-GCM/128]...");
479            baos.reset();
480            msg.saveChanges();
481            msg.writeTo(baos);
482            bais = new ByteArrayInputStream(baos.toByteArray());
483            msg = new MimeMessage(session, bais);
484            if (PRINT_MESSAGES) {
485              printMessage(msg);
486            }
487            DumpMessage.dumpEncryptedMessage(msg);
488            
489            System.out.println("\n\n*****************************************\n\n");
490            
491            // Create an implicitly signed and authenticated encrypted message with attachment
492            msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_GCM.clone(), 192, multipart, true, true);
493            System.out.println("creating implicitly signed and authenticated encrypted message [AES-GCM/192]...");
494            baos.reset();
495            msg.saveChanges();
496            msg.writeTo(baos);
497            bais = new ByteArrayInputStream(baos.toByteArray());
498            msg = new MimeMessage(session, bais);
499            if (PRINT_MESSAGES) {
500              printMessage(msg);
501            }
502            DumpMessage.dumpEncryptedMessage(msg);
503            
504            System.out.println("\n\n*****************************************\n\n");
505    
506            // Create an explicitly signed and authenticated encrypted message with attachment
507            msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_GCM.clone(), 192, multipart, true, true);
508            System.out.println("creating explicitly signed and authenticated encrypted message [AES-GCM/192]...");
509            baos.reset();
510            msg.saveChanges();
511            msg.writeTo(baos);
512            bais = new ByteArrayInputStream(baos.toByteArray());
513            msg = new MimeMessage(session, bais);
514            if (PRINT_MESSAGES) {
515              printMessage(msg);
516            }
517            DumpMessage.dumpEncryptedMessage(msg);
518            
519            System.out.println("\n\n*****************************************\n\n");
520                
521            // Create an implicitly signed and authenticated encrypted message with attachment
522            msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_GCM.clone(), 256, multipart, true, true);
523            System.out.println("creating implicitly signed and authenticated encrypted message [AES-GCM/256]...");
524            baos.reset();
525            msg.saveChanges();
526            msg.writeTo(baos);
527            bais = new ByteArrayInputStream(baos.toByteArray());
528            msg = new MimeMessage(session, bais);
529            if (PRINT_MESSAGES) {
530              printMessage(msg);
531            }
532            DumpMessage.dumpEncryptedMessage(msg);
533            
534            System.out.println("\n\n*****************************************\n\n");
535    
536            // Create an explicitly signed and authenticated encrypted message with attachment
537            msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_GCM.clone(), 256, multipart, true, true);
538            System.out.println("creating explicitly signed and authenticated encrypted message [AES-GCM/256]...");
539            baos.reset();
540            msg.saveChanges();
541            msg.writeTo(baos);
542            bais = new ByteArrayInputStream(baos.toByteArray());
543            msg = new MimeMessage(session, bais);
544            if (PRINT_MESSAGES) {
545              printMessage(msg);
546            }
547            DumpMessage.dumpEncryptedMessage(msg);
548            
549            System.out.println("\n\n*****************************************\n\n");
550            
551            
552            // Create an implicitly signed and authenticated encrypted message with attachment
553             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_CCM.clone(), 128, multipart, true, true);
554             System.out.println("creating implicitly signed and authenticated encrypted message [AES-CCM/128]...");
555             baos.reset();
556             msg.saveChanges();
557             msg.writeTo(baos);
558             bais = new ByteArrayInputStream(baos.toByteArray());
559             msg = new MimeMessage(session, bais);
560             if (PRINT_MESSAGES) {
561               printMessage(msg);
562             }
563             DumpMessage.dumpEncryptedMessage(msg);
564             
565             System.out.println("\n\n*****************************************\n\n");
566    
567             // Create an explicitly signed and authenticated encrypted message with attachment
568             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_CCM.clone(), 128, multipart, true, true);
569             System.out.println("creating explicitly signed and authenticated encrypted message [AES-CCM/128]...");
570             baos.reset();
571             msg.saveChanges();
572             msg.writeTo(baos);
573             bais = new ByteArrayInputStream(baos.toByteArray());
574             msg = new MimeMessage(session, bais);
575             if (PRINT_MESSAGES) {
576               printMessage(msg);
577             }
578             DumpMessage.dumpEncryptedMessage(msg);
579             
580             System.out.println("\n\n*****************************************\n\n");
581             
582             // Create an implicitly signed and authenticated encrypted message with attachment
583             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_CCM.clone(), 192, multipart, true, true);
584             System.out.println("creating implicitly signed and authenticated encrypted message [AES-CCM/192]...");
585             baos.reset();
586             msg.saveChanges();
587             msg.writeTo(baos);
588             bais = new ByteArrayInputStream(baos.toByteArray());
589             msg = new MimeMessage(session, bais);
590             if (PRINT_MESSAGES) {
591               printMessage(msg);
592             }
593             DumpMessage.dumpEncryptedMessage(msg);
594             
595             System.out.println("\n\n*****************************************\n\n");
596    
597             // Create an explicitly signed and authenticated encrypted message with attachment
598             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_CCM.clone(), 192, multipart, true, true);
599             System.out.println("creating explicitly signed and authenticated encrypted message [AES-CCM/192]...");
600             baos.reset();
601             msg.saveChanges();
602             msg.writeTo(baos);
603             bais = new ByteArrayInputStream(baos.toByteArray());
604             msg = new MimeMessage(session, bais);
605             if (PRINT_MESSAGES) {
606               printMessage(msg);
607             }
608             DumpMessage.dumpEncryptedMessage(msg);
609             
610             System.out.println("\n\n*****************************************\n\n");
611             
612             // Create an implicitly signed and authenticated encrypted message with attachment
613             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_CCM.clone(), 256, multipart, true, true);
614             System.out.println("creating implicitly signed and authenticated encrypted message [AES-CCM/256]...");
615             baos.reset();
616             msg.saveChanges();
617             msg.writeTo(baos);
618             bais = new ByteArrayInputStream(baos.toByteArray());
619             msg = new MimeMessage(session, bais);
620             if (PRINT_MESSAGES) {
621               printMessage(msg);
622             }
623             DumpMessage.dumpEncryptedMessage(msg);
624             
625             System.out.println("\n\n*****************************************\n\n");
626    
627             // Create an explicitly signed and authenticated encrypted message with attachment
628             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_CCM.clone(), 256, multipart, true, true);
629             System.out.println("creating explicitly signed and authenticated encrypted message [AES-CCM/256]...");
630             baos.reset();
631             msg.saveChanges();
632             msg.writeTo(baos);
633             bais = new ByteArrayInputStream(baos.toByteArray());
634             msg = new MimeMessage(session, bais);
635             if (PRINT_MESSAGES) {
636               printMessage(msg);
637             }
638             DumpMessage.dumpEncryptedMessage(msg);
639             
640             System.out.println("\n\n*****************************************\n\n");
641            
642             // Create an implicitly signed and authenticated encrypted message with attachment
643             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.chacha20Poly1305.clone(), 256, multipart, true, true);
644             System.out.println("creating implicitly signed and authenticated encrypted message [ChaCha20Poly1305]...");
645             baos.reset();
646             msg.saveChanges();
647             msg.writeTo(baos);
648             bais = new ByteArrayInputStream(baos.toByteArray());
649             msg = new MimeMessage(session, bais);
650             if (PRINT_MESSAGES) {
651               printMessage(msg);
652             }
653             DumpMessage.dumpEncryptedMessage(msg);
654             
655             System.out.println("\n\n*****************************************\n\n");
656    
657             // Create an explicitly signed and authenticated encrypted message with attachment
658             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.chacha20Poly1305.clone(), 256, multipart, true, true);
659             System.out.println("creating explicitly signed and authenticated encrypted message [ChaCha20Poly1305]...");
660             baos.reset();
661             msg.saveChanges();
662             msg.writeTo(baos);
663             bais = new ByteArrayInputStream(baos.toByteArray());
664             msg = new MimeMessage(session, bais);
665             if (PRINT_MESSAGES) {
666               printMessage(msg);
667             }
668             DumpMessage.dumpEncryptedMessage(msg);
669             
670             System.out.println("\n\n*****************************************\n\n");
671                
672              }
673             
674              // certs only message
675              msg = createCertsOnlyMessage(session);
676              System.out.println("creating certs-only message");
677              baos.reset();
678              msg.saveChanges();
679              msg.writeTo(baos);
680              bais = new ByteArrayInputStream(baos.toByteArray());
681              msg = new MimeMessage(session, bais);
682              if (PRINT_MESSAGES) {
683            printMessage(msg);
684          }
685              DumpMessage.dumpMsg(msg);
686              
687              System.out.println("\n\n*****************************************\n\n");
688    
689              // second certs only message
690              msg = createCertsOnlyMultiPartMessage(session);
691              System.out.println("creating message with certs-only part");
692              baos.reset();
693              msg.saveChanges();
694              msg.writeTo(baos);
695              bais = new ByteArrayInputStream(baos.toByteArray());
696              msg = new MimeMessage(session, bais);
697              if (PRINT_MESSAGES) {
698            printMessage(msg);
699          }
700              DumpMessage.dumpMsg(msg);
701              
702              System.out.println("\n\n*****************************************\n\n");
703    
704              // application/pkcs10 cert request message
705          msg = createPKCS10Message(session);
706          System.out.println("creating application/pkcs10 message...");
707              baos.reset();
708              msg.saveChanges();
709              msg.writeTo(baos);
710              bais = new ByteArrayInputStream(baos.toByteArray());
711              msg = new MimeMessage(session, bais);
712              if (PRINT_MESSAGES) {
713            printMessage(msg);
714          }
715              DumpMessage.dumpMsg(msg);
716              
717              System.out.println("\n\n*****************************************\n\n");
718    
719              // sending application/pkcs10 message where the request is in the second part
720              msg = createPKCS10MultiPartMessage(session);
721              System.out.println("creating message with pkcs10 part...");
722              baos.reset();
723              msg.saveChanges();
724              msg.writeTo(baos);
725              bais = new ByteArrayInputStream(baos.toByteArray());
726              msg = new MimeMessage(session, bais);
727              if (PRINT_MESSAGES) {
728            printMessage(msg);
729          }
730              DumpMessage.dumpMsg(msg);
731              
732              System.out.println("\n\n*****************************************\n\n");
733    
734              // compressed message 
735              msg = createCompressedMessage(session, multipart, (AlgorithmID)CMSAlgorithmID.zlib_compress.clone());
736              System.out.println("creating message with compressed data...");
737              baos.reset();
738              msg.saveChanges();
739              msg.writeTo(baos);
740              bais = new ByteArrayInputStream(baos.toByteArray());
741              msg = new MimeMessage(session, bais);
742              if (PRINT_MESSAGES) {
743            printMessage(msg);
744          }
745              DumpMessage.dumpMsg(msg);
746    
747            } catch (Exception ex) {
748                ex.printStackTrace();
749                throw new RuntimeException(ex.toString());
750            }
751      }
752    
753      /**
754       * Creates a MIME message container with the given subject for the given session.
755       * 
756       * @param session the mail sesion
757       * @param subject the subject of the message
758       *
759       * @return the MIME message with FROM, TO, DATE and SUBJECT headers (without content)
760       *
761       * @throws MessagingException if the message cannot be created
762       */
763      public Message createMessage(Session session, String subject) throws MessagingException {
764        MimeMessage msg = new MimeMessage(session);
765        msg.setFrom(new InternetAddress(from_));
766            msg.setRecipients(Message.RecipientType.TO,     InternetAddress.parse(to_, false));
767            msg.setSentDate(new Date());
768        msg.setSubject(subject);
769        return msg;
770      }
771      
772      /**
773       * Creates a simple plain (neither signed nor encrypted) message.
774       *
775       * @param session the mail session
776       * @param dataHandler the content of the message
777       * 
778       * @return the plain message
779       *
780       * @throws MessagingException if an error occurs when creating the message
781       */
782      public Message createPlainMessage(Session session, DataHandler dataHandler) throws MessagingException {
783    
784        Message msg = createMessage(session, "IAIK-S/MIME: Plain message");
785        if (dataHandler != null) {
786          msg.setDataHandler(dataHandler);
787        } else {
788          msg.setText("This is a plain message!\nIt is wether signed nor encrypted!\n");
789        }
790        return msg;
791      }
792      
793      /**
794       * Creates a signed and encrypted message.
795       *
796       * @param session the mail session
797       * @param contentEA the content encryption algorithm to be used
798       * @param keyLength the length of the secret content encryption key to be created and used
799       * @param dataHandler the content of the message to be signed and encrypted
800       * @param implicit whether to use implicit (application/pkcs7-mime) or explicit
801       *                 (multipart/signed) signing
802       * @param authEncrypt whether to create an authenticated encrypted message                
803       * 
804       * @return the signed and encrypted message
805       *
806       * @throws MessagingException if an error occurs when creating the message
807       */
808      public Message createSignedAndEncryptedMessage(Session session, 
809        AlgorithmID contentEA, int keyLength,
810        DataHandler dataHandler, boolean implicit, boolean authEncrypt)
811        throws MessagingException {
812    
813        String subject = null;
814        String text = null;
815        if (implicit) {
816          subject = "IAIK-S/MIME: Implicitly signed and " + (authEncrypt ? "authenticated " : "") + "encrypted";
817          text = "This message is implicitly signed and " + (authEncrypt ? "authenticated " : "") + "encrypted!\n\n\n";
818        } else {
819          subject = "IAIK-S/MIME: explicitly signed and " + (authEncrypt ? "authenticated " : "") + " encrypted";
820          text = "This message is explicitly signed and " + (authEncrypt ? "authenticated " : "") + " encrypted!\n\n\n";
821        }
822        Message msg = createMessage(session, subject);
823    
824        SignedContent sc = new SignedContent(implicit);
825        if (dataHandler != null) {
826          sc.setDataHandler(dataHandler);
827        } else {
828          sc.setText(text);
829        }
830        sc.setCertificates(signerCertificates_);
831        try {
832          sc.addSigner(signerPrivateKey_, 
833                       signerCertificate_,
834                       (AlgorithmID)AlgorithmID.sha256.clone(),
835                       (AlgorithmID)AlgorithmID.rsaEncryption.clone());
836        } catch (NoSuchAlgorithmException ex) {
837          throw new MessagingException("Algorithm not supported: " + ex.getMessage(), ex);
838        }
839    
840        EncryptedContent ec = null;
841        if (authEncrypt) {
842          ec = new AuthEncryptedContent(sc);
843        } else {
844          ec = new EncryptedContent(sc);
845        }
846    
847        
848        AlgorithmID algorithm = (AlgorithmID)contentEA.clone();
849        
850        // sender wants to be able to decrypt the message
851        ec.addRecipient(senderCryptCertificate_, (AlgorithmID)AlgorithmID.rsaEncryption.clone());  
852         
853        // add RSA recipient
854        ec.addRecipient(rsaRecipientCertificate_, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
855        // set the encryption algorithm
856        try {
857          ec.setEncryptionAlgorithm(algorithm, keyLength);
858        } catch (NoSuchAlgorithmException ex) {
859          throw new MessagingException("Content encryption algorithm not supported: " + ex.getMessage());   
860        }   
861        msg.setContent(ec, ec.getContentType());
862        // let the EncryptedContent update some message headers
863        ec.setHeaders(msg);
864    
865        return msg;
866      }
867      
868      /**
869       * Creates a signed message.
870       *
871       * @param session the mail session
872       * @param dataHandler the content of the message to be signed
873       * @param implicit whether to use implicit (application/pkcs7-mime) or explicit
874       *                 (multipart/signed) signing
875       * @param digestAlgorithm the digest algorithm to be used
876       * @param signatureAlgorithm the signature algorithm to be used                
877       * 
878       * @return the signed message
879       *
880       * @throws MessagingException if an error occurs when creating the message
881       */
882      public Message createSignedMessage(Session session, 
883                                         DataHandler dataHandler,
884                                         boolean implicit,
885                                         AlgorithmID digestAlgorithm,
886                                         AlgorithmID signatureAlgorithm)
887          throws MessagingException {
888    
889        String subject = null;
890        StringBuffer buf = new StringBuffer();
891        
892        if (implicit) {
893          subject = "IAIK-S/MIME: Implicitly Signed";
894          buf.append("This message is implicitly signed!\n");
895          buf.append("You need an S/MIME aware mail client to view this message.\n");
896          buf.append("\n\n");
897        } else {
898          subject = "IAIK-S/MIME: Explicitly Signed";
899          buf.append("This message is explicitly signed!\n");
900          buf.append("Every mail client can view this message.\n");
901          buf.append("Non S/MIME mail clients will show the signature as attachment.\n");
902          buf.append("\n\n");
903        }
904        
905        Message msg = createMessage(session, subject);
906        
907        SignedContent sc = new SignedContent(implicit);
908        if (dataHandler != null) {
909          sc.setDataHandler(dataHandler);
910        } else {
911          sc.setText(buf.toString());
912        }
913        sc.setCertificates(signerCertificates_);
914    
915        try {
916          sc.addSigner(signerPrivateKey_, 
917                       signerCertificate_,
918                       (AlgorithmID)digestAlgorithm.clone(),
919                       (AlgorithmID)signatureAlgorithm.clone());
920        } catch (NoSuchAlgorithmException ex) {
921          throw new MessagingException("Algorithm not supported: " + ex.getMessage(), ex);
922        }
923    
924        msg.setContent(sc, sc.getContentType());
925        // let the SignedContent update some message headers
926        sc.setHeaders(msg);
927        return msg;
928      }
929      
930      /**
931       * Creates an encrypted message.
932       *
933       * @param session the mail session
934       * @param contentEA the content encryption algorithm to be used
935       * @param keyLength the length of the secret content encryption key to be created and used
936       * 
937       * @return the encrypted message
938       *
939       * @throws MessagingException if an error occurs when creating the message
940       */
941      public Message createEncryptedMessage(Session session, AlgorithmID contentEA, int keyLength)
942        throws MessagingException {
943        
944        AlgorithmID algorithm = (AlgorithmID)contentEA.clone();
945        
946        StringBuffer subject = new StringBuffer();
947        subject.append("IAIK-S/MIME: Encrypted ["+algorithm.getName());
948        if (keyLength > 0) {
949          subject.append("/"+keyLength);
950        }  
951        subject.append("]");
952        Message msg = createMessage(session, subject.toString());
953    
954        EncryptedContent ec = new EncryptedContent();
955    
956        StringBuffer buf = new StringBuffer();
957        buf.append("This is the encrypted content!\n");
958        buf.append("Content encryption algorithm: "+algorithm.getName());
959        buf.append("\n\n");
960    
961        ec.setText(buf.toString());
962        
963        // sender wants to be able to decrypt the message
964        ec.addRecipient(senderCryptCertificate_, (AlgorithmID)AlgorithmID.rsaEncryption.clone());  
965       
966        // add RSA recipient
967        ec.addRecipient(rsaRecipientCertificate_, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
968        try {
969          ec.setEncryptionAlgorithm(algorithm, keyLength);
970        } catch (NoSuchAlgorithmException ex) {
971          throw new MessagingException("Content encryption algorithm not supported: " + ex.getMessage());   
972        }    
973    
974        msg.setContent(ec, ec.getContentType());
975        // let the EncryptedContent update some message headers
976        ec.setHeaders(msg);
977    
978        return msg;
979      }
980      
981      /**
982       * Creates an authenticated encrypted message.
983       *
984       * @param session the mail session
985       * @param contentEA the content encryption algorithm to be used
986       * @param keyLength the length of the secret content encryption key to be created and used
987       * 
988       * @return the encrypted message
989       *
990       * @throws MessagingException if an error occurs when creating the message
991       */
992      public Message createAuthEncryptedMessage(Session session, AlgorithmID contentEA, int keyLength)
993          throws MessagingException {
994        
995        AlgorithmID algorithm = (AlgorithmID)contentEA.clone();
996       
997        StringBuffer subject = new StringBuffer();
998        subject.append("IAIK-S/MIME: Authenticated Encrypted ["+algorithm.getName());
999        if (keyLength > 0) {
1000          subject.append("/"+keyLength);
1001        }  
1002        subject.append("]");
1003        Message msg = createMessage(session, subject.toString());
1004    
1005        AuthEncryptedContent ec = new AuthEncryptedContent();
1006    
1007        StringBuffer buf = new StringBuffer();
1008        buf.append("This is the authenticated encrypted content!\n");
1009        buf.append("Content encryption algorithm: "+algorithm.getName());
1010        buf.append("\n\n");
1011    
1012        ec.setText(buf.toString());
1013        
1014        // sender wants to be able to decrypt the message
1015        ec.addRecipient(senderCryptCertificate_, (AlgorithmID)AlgorithmID.rsaEncryption.clone()); 
1016        
1017        // add RSA recipient 
1018        ec.addRecipient(rsaRecipientCertificate_, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
1019        try {
1020          ec.setEncryptionAlgorithm(algorithm, keyLength);
1021        } catch (NoSuchAlgorithmException ex) {
1022          throw new MessagingException("Content encryption algorithm not supported: " + ex.getMessage());   
1023        }    
1024    
1025        msg.setContent(ec, ec.getContentType());
1026        // let the EncryptedContent update some message headers
1027        ec.setHeaders(msg);
1028    
1029        return msg;
1030      }
1031      
1032      /**
1033       * Creates a certs-only message.
1034       *
1035       * @param session the mail session
1036       * 
1037       * @return the certs-only message
1038       *
1039       * @throws MessagingException if an error occurs when creating the message
1040       */
1041      public Message createCertsOnlyMessage(Session session)
1042          throws MessagingException {
1043    
1044        Message msg = createMessage(session, "IAIK S/MIME: Certs-only message");
1045        //use new content types
1046        SMimeParameters.useNewContentTypes(true);
1047        SignedContent sc = new SignedContent(true, SignedContent.CERTS_ONLY);
1048        sc.setCertificates(signerCertificates_);
1049        msg.setContent(sc, sc.getContentType());
1050        //set filename and attachment parameters
1051        sc.setHeaders(msg);
1052    
1053        return msg;
1054      }
1055      
1056      
1057      /**
1058       * Creates a certs-only message where the certificate list is transferred as attachment.
1059       *
1060       * @param session the mail session
1061       * 
1062       * @return the certs-only message
1063       *
1064       * @throws MessagingException if an error occurs when creating the message
1065       */
1066      public Message createCertsOnlyMultiPartMessage(Session session) throws MessagingException {
1067    
1068        MimeBodyPart mbp1 = new MimeBodyPart();
1069            mbp1.setText("This is a test where the certs-only message is included in the second part!\n\n");
1070    
1071        MimeBodyPart attachment = new MimeBodyPart();
1072        //use new content types
1073        SMimeParameters.useNewContentTypes(true);
1074        SignedContent sc = new SignedContent(true, SignedContent.CERTS_ONLY);
1075        sc.setCertificates(signerCertificates_);
1076        attachment.setContent(sc, sc.getContentType());
1077        // let the SignedContent update some headers
1078        sc.setHeaders(attachment);
1079        Multipart mp = new MimeMultipart();
1080        mp.addBodyPart(mbp1);
1081        mp.addBodyPart(attachment);
1082    
1083        Message msg = createMessage(session, "IAIK S/MIME: Certs-only multipart message");
1084        msg.setContent(mp, mp.getContentType());
1085        return msg;
1086      }
1087      
1088       /**
1089       * Creates a compressed message.
1090       *
1091       * @param session the mail session
1092       * @param dataHandler the datahandler supplying the content to be compressed
1093       * @param algorithm the compression algorithm to be used
1094       * 
1095       * @return the compressed message
1096       *
1097       * @throws MessagingException if an error occurs when creating the message
1098       */
1099      public Message createCompressedMessage(Session session, DataHandler dataHandler, AlgorithmID algorithm)
1100          throws MessagingException {
1101    
1102        String subject = "IAIK-S/MIME: Compressed ["+algorithm.getName()+"]";
1103        Message msg = createMessage(session, subject.toString());
1104    
1105        CompressedContent compressedContent = new CompressedContent();
1106        
1107        if (dataHandler == null) {
1108          StringBuffer buf = new StringBuffer();
1109          buf.append("This is the compressed content!\n");
1110          buf.append("Compression algorithm: "+algorithm.getName());
1111          buf.append("\n\n");
1112          compressedContent.setText(buf.toString());
1113        } else {
1114          compressedContent.setDataHandler(dataHandler);   
1115        }    
1116        
1117        try {
1118          compressedContent.setCompressionAlgorithm(algorithm);
1119        } catch (NoSuchAlgorithmException ex) {
1120          throw new MessagingException("Compression algorithm not supported: " + ex.getMessage());   
1121        }   
1122    
1123        msg.setContent(compressedContent, compressedContent.getContentType());
1124        // let the CompressedContent update some message headers
1125        compressedContent.setHeaders(msg);
1126    
1127        return msg;
1128      }
1129    
1130      /**
1131       * Creates a PKCS#10 certificate request message.
1132       *
1133       * @param session the mail session
1134       * 
1135       * @return the PKCS#10 certificate request message
1136       *
1137       * @throws MessagingException if an error occurs when creating the message
1138       */
1139      public Message createPKCS10Message(Session session)
1140        throws MessagingException {
1141    
1142        Message msg = createMessage(session, "IAIK-S/MIME: Certificate Request");
1143    
1144        PKCS10Content pc = new PKCS10Content();
1145        CertificateRequest request = null;
1146        try {
1147           request = createCertificateRequest();
1148        } catch (PKCSException ex) {
1149           throw new MessagingException(ex.getMessage());
1150        }
1151        pc.setCertRequest(request);
1152        msg.setContent(pc, pc.getContentType());
1153        // let the PKCS10Content update some message headers
1154        pc.setHeaders(msg);
1155    
1156        return msg;
1157      }
1158    
1159    
1160      private CertificateRequest createCertificateRequest() throws PKCSException {
1161        try {
1162          Name subject = new Name();
1163              subject.addRDN(ObjectID.commonName, firstName_ + " " + lastName_);
1164              subject.addRDN(ObjectID.emailAddress, from_);
1165              CertificateRequest certRequest;
1166          certRequest = new CertificateRequest(signerCertificate_.getPublicKey(), subject);
1167              certRequest.sign((AlgorithmID)AlgorithmID.sha256WithRSAEncryption.clone(), signerPrivateKey_);
1168              certRequest.verify();
1169              return certRequest;
1170            } catch (Exception ex) {
1171              throw new PKCSException("Cannot create cert request: " + ex.getMessage());
1172            }
1173    
1174      }
1175      
1176      /**
1177       * Creates a PKCS#10 message where the certificate request is transferred as attachment.
1178       *
1179       * @param session the mail session
1180       * 
1181       * @return the PKCS#10 certificate request message
1182       *
1183       * @throws MessagingException if an error occurs when creating the message
1184       */
1185      public Message createPKCS10MultiPartMessage(Session session) throws MessagingException {
1186    
1187        MimeBodyPart mbp1 = new MimeBodyPart();
1188            mbp1.setText("This is a test where the request message is included in the second part!\n\n");
1189            // try to test an attachment
1190            // this demo attaches our homepage
1191        MimeBodyPart attachment = new MimeBodyPart();
1192        //use new content types
1193        SMimeParameters.useNewContentTypes(true);
1194        PKCS10Content pc = new PKCS10Content();
1195        CertificateRequest request = null;
1196        try {
1197          request = createCertificateRequest();
1198        } catch (PKCSException ex) {
1199          throw new MessagingException(ex.getMessage());
1200        }
1201        pc.setCertRequest(request);
1202        DataHandler pkcs10Handler = new DataHandler(pc, pc.getContentType());
1203        attachment.setDataHandler(pkcs10Handler);
1204        attachment.setDisposition("attachment");
1205        attachment.setFileName("smime.p10");
1206        Multipart mp = new MimeMultipart();
1207        mp.addBodyPart(mbp1);
1208        mp.addBodyPart(attachment);
1209    
1210        Message msg = createMessage(session, "IAIK-S/MIME: Certificate Request multipart message");
1211        msg.setContent(mp, mp.getContentType());
1212        return msg;
1213      }
1214      
1215      /** 
1216       * Prints a dump of the given message to System.out.
1217       *
1218       * @param msg the message to be dumped to System.out
1219       *
1220       * @throws IOException if an I/O error occurs
1221       */
1222      static void printMessage(Message msg) throws IOException {
1223        System.out.println("------------------------------------------------------------------");
1224        System.out.println("Message dump: \n");
1225        try {
1226          msg.writeTo(System.out);
1227        } catch (MessagingException ex) {
1228          throw new IOException(ex.getMessage());   
1229        }    
1230        System.out.println("\n------------------------------------------------------------------");
1231      }  
1232      
1233      /**
1234       * The main method.
1235       */
1236      public static void main(String[] argv) throws IOException {
1237         
1238        DemoSMimeUtil.initDemos();
1239            (new SMimeV4Demo()).start();
1240        System.out.println("\nReady!");
1241        DemoUtil.waitKey();
1242      }
1243    }