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 < 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 }