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