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/SMimeSendDemo.java 38    12.02.25 17:58 Dbratko $
059    // $Revision: 38 $
060    //
061    
062    package demo.smime.basic;
063    
064    import iaik.asn1.ObjectID;
065    import iaik.asn1.structures.AlgorithmID;
066    import iaik.asn1.structures.Name;
067    import iaik.pkcs.PKCSException;
068    import iaik.pkcs.pkcs10.CertificateRequest;
069    import iaik.smime.EncryptedContent;
070    import iaik.smime.PKCS10Content;
071    import iaik.smime.SMimeBodyPart;
072    import iaik.smime.SMimeMultipart;
073    import iaik.smime.SMimeParameters;
074    import iaik.smime.SignedContent;
075    import iaik.x509.X509Certificate;
076    
077    import java.io.IOException;
078    import java.security.NoSuchAlgorithmException;
079    import java.security.PrivateKey;
080    import java.security.interfaces.RSAPrivateKey;
081    import java.util.Date;
082    
083    import javax.activation.DataHandler;
084    import javax.activation.FileDataSource;
085    import javax.mail.Message;
086    import javax.mail.MessagingException;
087    import javax.mail.Multipart;
088    import javax.mail.Session;
089    import javax.mail.Transport;
090    import javax.mail.internet.InternetAddress;
091    import javax.mail.internet.MimeBodyPart;
092    import javax.mail.internet.MimeMessage;
093    import javax.mail.internet.MimeMultipart;
094    
095    import demo.DemoSMimeUtil;
096    import demo.DemoUtil;
097    import demo.keystore.CMSKeyStore;
098    
099    /**
100     * This class demonstrates the usage of the IAIK S/MIME implementation for sending
101     * signed and/or encryped emails based on the JavaMail API. 
102     * <p>
103     * To run this demo the following packages are required:
104     * <ul>
105     *    <li>
106     *       <code>iaik_cms.jar</code> (IAIK-CMS/SMIME)
107     *    </li>
108     *    <li>
109     *       <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>).
110     *    </li>
111     *    <li>
112     *       <code>mail.jar</code> (<a href="http://www.oracle.com/technetwork/java/javamail/index.html" target="_blank">JavaMail API</a>).
113     *    </li>   
114     *    <li>
115     *       <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).
116     *    </li> 
117     * </ul>
118     * 
119     * <b>Usage:</b>
120     * <pre>
121     * SMimeSend [-H host] [-S sender name] [-F (From) sender address] [-T (To) recipient address]
122     * </pre>
123     * <b>Example</b>:
124     * <pre>
125     * SMimeSend -H mailhost -S \"John SMime\" -F smimetest@iaik.tugraz.at -T smimetest@iaik.tugraz.at
126     * </pre>
127     * By default this demo used "mailhost" as host, "John SMime" as sender name, and "smimetest@iaik.tugraz.at"
128     * as sender and also as recipient mail address. "smimetest@iaik.tugraz.at" is also the email address
129     * contained in the demo certificates. Although you should specify other email addresses to send
130     * the test messages to yourself, be aware that the certificate email check may fail on the
131     * receiving side ({@link SMimeShowDemo SMimeShowDemo}).
132     *
133     * @see iaik.smime.EncryptedContent
134     * @see iaik.smime.SignedContent
135     */
136    public class SMimeSendDemo {
137    
138      String senderName_ = "John SMime";
139      String to_ = "smimetest@iaik.tugraz.at";     // email recipient
140      String from_ = "smimetest@iaik.tugraz.at";   // email sender
141      String host_ = "mailhost";                   // name of the mailhost
142    
143      X509Certificate[] signerCertificates_;    // list of certificates to include in the S/MIME message
144      X509Certificate recipientCertificate_;    // certificate of the recipient
145      X509Certificate signerCertificate_;       // certificate of the signer/sender
146      X509Certificate encryptionCertOfSigner_;  // signer uses different certificate for encryption
147      PrivateKey signerPrivateKey_;             // private key of the signer/sender
148      
149      /**
150       * Default constructor. Reads certificates and keys from the demo keystore.
151       */
152      public SMimeSendDemo() {
153        
154        System.out.println();
155        System.out.println("******************************************************************************************");
156        System.out.println("*                                 SMimeSend demo                                         *");
157        System.out.println("*         (shows how to create and send signed and encrypted S/MIME messages)            *");
158        System.out.println("******************************************************************************************");
159        System.out.println();
160        
161        // get the certificates from the KeyStore
162        signerCertificates_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1);
163        signerPrivateKey_ = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1);
164        signerCertificate_ = signerCertificates_[0];
165    
166        // recipient = signer for this test
167        recipientCertificate_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2)[0];
168        encryptionCertOfSigner_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1)[0];
169        
170        // send the encryption cert of the signer along with the signer certificates
171        X509Certificate[] tmpCerts = new X509Certificate[signerCertificates_.length + 1];
172        System.arraycopy(signerCertificates_, 0, tmpCerts, 0, signerCertificates_.length);
173        tmpCerts[signerCertificates_.length] = encryptionCertOfSigner_;
174        signerCertificates_ = tmpCerts;
175      }
176      
177      /**
178       * Starts the demo.
179       *
180       *
181       * @param argv optional parameters like mailhost, sender name,...
182       * 
183       * @throws IOException if an I/O related error occurs
184       */
185      public void start(String[] argv) throws IOException {
186        
187        int optind = 0;
188        if (argv.length > 0) {
189          for (optind = 0; optind < argv.length; optind++) {
190            if (argv[optind].equals("-H")) {
191              host_ = argv[++optind];
192            } else if (argv[optind].equals("-S")) {
193              senderName_ = argv[++optind];
194            } else if (argv[optind].equals("-F")) {
195              from_ = argv[++optind];
196            } else if (argv[optind].equals("-T")) {
197              to_ = argv[++optind];
198            } else {
199              System.out.println("Usage: SMimeSend [-H host] [-S sender name] [-F (From) sender address] [-T (To) recipient address]");
200              System.out.println("e.g.:");
201              System.out.println("Usage: SMimeSend -H mailhost -S \"John SMime\" -F smimetest@iaik.tugraz.at -T smimetest@iaik.tugraz.at");
202              System.exit(1);
203            } 
204          }  
205        } 
206    
207    
208        // get the default Session
209            Session session = DemoSMimeUtil.getSession(host_);
210    
211            try {
212          // Create a demo Multipart
213          MimeBodyPart mbp1 = new SMimeBodyPart();
214              mbp1.setText("This is a Test of the IAIK S/MIME implementation!\n\n");
215          // try to test an attachment
216          MimeBodyPart attachment = new SMimeBodyPart();
217          attachment.setDataHandler(new DataHandler(new FileDataSource("test.html")));
218          attachment.setFileName("test.html");
219          Multipart mp = new SMimeMultipart();
220          mp.addBodyPart(mbp1);
221          mp.addBodyPart(attachment);
222          DataHandler multipart = new DataHandler(mp, mp.getContentType());
223    
224          Message msg;    // the message to send
225    
226          // 1. This is a plain message
227          msg = createPlainMessage(session, multipart);
228          System.out.println("sending plain message...");
229              Transport.send(msg);
230    
231          // 2. This is an explicitly signed message
232          msg = createSignedMessage(session, multipart, false);
233          System.out.println("sending explicitly signed message...");
234              Transport.send(msg);
235    
236          // 3. This is an implicitly signed message
237          msg = createSignedMessage(session, multipart, true);
238          System.out.println("sending implicitly signed message...");
239              Transport.send(msg);
240    
241          // 4. Now create encrypted messages with different content encryption algorithms
242              // RC2 is deprecated; only demonstrated here
243          msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.rc2_CBC.clone(), 40);
244          System.out.println("sending encrypted message [RC2/40]...");
245              Transport.send(msg);
246          
247          msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.rc2_CBC.clone(), 64);
248          System.out.println("sending encrypted message [RC2/64]...");
249              Transport.send(msg);
250          
251          msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.rc2_CBC.clone(), 128);
252          System.out.println("sending encrypted message [RC2/128]...");
253              Transport.send(msg);
254          
255              // TripleDES is deprecated; only demonstrated here
256          msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.des_EDE3_CBC.clone(), 192);
257          System.out.println("sending encrypted message [TripleDES]...");
258              Transport.send(msg);
259              
260              msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes128_CBC.clone(), 128);
261          System.out.println("sending encrypted message [AES-128]...");
262          Transport.send(msg);
263          
264          msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes192_CBC.clone(), 192);
265          System.out.println("sending encrypted message [AES-192]...");
266          Transport.send(msg);
267          
268          msg = createEncryptedMessage(session, (AlgorithmID)AlgorithmID.aes256_CBC.clone(), 256);
269          System.out.println("sending encrypted message [AES-256]...");
270          Transport.send(msg);
271    
272          // 5. Now create a implicitly signed and encrypted message with attachment
273          msg = createSignedAndEncryptedMessage(session, multipart, true);
274          System.out.println("sending implicitly signed and encrypted message [AES-256]...");
275              Transport.send(msg);
276    
277          // 6. Now create a explicitly signed and encrypted message with attachment
278          msg = createSignedAndEncryptedMessage(session, multipart, false);
279          System.out.println("sending explicitly signed and encrypted message [AES-256]...");
280              Transport.send(msg);
281    
282              // 7. certs only message
283              msg = createCertsOnlyMessage(session);
284              System.out.println("sending certs-only message");
285              Transport.send(msg);
286    
287              // 8. second certs only message
288              msg = createCertsOnlyMultiPartMessage(session);
289              System.out.println("sending message with certs-only part");
290              Transport.send(msg);
291    
292              //sending cert request
293          msg = createPKCS10Message(session);
294          System.out.println("sending application/pkcs10 message...");
295              Transport.send(msg);
296    
297              // ending application/pkcs10 message where the request is in the second part
298              msg = createPKCS10MultiPartMessage(session);
299              System.out.println("sending message with pkcs10 part...");
300              Transport.send(msg);
301    
302            } catch (MessagingException mex) {
303          mex.printStackTrace();
304              Exception ex = null;
305              if ((ex = mex.getNextException()) != null) {
306            ex.printStackTrace();
307              }
308              throw new RuntimeException(mex.toString());
309            }
310    
311      }
312      
313      /**
314       * Creates a MIME message container with the given subject for the given session.
315       * 
316       * @param session the mail sesion
317       * @param subject the subject of the message
318       *
319       * @return the MIME message with FROM, TO, DATE and SUBJECT headers (without content)
320       *
321       * @throws MessagingException if the message cannot be created
322       */
323      public Message createMessage(Session session, String subject) throws MessagingException {
324        MimeMessage msg = new MimeMessage(session);
325        msg.setFrom(new InternetAddress(from_));
326            msg.setRecipients(Message.RecipientType.TO,     InternetAddress.parse(to_, false));
327            msg.setSentDate(new Date());
328        msg.setSubject(subject);
329        return msg;
330      }
331      
332      /**
333       * Creates a simple plain (neither signed nor encrypted) message.
334       *
335       * @param session the mail session
336       * @param dataHandler the content of the message
337       * 
338       * @return the plain message
339       *
340       * @throws MessagingException if an error occurs when creating the message
341       */
342      public Message createPlainMessage(Session session, DataHandler dataHandler) throws MessagingException {
343    
344        Message msg = createMessage(session, "IAIK-S/MIME: Plain message");
345        if (dataHandler != null) {
346          msg.setDataHandler(dataHandler);
347        } else {
348          msg.setText("This is a plain message!\nIt is wether signed nor encrypted!\n");
349        }
350        return msg;
351      }
352    
353      /**
354       * Creates a signed and encrypted message.
355       *
356       * @param session the mail session
357       * @param dataHandler the content of the message to be signed and encrypted
358       * @param implicit whether to use implicit (application/pkcs7-mime) or explicit
359       *                 (multipart/signed) signing
360       * 
361       * @return the signed and encrypted message
362       *
363       * @throws MessagingException if an error occurs when creating the message
364       */
365      public Message createSignedAndEncryptedMessage(Session session, DataHandler dataHandler, boolean implicit)
366        throws MessagingException {
367    
368        String subject = null;
369        String text = null;
370        if (implicit) {
371          subject = "IAIK-S/MIME: Implicitly Signed and Encrypted";
372          text = "This message is implicitly signed and encrypted!\n\n\n";
373        } else {
374          subject = "IAIK-S/MIME: Explicitly Signed and Encrypted";
375          text = "This message is explicitly signed and encrypted!\n\n\n";
376        }
377        Message msg = createMessage(session, subject);
378    
379        SignedContent sc = new SignedContent(implicit);
380        if (dataHandler != null) {
381          sc.setDataHandler(dataHandler);
382        } else {
383          sc.setText(text);
384        }
385        sc.setCertificates(signerCertificates_);
386        try {
387          sc.addSigner((RSAPrivateKey)signerPrivateKey_, signerCertificate_, encryptionCertOfSigner_, true);
388        } catch (NoSuchAlgorithmException ex) {
389          throw new MessagingException("Algorithm not supported: " + ex.getMessage(), ex);
390        }
391    
392        EncryptedContent ec = new EncryptedContent(sc);
393        // encrypt for the recipient
394        ec.addRecipient(recipientCertificate_, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
395        // I want to be able to decrypt the message, too
396        ec.addRecipient(encryptionCertOfSigner_, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
397        // set the encryption algorithm
398        try {
399          ec.setEncryptionAlgorithm((AlgorithmID)AlgorithmID.aes256_CBC.clone(), 256);
400        } catch (NoSuchAlgorithmException ex) {
401          throw new MessagingException("Content encryption algorithm not supported: " + ex.getMessage());   
402        }   
403        msg.setContent(ec, ec.getContentType());
404        // let the EncryptedContent update some message headers
405        ec.setHeaders(msg);
406    
407        return msg;
408      }
409      
410      /**
411       * Creates a signed message.
412       *
413       * @param session the mail session
414       * @param dataHandler the content of the message to be signed
415       * @param implicit whether to use implicit (application/pkcs7-mime) or explicit
416       *                 (multipart/signed) signing
417       * 
418       * @return the signed message
419       *
420       * @throws MessagingException if an error occurs when creating the message
421       */
422      public Message createSignedMessage(Session session, DataHandler dataHandler, boolean implicit)
423          throws MessagingException {
424    
425        String subject = null;
426        StringBuffer buf = new StringBuffer();
427        
428        if (implicit) {
429          subject = "IAIK-S/MIME: Implicitly Signed";
430          buf.append("This message is implicitly signed!\n");
431          buf.append("You need an S/MIME aware mail client to view this message.\n");
432          buf.append("\n\n");
433        } else {
434          subject = "IAIK-S/MIME: Explicitly Signed";
435          buf.append("This message is explicitly signed!\n");
436          buf.append("Every mail client can view this message.\n");
437          buf.append("Non S/MIME mail clients will show the signature as attachment.\n");
438          buf.append("\n\n");
439        }
440        
441        Message msg = createMessage(session, subject);
442        
443        SignedContent sc = new SignedContent(implicit);
444        if (dataHandler != null) {
445          sc.setDataHandler(dataHandler);
446        } else {
447          sc.setText(buf.toString());
448        }
449        sc.setCertificates(signerCertificates_);
450    
451        try {
452          sc.addSigner((RSAPrivateKey)signerPrivateKey_, signerCertificate_, encryptionCertOfSigner_, true);
453        } catch (NoSuchAlgorithmException ex) {
454          throw new MessagingException("Algorithm not supported: " + ex.getMessage(), ex);
455        }
456    
457        msg.setContent(sc, sc.getContentType());
458        // let the SignedContent update some message headers
459        sc.setHeaders(msg);
460        return msg;
461      }
462      
463      /**
464       * Creates an encrypted message.
465       *
466       * @param session the mail session
467       * @param algorithm the content encryption algorithm to be used
468       * @param keyLength the length of the secret content encryption key to be created and used
469       * 
470       * @return the encrypted message
471       *
472       * @throws MessagingException if an error occurs when creating the message
473       */
474      public Message createEncryptedMessage(Session session, AlgorithmID algorithm, int keyLength)
475          throws MessagingException {
476    
477        StringBuffer subject = new StringBuffer();
478        subject.append("IAIK-S/MIME: Encrypted ["+algorithm.getName());
479        if (keyLength > 0) {
480          subject.append("/"+keyLength);
481        }  
482        subject.append("]");
483        Message msg = createMessage(session, subject.toString());
484    
485        EncryptedContent ec = new EncryptedContent();
486    
487        StringBuffer buf = new StringBuffer();
488        buf.append("This is the encrypted content!\n");
489        buf.append("Content encryption algorithm: "+algorithm.getName());
490        buf.append("\n\n");
491    
492        ec.setText(buf.toString());
493        // encrypt for the recipient
494        ec.addRecipient(recipientCertificate_, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
495        // I want to be able to decrypt the message, too
496        ec.addRecipient(encryptionCertOfSigner_, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
497        try {
498          ec.setEncryptionAlgorithm(algorithm, keyLength);
499        } catch (NoSuchAlgorithmException ex) {
500          throw new MessagingException("Content encryption algorithm not supported: " + ex.getMessage());   
501        }   
502    
503        msg.setContent(ec, ec.getContentType());
504        // let the EncryptedContent update some message headers
505        ec.setHeaders(msg);
506    
507        return msg;
508      }
509      
510      /**
511       * Creates a certs-only message.
512       *
513       * @param session the mail session
514       * 
515       * @return the certs-only message
516       *
517       * @throws MessagingException if an error occurs when creating the message
518       */
519      public Message createCertsOnlyMessage(Session session)
520          throws MessagingException {
521    
522        Message msg = createMessage(session, "IAIK S/MIME: Certs-only message");
523        //use new content types
524        SMimeParameters.useNewContentTypes(true);
525        SignedContent sc = new SignedContent(true, SignedContent.CERTS_ONLY);
526        sc.setCertificates(signerCertificates_);
527        msg.setContent(sc, sc.getContentType());
528        //set filename and attachment parameters
529        sc.setHeaders(msg);
530    
531    
532        return msg;
533      }
534    
535      
536      /**
537       * Creates a certs-only message where the certificate list is transferred as attachment.
538       *
539       * @param session the mail session
540       * 
541       * @return the certs-only message
542       *
543       * @throws MessagingException if an error occurs when creating the message
544       */
545      public Message createCertsOnlyMultiPartMessage(Session session) throws MessagingException {
546    
547        MimeBodyPart mbp1 = new MimeBodyPart();
548            mbp1.setText("This is a test where the certs-only message is included in the second part!\n\n");
549    
550        MimeBodyPart attachment = new MimeBodyPart();
551        //use new content types
552        SMimeParameters.useNewContentTypes(true);
553        SignedContent sc = new SignedContent(true, SignedContent.CERTS_ONLY);
554        sc.setCertificates(signerCertificates_);
555        attachment.setContent(sc, sc.getContentType());
556        // let the SignedContent update some message headers
557        sc.setHeaders(attachment);
558        Multipart mp = new MimeMultipart();
559        mp.addBodyPart(mbp1);
560        mp.addBodyPart(attachment);
561    
562        Message msg = createMessage(session, "IAIK S/MIME: Certs-only multipart message");
563        msg.setContent(mp, mp.getContentType());
564        return msg;
565      }
566      
567        
568      /**
569       * Creates a PKCS#10 certificate request message.
570       *
571       * @param session the mail session
572       * 
573       * @return the PKCS#10 certificate request message
574       *
575       * @throws MessagingException if an error occurs when creating the message
576       */  
577      public Message createPKCS10Message(Session session)
578        throws MessagingException {
579    
580        Message msg = createMessage(session, "IAIK-S/MIME: Certificate Request");
581    
582        PKCS10Content pc = new PKCS10Content();
583        CertificateRequest request = null;
584        try {
585           request = createCertificateRequest();
586        } catch (PKCSException ex) {
587           throw new MessagingException(ex.getMessage());
588        }
589        pc.setCertRequest(request);
590        msg.setContent(pc, pc.getContentType());
591        // let the PKCS10Content update some message headers
592        pc.setHeaders(msg);
593    
594        return msg;
595      }
596    
597      /**
598       * Creates a PKCS#10 certificate request.
599       *
600       * @return the certificate request
601       *
602       * @throws PKCSException if the request cannot be created
603       */
604      private CertificateRequest createCertificateRequest() throws PKCSException {
605        try {
606          Name subject = new Name();
607              subject.addRDN(ObjectID.commonName, senderName_);
608              subject.addRDN(ObjectID.emailAddress, from_);
609              CertificateRequest certRequest;
610    
611          certRequest = new CertificateRequest(signerCertificate_.getPublicKey(), subject);
612              certRequest.sign((AlgorithmID)AlgorithmID.sha256WithRSAEncryption.clone(), signerPrivateKey_);
613              certRequest.verify();
614              return certRequest;
615            } catch (Exception ex) {
616              throw new PKCSException("Cannot create cert request: " + ex.getMessage());
617            }
618    
619      }
620      
621      /**
622       * Creates a PKCS#10 message where the certificate request is transferred as attachment.
623       *
624       * @param session the mail session
625       * 
626       * @return the PKCS#10 certificate request message
627       *
628       * @throws MessagingException if an error occurs when creating the message
629       */
630      public Message createPKCS10MultiPartMessage(Session session) throws MessagingException {
631    
632          MimeBodyPart mbp1 = new MimeBodyPart();
633              mbp1.setText("This is a test where the request message is included in the second part!\n\n");
634              // try to test an attachment
635              // this demo attaches our homepage
636          MimeBodyPart attachment = new MimeBodyPart();
637          //use new content types
638          SMimeParameters.useNewContentTypes(true);
639          PKCS10Content pc = new PKCS10Content();
640          CertificateRequest request = null;
641          try {
642             request = createCertificateRequest();
643          } catch (PKCSException ex) {
644             throw new MessagingException(ex.getMessage());
645          }
646          pc.setCertRequest(request);
647          DataHandler pkcs10Handler = new DataHandler(pc, pc.getContentType());
648          attachment.setDataHandler(pkcs10Handler);
649          attachment.setDisposition("attachment");
650          attachment.setFileName("smime.p10");
651          Multipart mp = new MimeMultipart();
652          mp.addBodyPart(mbp1);
653          mp.addBodyPart(attachment);
654    
655          Message msg = createMessage(session, "IAIK-S/MIME: Certificate Request multipart message");
656          msg.setContent(mp, mp.getContentType());
657          return msg;
658      }
659    
660    
661      /** 
662       * Main method.
663       */
664      public static void main(String[] argv) throws IOException {
665    
666        DemoSMimeUtil.initDemos();
667            (new SMimeSendDemo()).start(argv);
668        System.out.println("\nReady!");
669        DemoUtil.waitKey();
670      }
671    }