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/SMimeEnvelopedDemoAEAD.java 3     12.02.25 17:58 Dbratko $
059    // $Revision: 3 $
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    
081    import demo.DemoSMimeUtil;
082    import demo.DemoUtil;
083    import demo.keystore.CMSKeyStore;
084    import demo.smime.DumpMessage;
085    import iaik.asn1.structures.AlgorithmID;
086    import iaik.smime.AuthEncryptedContent;
087    import iaik.smime.EncryptedContent;
088    import iaik.smime.SMimeBodyPart;
089    import iaik.smime.SMimeMultipart;
090    import iaik.smime.SignedContent;
091    import iaik.x509.X509Certificate;
092    
093    /**
094     * This class demonstrates the usage of the IAIK S/MIME implementation. It shows how to create
095     * signed and/or encrypted S/MIME messages and how to parse them and verify the signatures 
096     * and decrypt the content, respectively. This demos creates encrypted messages using an AEAD
097     * cipher mode (like GCM). Although CMS and S/MIME generally use AEAD cipher modes with the 
098     * <code>AuthEnvelopedData</code> content type, it is technically possible to also use
099     * AEAD cipher modes with the <code>EnvelopedData</code> content type (when appending the mac value
100     * to the cipher text). This demo shows how to encrypt S/MIME messages with AEAD cipher modes when
101     * using the CMS <code>EnvelopedData</code> type.
102    
103     * <p>
104     * To run this demo the following packages are required:
105     * <ul>
106     *    <li>
107     *       <code>iaik_cms.jar</code> (IAIK-CMS/SMIME)
108     *    </li>
109     *    <li>
110     *       <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>).
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     */
123    public class SMimeEnvelopedDemoAEAD {
124        
125      // whether to print dump all generates test messages to System.out
126      final static boolean PRINT_MESSAGES = false;   
127      
128    
129      String firstName_ = "John";
130      String lastName_ = "SMime";
131      String to_ = "smimetest@iaik.tugraz.at";     // email recipient
132      String from_ = "smimetest@iaik.tugraz.at";   // email sender
133      String host_ = "mailhost";                   // name of the mailhost
134    
135      X509Certificate[] signerCertificates_;       // list of certificates to include in the S/MIME message
136      X509Certificate signerCertificate_;          // certificate of the signer/sender
137      PrivateKey signerPrivateKey_;                // private key of the signer/sender
138      
139      X509Certificate senderCryptCertificate_;     // the encryption certificate of the signer/sender
140      
141      X509Certificate rsaRecipientCertificate_;    // RSA encryption cert and key of a recipient
142      
143      /**
144       * Default constructor. Reads certificates and keys from the demo keystore.
145       */
146      public SMimeEnvelopedDemoAEAD() {
147        
148        System.out.println();
149        System.out.println("********************************************************************************************");
150        System.out.println("*                        SMimeEnvelopedDemoAEAD demo                                       *");
151        System.out.println("* (shows how to create and parse encrypted (enveloped) S/MIME messages with AEAD ciphers)  *");
152        System.out.println("********************************************************************************************");
153        System.out.println();
154        
155        // get the certificates from the KeyStore
156        signerCertificates_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1);
157        signerPrivateKey_ = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1);
158        signerCertificate_ = signerCertificates_[0];
159        senderCryptCertificate_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1)[0];
160    
161        rsaRecipientCertificate_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2)[0];
162    
163      }
164      
165      /**
166       * Starts the demo.
167       *
168       * @throws IOException if an I/O related error occurs
169       */
170      public void start() throws IOException {
171    
172        // get the default Session
173            Session session = DemoSMimeUtil.getSession();
174    
175            try {
176          // Create a demo Multipart
177          MimeBodyPart mbp1 = new SMimeBodyPart();
178              mbp1.setText("This is a Test of the IAIK S/MIME implementation!\n\n");
179              // attachment
180          MimeBodyPart attachment = new SMimeBodyPart();
181          attachment.setDataHandler(new DataHandler(new FileDataSource("test.html")));
182          attachment.setFileName("test.html");
183    
184          Multipart mp = new SMimeMultipart();
185          mp.addBodyPart(mbp1);
186          mp.addBodyPart(attachment);
187          DataHandler multipart = new DataHandler(mp, mp.getContentType());
188    
189          Message msg;    // the message to send
190          ByteArrayOutputStream baos = new ByteArrayOutputStream(); // we write to a stream
191          ByteArrayInputStream bais;  // we read from a stream
192    
193              
194              // Now create encrypted messages with different content encryption algorithms
195              if (DemoUtil.getIaikProviderVersion() >= 5.62) {
196                
197                msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_GCM.clone(), 128);
198            System.out.println("creating encrypted message [AES-GCM/128]...");
199            baos.reset();
200            msg.saveChanges();
201            msg.writeTo(baos);
202            bais = new ByteArrayInputStream(baos.toByteArray());
203            msg = new MimeMessage(session, bais);
204            if (PRINT_MESSAGES) {
205              printMessage(msg);
206            }
207            DumpMessage.dumpEncryptedMessage(msg);
208             
209            System.out.println("\n\n*****************************************\n\n");
210            
211            msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_GCM.clone(), 192);
212            System.out.println("creating encrypted message [AES-GCM/192]...");
213            baos.reset();
214            msg.saveChanges();
215            msg.writeTo(baos);
216            bais = new ByteArrayInputStream(baos.toByteArray());
217            msg = new MimeMessage(session, bais);
218            if (PRINT_MESSAGES) {
219              printMessage(msg);
220            }
221            DumpMessage.dumpEncryptedMessage(msg); 
222             
223            System.out.println("\n\n*****************************************\n\n");
224                
225                msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_GCM.clone(), 256);
226                System.out.println("creating encrypted message [AES-GCM/256]...");
227                baos.reset();
228                msg.saveChanges();
229                msg.writeTo(baos);
230                bais = new ByteArrayInputStream(baos.toByteArray());
231                msg = new MimeMessage(session, bais);
232                if (PRINT_MESSAGES) {
233                  printMessage(msg);
234                }
235                DumpMessage.dumpEncryptedMessage(msg);
236                 
237                System.out.println("\n\n*****************************************\n\n");
238                
239                msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_CCM.clone(), 128);
240            System.out.println("creating encrypted message [AES-CCM/128]...");
241            baos.reset();
242            msg.saveChanges();
243            msg.writeTo(baos);
244            bais = new ByteArrayInputStream(baos.toByteArray());
245            msg = new MimeMessage(session, bais);
246            if (PRINT_MESSAGES) {
247              printMessage(msg);
248            }
249            DumpMessage.dumpEncryptedMessage(msg);
250             
251            System.out.println("\n\n*****************************************\n\n");
252            
253            msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_CCM.clone(), 192);
254            System.out.println("creating encrypted message [AES-CCM/192]...");
255            baos.reset();
256            msg.saveChanges();
257            msg.writeTo(baos);
258            bais = new ByteArrayInputStream(baos.toByteArray());
259            msg = new MimeMessage(session, bais);
260            if (PRINT_MESSAGES) {
261              printMessage(msg);
262            }
263            DumpMessage.dumpEncryptedMessage(msg); 
264            
265            msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_CCM.clone(), 256);
266            System.out.println("creating encrypted message [AES-CCM/256]...");
267            baos.reset();
268            msg.saveChanges();
269            msg.writeTo(baos);
270            bais = new ByteArrayInputStream(baos.toByteArray());
271            msg = new MimeMessage(session, bais);
272            if (PRINT_MESSAGES) {
273              printMessage(msg);
274            }
275            DumpMessage.dumpEncryptedMessage(msg);
276             
277            System.out.println("\n\n*****************************************\n\n");
278            
279            msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.chacha20Poly1305.clone(), 256);
280            System.out.println("creating encrypted message [ChaChaPoly1305]...");
281            baos.reset();
282            msg.saveChanges();
283            msg.writeTo(baos);
284            bais = new ByteArrayInputStream(baos.toByteArray());
285            msg = new MimeMessage(session, bais);
286            if (PRINT_MESSAGES) {
287              printMessage(msg);
288            }
289            DumpMessage.dumpEncryptedMessage(msg);  
290             
291            System.out.println("\n\n*****************************************\n\n");
292            
293           // Create an implicitly signed and encrypted message with attachment
294            msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_GCM.clone(), 128, multipart, true, true);
295            System.out.println("creating implicitly signed and encrypted message [AES-GCM/128]...");
296            baos.reset();
297            msg.saveChanges();
298            msg.writeTo(baos);
299            bais = new ByteArrayInputStream(baos.toByteArray());
300            msg = new MimeMessage(session, bais);
301            if (PRINT_MESSAGES) {
302              printMessage(msg);
303            }
304            DumpMessage.dumpEncryptedMessage(msg);
305            
306            System.out.println("\n\n*****************************************\n\n");
307    
308            // Create an explicitly signed and encrypted message with attachment
309            msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_GCM.clone(), 128, multipart, true, true);
310            System.out.println("creating explicitly signed and encrypted message [AES-GCM/128]...");
311            baos.reset();
312            msg.saveChanges();
313            msg.writeTo(baos);
314            bais = new ByteArrayInputStream(baos.toByteArray());
315            msg = new MimeMessage(session, bais);
316            if (PRINT_MESSAGES) {
317              printMessage(msg);
318            }
319            DumpMessage.dumpEncryptedMessage(msg);
320            
321            System.out.println("\n\n*****************************************\n\n");
322            
323            // Create an implicitly signed and encrypted message with attachment
324            msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_GCM.clone(), 192, multipart, true, true);
325            System.out.println("creating implicitly signed and encrypted message [AES-GCM/192]...");
326            baos.reset();
327            msg.saveChanges();
328            msg.writeTo(baos);
329            bais = new ByteArrayInputStream(baos.toByteArray());
330            msg = new MimeMessage(session, bais);
331            if (PRINT_MESSAGES) {
332              printMessage(msg);
333            }
334            DumpMessage.dumpEncryptedMessage(msg);
335            
336            System.out.println("\n\n*****************************************\n\n");
337    
338            // Create an explicitly signed and encrypted message with attachment
339            msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_GCM.clone(), 192, multipart, true, true);
340            System.out.println("creating explicitly signed and encrypted message [AES-GCM/192]...");
341            baos.reset();
342            msg.saveChanges();
343            msg.writeTo(baos);
344            bais = new ByteArrayInputStream(baos.toByteArray());
345            msg = new MimeMessage(session, bais);
346            if (PRINT_MESSAGES) {
347              printMessage(msg);
348            }
349            DumpMessage.dumpEncryptedMessage(msg);
350            
351            System.out.println("\n\n*****************************************\n\n");
352                
353            // Create an implicitly signed and encrypted message with attachment
354            msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_GCM.clone(), 256, multipart, true, true);
355            System.out.println("creating implicitly signed and encrypted message [AES-GCM/256]...");
356            baos.reset();
357            msg.saveChanges();
358            msg.writeTo(baos);
359            bais = new ByteArrayInputStream(baos.toByteArray());
360            msg = new MimeMessage(session, bais);
361            if (PRINT_MESSAGES) {
362              printMessage(msg);
363            }
364            DumpMessage.dumpEncryptedMessage(msg);
365            
366            System.out.println("\n\n*****************************************\n\n");
367    
368            // Create an explicitly signed and encrypted message with attachment
369            msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_GCM.clone(), 256, multipart, true, true);
370            System.out.println("creating explicitly signed and encrypted message [AES-GCM/256]...");
371            baos.reset();
372            msg.saveChanges();
373            msg.writeTo(baos);
374            bais = new ByteArrayInputStream(baos.toByteArray());
375            msg = new MimeMessage(session, bais);
376            if (PRINT_MESSAGES) {
377              printMessage(msg);
378            }
379            DumpMessage.dumpEncryptedMessage(msg);
380            
381            System.out.println("\n\n*****************************************\n\n");
382            
383            
384            // Create an implicitly signed and encrypted message with attachment
385             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_CCM.clone(), 128, multipart, true, true);
386             System.out.println("creating implicitly signed and encrypted message [AES-CCM/128]...");
387             baos.reset();
388             msg.saveChanges();
389             msg.writeTo(baos);
390             bais = new ByteArrayInputStream(baos.toByteArray());
391             msg = new MimeMessage(session, bais);
392             if (PRINT_MESSAGES) {
393               printMessage(msg);
394             }
395             DumpMessage.dumpEncryptedMessage(msg);
396             
397             System.out.println("\n\n*****************************************\n\n");
398    
399             // Create an explicitly signed and encrypted message with attachment
400             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_CCM.clone(), 128, multipart, true, true);
401             System.out.println("creating explicitly signed and encrypted message [AES-CCM/128]...");
402             baos.reset();
403             msg.saveChanges();
404             msg.writeTo(baos);
405             bais = new ByteArrayInputStream(baos.toByteArray());
406             msg = new MimeMessage(session, bais);
407             if (PRINT_MESSAGES) {
408               printMessage(msg);
409             }
410             DumpMessage.dumpEncryptedMessage(msg);
411             
412             System.out.println("\n\n*****************************************\n\n");
413             
414             // Create an implicitly signed and encrypted message with attachment
415             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_CCM.clone(), 192, multipart, true, true);
416             System.out.println("creating implicitly signed and encrypted message [AES-CCM/192]...");
417             baos.reset();
418             msg.saveChanges();
419             msg.writeTo(baos);
420             bais = new ByteArrayInputStream(baos.toByteArray());
421             msg = new MimeMessage(session, bais);
422             if (PRINT_MESSAGES) {
423               printMessage(msg);
424             }
425             DumpMessage.dumpEncryptedMessage(msg);
426             
427             System.out.println("\n\n*****************************************\n\n");
428    
429             // Create an explicitly signed and encrypted message with attachment
430             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_CCM.clone(), 192, multipart, true, true);
431             System.out.println("creating explicitly signed and encrypted message [AES-CCM/192]...");
432             baos.reset();
433             msg.saveChanges();
434             msg.writeTo(baos);
435             bais = new ByteArrayInputStream(baos.toByteArray());
436             msg = new MimeMessage(session, bais);
437             if (PRINT_MESSAGES) {
438               printMessage(msg);
439             }
440             DumpMessage.dumpEncryptedMessage(msg);
441             
442             System.out.println("\n\n*****************************************\n\n");
443             
444             // Create an implicitly signed and encrypted message with attachment
445             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_CCM.clone(), 256, multipart, true, true);
446             System.out.println("creating implicitly signed and encrypted message [AES-CCM/256]...");
447             baos.reset();
448             msg.saveChanges();
449             msg.writeTo(baos);
450             bais = new ByteArrayInputStream(baos.toByteArray());
451             msg = new MimeMessage(session, bais);
452             if (PRINT_MESSAGES) {
453               printMessage(msg);
454             }
455             DumpMessage.dumpEncryptedMessage(msg);
456             
457             System.out.println("\n\n*****************************************\n\n");
458    
459             // Create an explicitly signed and encrypted message with attachment
460             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_CCM.clone(), 256, multipart, true, true);
461             System.out.println("creating explicitly signed and encrypted message [AES-CCM/256]...");
462             baos.reset();
463             msg.saveChanges();
464             msg.writeTo(baos);
465             bais = new ByteArrayInputStream(baos.toByteArray());
466             msg = new MimeMessage(session, bais);
467             if (PRINT_MESSAGES) {
468               printMessage(msg);
469             }
470             DumpMessage.dumpEncryptedMessage(msg);
471             
472             System.out.println("\n\n*****************************************\n\n");
473            
474             // Create an implicitly signed and encrypted message with attachment
475             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.chacha20Poly1305.clone(), 256, multipart, true, true);
476             System.out.println("creating implicitly signed and encrypted message [ChaCha20Poly1305]...");
477             baos.reset();
478             msg.saveChanges();
479             msg.writeTo(baos);
480             bais = new ByteArrayInputStream(baos.toByteArray());
481             msg = new MimeMessage(session, bais);
482             if (PRINT_MESSAGES) {
483               printMessage(msg);
484             }
485             DumpMessage.dumpEncryptedMessage(msg);
486             
487             System.out.println("\n\n*****************************************\n\n");
488    
489             // Create an explicitly signed and encrypted message with attachment
490             msg = createSignedAndEncryptedMessage(session, (AlgorithmID)AlgorithmID.chacha20Poly1305.clone(), 256, multipart, true, true);
491             System.out.println("creating explicitly signed and encrypted message [ChaCha20Poly1305]...");
492             baos.reset();
493             msg.saveChanges();
494             msg.writeTo(baos);
495             bais = new ByteArrayInputStream(baos.toByteArray());
496             msg = new MimeMessage(session, bais);
497             if (PRINT_MESSAGES) {
498               printMessage(msg);
499             }
500             DumpMessage.dumpEncryptedMessage(msg);
501             
502             System.out.println("\n\n*****************************************\n\n");
503                
504              }
505             
506             
507    
508            } catch (Exception ex) {
509                ex.printStackTrace();
510                throw new RuntimeException(ex.toString());
511            }
512      }
513    
514      /**
515       * Creates a MIME message container with the given subject for the given session.
516       * 
517       * @param session the mail sesion
518       * @param subject the subject of the message
519       *
520       * @return the MIME message with FROM, TO, DATE and SUBJECT headers (without content)
521       *
522       * @throws MessagingException if the message cannot be created
523       */
524      public Message createMessage(Session session, String subject) throws MessagingException {
525        MimeMessage msg = new MimeMessage(session);
526        msg.setFrom(new InternetAddress(from_));
527            msg.setRecipients(Message.RecipientType.TO,     InternetAddress.parse(to_, false));
528            msg.setSentDate(new Date());
529        msg.setSubject(subject);
530        return msg;
531      }
532      
533      /**
534       * Creates a simple plain (neither signed nor encrypted) message.
535       *
536       * @param session the mail session
537       * @param dataHandler the content of the message
538       * 
539       * @return the plain message
540       *
541       * @throws MessagingException if an error occurs when creating the message
542       */
543      public Message createPlainMessage(Session session, DataHandler dataHandler) throws MessagingException {
544    
545        Message msg = createMessage(session, "IAIK-S/MIME: Plain message");
546        if (dataHandler != null) {
547          msg.setDataHandler(dataHandler);
548        } else {
549          msg.setText("This is a plain message!\nIt is wether signed nor encrypted!\n");
550        }
551        return msg;
552      }
553      
554      /**
555       * Creates a signed and encrypted message.
556       *
557       * @param session the mail session
558       * @param contentEA the content encryption algorithm to be used
559       * @param keyLength the length of the secret content encryption key to be created and used
560       * @param dataHandler the content of the message to be signed and encrypted
561       * @param implicit whether to use implicit (application/pkcs7-mime) or explicit
562       *                 (multipart/signed) signing
563       * @param authEncrypt whether to create an encrypted message                
564       * 
565       * @return the signed and encrypted message
566       *
567       * @throws MessagingException if an error occurs when creating the message
568       */
569      public Message createSignedAndEncryptedMessage(Session session, 
570        AlgorithmID contentEA, int keyLength,
571        DataHandler dataHandler, boolean implicit, boolean authEncrypt)
572        throws MessagingException {
573    
574        String subject = null;
575        String text = null;
576        if (implicit) {
577          subject = "IAIK-S/MIME: Implicitly signed and " + (authEncrypt ? "authenticated " : "") + "encrypted";
578          text = "This message is implicitly signed and " + (authEncrypt ? "authenticated " : "") + "encrypted!\n\n\n";
579        } else {
580          subject = "IAIK-S/MIME: explicitly signed and " + (authEncrypt ? "authenticated " : "") + " encrypted";
581          text = "This message is explicitly signed and " + (authEncrypt ? "authenticated " : "") + " encrypted!\n\n\n";
582        }
583        Message msg = createMessage(session, subject);
584    
585        SignedContent sc = new SignedContent(implicit);
586        if (dataHandler != null) {
587          sc.setDataHandler(dataHandler);
588        } else {
589          sc.setText(text);
590        }
591        sc.setCertificates(signerCertificates_);
592        try {
593          sc.addSigner(signerPrivateKey_, 
594                       signerCertificate_,
595                       (AlgorithmID)AlgorithmID.sha256.clone(),
596                       (AlgorithmID)AlgorithmID.rsaEncryption.clone());
597        } catch (NoSuchAlgorithmException ex) {
598          throw new MessagingException("Algorithm not supported: " + ex.getMessage(), ex);
599        }
600    
601        EncryptedContent ec = null;
602        if (authEncrypt) {
603          ec = new AuthEncryptedContent(sc);
604        } else {
605          ec = new EncryptedContent(sc);
606        }
607    
608        
609        AlgorithmID algorithm = (AlgorithmID)contentEA.clone();
610        
611        // sender wants to be able to decrypt the message
612        ec.addRecipient(senderCryptCertificate_, (AlgorithmID)AlgorithmID.rsaEncryption.clone());  
613         
614        // add RSA recipient
615        ec.addRecipient(rsaRecipientCertificate_, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
616        // set the encryption algorithm
617        try {
618          ec.setEncryptionAlgorithm(algorithm, keyLength);
619        } catch (NoSuchAlgorithmException ex) {
620          throw new MessagingException("Content encryption algorithm not supported: " + ex.getMessage());   
621        }   
622        msg.setContent(ec, ec.getContentType());
623        // let the EncryptedContent update some message headers
624        ec.setHeaders(msg);
625    
626        return msg;
627      }
628      
629      /**
630       * Creates a signed message.
631       *
632       * @param session the mail session
633       * @param dataHandler the content of the message to be signed
634       * @param implicit whether to use implicit (application/pkcs7-mime) or explicit
635       *                 (multipart/signed) signing
636       * @param digestAlgorithm the digest algorithm to be used
637       * @param signatureAlgorithm the signature algorithm to be used                
638       * 
639       * @return the signed message
640       *
641       * @throws MessagingException if an error occurs when creating the message
642       */
643      public Message createSignedMessage(Session session, 
644                                         DataHandler dataHandler,
645                                         boolean implicit,
646                                         AlgorithmID digestAlgorithm,
647                                         AlgorithmID signatureAlgorithm)
648          throws MessagingException {
649    
650        String subject = null;
651        StringBuffer buf = new StringBuffer();
652        
653        if (implicit) {
654          subject = "IAIK-S/MIME: Implicitly Signed";
655          buf.append("This message is implicitly signed!\n");
656          buf.append("You need an S/MIME aware mail client to view this message.\n");
657          buf.append("\n\n");
658        } else {
659          subject = "IAIK-S/MIME: Explicitly Signed";
660          buf.append("This message is explicitly signed!\n");
661          buf.append("Every mail client can view this message.\n");
662          buf.append("Non S/MIME mail clients will show the signature as attachment.\n");
663          buf.append("\n\n");
664        }
665        
666        Message msg = createMessage(session, subject);
667        
668        SignedContent sc = new SignedContent(implicit);
669        if (dataHandler != null) {
670          sc.setDataHandler(dataHandler);
671        } else {
672          sc.setText(buf.toString());
673        }
674        sc.setCertificates(signerCertificates_);
675    
676        try {
677          sc.addSigner(signerPrivateKey_, 
678                       signerCertificate_,
679                       (AlgorithmID)digestAlgorithm.clone(),
680                       (AlgorithmID)signatureAlgorithm.clone());
681        } catch (NoSuchAlgorithmException ex) {
682          throw new MessagingException("Algorithm not supported: " + ex.getMessage(), ex);
683        }
684    
685        msg.setContent(sc, sc.getContentType());
686        // let the SignedContent update some message headers
687        sc.setHeaders(msg);
688        return msg;
689      }
690      
691      /**
692       * Creates an encrypted message.
693       *
694       * @param session the mail session
695       * @param contentEA the content encryption algorithm to be used
696       * @param keyLength the length of the secret content encryption key to be created and used
697       * 
698       * @return the encrypted message
699       *
700       * @throws MessagingException if an error occurs when creating the message
701       */
702      public Message createEncryptedMessage(Session session, AlgorithmID contentEA, int keyLength)
703        throws MessagingException {
704        
705        AlgorithmID algorithm = (AlgorithmID)contentEA.clone();
706        
707        StringBuffer subject = new StringBuffer();
708        subject.append("IAIK-S/MIME: Encrypted ["+algorithm.getName());
709        if (keyLength > 0) {
710          subject.append("/"+keyLength);
711        }  
712        subject.append("]");
713        Message msg = createMessage(session, subject.toString());
714    
715        EncryptedContent ec = new EncryptedContent();
716    
717        StringBuffer buf = new StringBuffer();
718        buf.append("This is the encrypted content!\n");
719        buf.append("Content encryption algorithm: "+algorithm.getName());
720        buf.append("\n\n");
721    
722        ec.setText(buf.toString());
723        
724        // sender wants to be able to decrypt the message
725        ec.addRecipient(senderCryptCertificate_, (AlgorithmID)AlgorithmID.rsaEncryption.clone());  
726       
727        // add RSA recipient
728        ec.addRecipient(rsaRecipientCertificate_, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
729        try {
730          ec.setEncryptionAlgorithm(algorithm, keyLength);
731        } catch (NoSuchAlgorithmException ex) {
732          throw new MessagingException("Content encryption algorithm not supported: " + ex.getMessage());   
733        }    
734    
735        msg.setContent(ec, ec.getContentType());
736        // let the EncryptedContent update some message headers
737        ec.setHeaders(msg);
738    
739        return msg;
740      }
741      
742      
743      /** 
744       * Prints a dump of the given message to System.out.
745       *
746       * @param msg the message to be dumped to System.out
747       *
748       * @throws IOException if an I/O error occurs
749       */
750      static void printMessage(Message msg) throws IOException {
751        System.out.println("------------------------------------------------------------------");
752        System.out.println("Message dump: \n");
753        try {
754          msg.writeTo(System.out);
755        } catch (MessagingException ex) {
756          throw new IOException(ex.getMessage());   
757        }    
758        System.out.println("\n------------------------------------------------------------------");
759      }  
760      
761      /**
762       * The main method.
763       */
764      public static void main(String[] argv) throws IOException {
765        String jdkVersion = (String) System.getProperty("java.version");
766        if (jdkVersion.compareTo("1.7") >= 0) { 
767          DemoSMimeUtil.initDemos();
768            (new SMimeEnvelopedDemoAEAD()).start();
769          System.out.println("\nReady!");
770          DemoUtil.waitKey();
771        } else {
772          System.err.println("This demo requires Java 7 or later!");
773        }  
774      }
775    }