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/BinarySignedDemo.java 22 12.02.25 17:58 Dbratko $ 059 // $Revision: 22 $ 060 // 061 062 package demo.smime.basic; 063 064 import iaik.smime.BinaryCanonicalizer; 065 import iaik.smime.DefaultCanonicalizer; 066 import iaik.smime.SMimeBodyPart; 067 import iaik.smime.SMimeMultipart; 068 import iaik.smime.SMimeParameters; 069 import iaik.smime.SignedContent; 070 import iaik.x509.X509Certificate; 071 072 import java.io.ByteArrayInputStream; 073 import java.io.ByteArrayOutputStream; 074 import java.io.IOException; 075 import java.security.NoSuchAlgorithmException; 076 import java.security.PrivateKey; 077 import java.security.interfaces.RSAPrivateKey; 078 import java.util.Date; 079 080 import javax.activation.DataHandler; 081 import javax.activation.FileDataSource; 082 import javax.mail.Message; 083 import javax.mail.MessagingException; 084 import javax.mail.Multipart; 085 import javax.mail.Session; 086 import javax.mail.internet.InternetAddress; 087 import javax.mail.internet.MimeBodyPart; 088 import javax.mail.internet.MimeMessage; 089 090 import demo.DemoSMimeUtil; 091 import demo.DemoUtil; 092 import demo.keystore.CMSKeyStore; 093 import demo.smime.DumpMessage; 094 095 /** 096 * This class shows how to create, sign and then parse/verify a 097 * mulitpart/signed message where the content is not canonicalized. 098 * <p> 099 * The only difference to the common usage of this S/MIME library 100 * is to use a {@link iaik.smime.BinaryCanonicalizer binary 101 * canonicalizer} which does not canonicalize the content. 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 * @see iaik.smime.SignedContent 120 * @see iaik.smime.BinaryCanonicalizer 121 */ 122 public class BinarySignedDemo { 123 124 // whether to print dump all generates test messages to System.out 125 final static boolean PRINT_MESSAGES = false; 126 127 String firstName_ = "John"; // name of sender 128 String lastName_ = "SMime"; 129 String from_ = "smimetest@iaik.tugraz.at"; // email sender 130 String to_ = "smimetest@iaik.tugraz.at"; // email recipient 131 String host_ = "mailhost"; // name of the mailhost 132 133 X509Certificate[] signerCertificates_; // list of certificates to include in the S/MIME message 134 X509Certificate recipientCertificate_; // certificate of the recipient 135 X509Certificate signerCertificate_; // certificate of the signer/sender 136 X509Certificate encryptionCertOfSigner_; // signer uses different certificate for encryption 137 PrivateKey signerPrivateKey_; // private key of the signer/sender 138 139 /** 140 * Default constructor. Reads certificates and keys from the demo keystore. 141 */ 142 public BinarySignedDemo() { 143 144 System.out.println(); 145 System.out.println("********************************************************************************************"); 146 System.out.println("* BinarySignedDemo *"); 147 System.out.println("* (shows how to sign and verify multipart/signed S/MIME messages without canonicalization) *"); 148 System.out.println("********************************************************************************************"); 149 System.out.println(); 150 151 // get the certificates from the KeyStore 152 signerCertificates_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1); 153 signerPrivateKey_ = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1); 154 signerCertificate_ = signerCertificates_[0]; 155 156 // recipient = signer for this test 157 recipientCertificate_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2)[0]; 158 encryptionCertOfSigner_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1)[0]; 159 } 160 161 /** 162 * Starts the demo. 163 * 164 * @throws IOException if an I/O related error occurs 165 */ 166 public void start() throws IOException { 167 168 // get the default Session 169 Session session = DemoSMimeUtil.getSession(); 170 171 172 try { 173 174 // we use a binary canonicalizer 175 SMimeParameters.setCanonicalizer(new BinaryCanonicalizer()); 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 195 // create explicitly signed message 196 msg = createSignedMessage(session, multipart); 197 System.out.println("creating explicitly signed message..."); 198 baos.reset(); 199 msg.saveChanges(); 200 msg.writeTo(baos); 201 bais = new ByteArrayInputStream(baos.toByteArray()); 202 msg = new MimeMessage(session, bais); 203 if (PRINT_MESSAGES) { 204 printMessage(msg); 205 } 206 DumpMessage.dumpMsg(msg); 207 208 } catch (Exception ex) { 209 ex.printStackTrace(); 210 throw new RuntimeException(ex.toString()); 211 } finally { 212 // reset to default canonicalizer 213 SMimeParameters.setCanonicalizer(new DefaultCanonicalizer()); 214 } 215 216 } 217 218 /** 219 * Creates a signed message. 220 * 221 * @param session the mail session 222 * @param dataHandler the content of the message to be signed 223 * 224 * @return the signed message 225 * 226 * @throws MessagingException if an error occurs when creating the message 227 */ 228 public Message createSignedMessage(Session session, DataHandler dataHandler) 229 throws MessagingException { 230 231 String subject = "IAIK-S/MIME: Explicitly Signed"; 232 233 MimeMessage msg = new MimeMessage(session); 234 msg.setFrom(new InternetAddress(from_)); 235 msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to_, false)); 236 msg.setSentDate(new Date()); 237 msg.setSubject(subject); 238 239 SignedContent sc = new SignedContent(false); 240 241 // set content 242 sc.setDataHandler(dataHandler); 243 sc.setCertificates(signerCertificates_); 244 245 try { 246 sc.addSigner((RSAPrivateKey)signerPrivateKey_, signerCertificate_); 247 } catch (NoSuchAlgorithmException ex) { 248 throw new MessagingException("Algorithm not supported: " + ex.getMessage(), ex); 249 } 250 251 msg.setContent(sc, sc.getContentType()); 252 // let the SignedContent update some message headers 253 sc.setHeaders(msg); 254 return msg; 255 } 256 257 258 /** 259 * Prints a dump of the given message to System.out. 260 * 261 * @param msg the message to be dumped to System.out 262 */ 263 private static void printMessage(Message msg) throws IOException { 264 System.out.println("------------------------------------------------------------------"); 265 System.out.println("Message dump: \n"); 266 try { 267 msg.writeTo(System.out); 268 } catch (MessagingException ex) { 269 throw new IOException(ex.getMessage()); 270 } 271 System.out.println("\n------------------------------------------------------------------"); 272 } 273 274 275 /** 276 * The main method. 277 */ 278 public static void main(String[] argv) throws IOException { 279 280 DemoSMimeUtil.initDemos(); 281 (new BinarySignedDemo()).start(); 282 System.out.println("\nReady!"); 283 DemoUtil.waitKey(); 284 } 285 }