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 }