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/SMimeV3SHA2withDSADemo.java 10 12.02.25 17:58 Dbratko $ 059 // $Revision: 10 $ 060 // 061 062 package demo.smime.basic; 063 064 import iaik.asn1.structures.AlgorithmID; 065 import iaik.cms.CMSAlgorithmID; 066 import iaik.smime.SMimeBodyPart; 067 import iaik.smime.SMimeMultipart; 068 import iaik.smime.SignedContent; 069 import iaik.x509.X509Certificate; 070 071 import java.io.ByteArrayInputStream; 072 import java.io.ByteArrayOutputStream; 073 import java.io.IOException; 074 import java.security.NoSuchAlgorithmException; 075 import java.security.PrivateKey; 076 import java.util.Date; 077 078 import javax.activation.DataHandler; 079 import javax.activation.FileDataSource; 080 import javax.mail.Message; 081 import javax.mail.MessagingException; 082 import javax.mail.Multipart; 083 import javax.mail.Session; 084 import javax.mail.internet.InternetAddress; 085 import javax.mail.internet.MimeBodyPart; 086 import javax.mail.internet.MimeMessage; 087 088 import demo.DemoSMimeUtil; 089 import demo.DemoUtil; 090 import demo.keystore.CMSKeyStore; 091 import demo.smime.DumpMessage; 092 093 /** 094 * This class demonstrates the usage of the IAIK S/MIME implementation with the 095 * SHA2withDSA signature algorithm (FIPS 186-3). It shows how to create signed 096 * S/MIMEv3 messages and how to parse them and verify the signature. 097 * <p> 098 * To run this demo the following packages are required: 099 * <ul> 100 * <li> 101 * <code>iaik_cms.jar</code> (IAIK-CMS/SMIME) 102 * </li> 103 * <li> 104 * <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>). 105 * </li> 106 * <li> 107 * <code>mail.jar</code> (<a href="http://www.oracle.com/technetwork/java/javamail/index.html" target="_blank">JavaMail API</a>). 108 * </li> 109 * <li> 110 * <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). 111 * </li> 112 * </ul> 113 */ 114 public class SMimeV3SHA2withDSADemo { 115 116 //whether to print dump all generates test messages to System.out 117 final static boolean PRINT_MESSAGES = false; 118 119 120 String firstName = "John"; 121 String lastName = "SMime"; 122 String to = "smimetest@iaik.tugraz.at"; // email recipient 123 String from = "smimetest@iaik.tugraz.at"; // email sender 124 String host = "mailhost"; // name of the mailhost 125 126 X509Certificate[] signerCertificates; // list of certificates to include in the S/MIME message 127 X509Certificate signerCertificate; // certificate of the signer/sender 128 PrivateKey signerPrivateKey; // private key of the signer/sender 129 130 /** 131 * Default constructor. Reads certificates and keys from the demo keystore. 132 */ 133 public SMimeV3SHA2withDSADemo() { 134 // get the certificates from the KeyStore 135 signerCertificates = CMSKeyStore.getCertificateChain(CMSKeyStore.DSA, CMSKeyStore.SZ_3072_SIGN); 136 signerPrivateKey = CMSKeyStore.getPrivateKey(CMSKeyStore.DSA, CMSKeyStore.SZ_3072_SIGN); 137 signerCertificate = signerCertificates[0]; 138 } 139 140 /** 141 * Starts the demo. 142 * 143 * @throws IOException if an I/O related error occurs 144 */ 145 public void start() throws IOException { 146 147 // get the default Session 148 Session session = DemoSMimeUtil.getSession(); 149 150 try { 151 // Create a demo Multipart 152 MimeBodyPart mbp1 = new SMimeBodyPart(); 153 mbp1.setText("This is a Test of the IAIK S/MIME implementation!\n\n"); 154 // attachment 155 MimeBodyPart attachment = new SMimeBodyPart(); 156 attachment.setDataHandler(new DataHandler(new FileDataSource("test.html"))); 157 attachment.setFileName("test.html"); 158 159 Multipart mp = new SMimeMultipart(); 160 mp.addBodyPart(mbp1); 161 mp.addBodyPart(attachment); 162 DataHandler multipart = new DataHandler(mp, mp.getContentType()); 163 164 Message msg; // the message to send 165 ByteArrayOutputStream baos = new ByteArrayOutputStream(); // we write to a stream 166 ByteArrayInputStream bais; // we read from a stream 167 168 AlgorithmID digestAlgorithm = CMSAlgorithmID.sha256; 169 AlgorithmID signatureAlgorithm = CMSAlgorithmID.dsaWithSHA256; 170 171 // 1. This is an explicitly signed message 172 msg = createSignedMessage(session, 173 multipart, 174 false, 175 (AlgorithmID)digestAlgorithm.clone(), 176 (AlgorithmID)signatureAlgorithm.clone()); 177 System.out.println("creating explicitly signed message..."); 178 baos.reset(); 179 msg.saveChanges(); 180 msg.writeTo(baos); 181 bais = new ByteArrayInputStream(baos.toByteArray()); 182 msg = new MimeMessage(session, bais); 183 if (PRINT_MESSAGES) { 184 printMessage(msg); 185 } 186 DumpMessage.dumpMsg(msg); 187 188 System.out.println("\n\n*****************************************\n\n"); 189 190 191 // 2. This is an implicitly signed message 192 msg = createSignedMessage(session, 193 multipart, 194 true, 195 (AlgorithmID)digestAlgorithm.clone(), 196 (AlgorithmID)signatureAlgorithm.clone()); 197 System.out.println("creating implicitly 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 System.out.println("\n\n*****************************************\n\n"); 209 210 } catch (Exception ex) { 211 ex.printStackTrace(); 212 throw new RuntimeException(ex.toString()); 213 } 214 } 215 216 /** 217 * Creates a signed message. 218 * 219 * @param session the mail session 220 * @param dataHandler the content of the message to be signed 221 * @param implicit whether to use implicit (application/pkcs7-mime) or explicit 222 * (multipart/signed) signing 223 * @param digestAlgorithm the digest algorithm to be used 224 * @param signatureAlgorithm the signature algorithm to be used 225 * 226 * @return the signed message 227 * 228 * @throws MessagingException if an error occurs when creating the message 229 */ 230 public Message createSignedMessage(Session session, 231 DataHandler dataHandler, 232 boolean implicit, 233 AlgorithmID digestAlgorithm, 234 AlgorithmID signatureAlgorithm) 235 throws MessagingException { 236 237 String subject = null; 238 StringBuffer buf = new StringBuffer(); 239 240 if (implicit) { 241 subject = "IAIK-S/MIME: Implicitly Signed"; 242 buf.append("This message is implicitly signed!\n"); 243 buf.append("You need an S/MIME aware mail client to view this message.\n"); 244 buf.append("\n\n"); 245 } else { 246 subject = "IAIK-S/MIME: Explicitly Signed"; 247 buf.append("This message is explicitly signed!\n"); 248 buf.append("Every mail client can view this message.\n"); 249 buf.append("Non S/MIME mail clients will show the signature as attachment.\n"); 250 buf.append("\n\n"); 251 } 252 253 Message msg = createMessage(session, subject); 254 255 SignedContent sc = new SignedContent(implicit); 256 if (dataHandler != null) { 257 sc.setDataHandler(dataHandler); 258 } else { 259 sc.setText(buf.toString()); 260 } 261 sc.setCertificates(signerCertificates); 262 263 try { 264 sc.addSigner(signerPrivateKey, 265 signerCertificate, 266 (AlgorithmID)digestAlgorithm.clone(), 267 (AlgorithmID)signatureAlgorithm.clone()); 268 } catch (NoSuchAlgorithmException ex) { 269 throw new MessagingException("Algorithm not supported: " + ex.getMessage(), ex); 270 } 271 272 msg.setContent(sc, sc.getContentType()); 273 // let the SignedContent update some message headers 274 sc.setHeaders(msg); 275 return msg; 276 } 277 278 /** 279 * Creates a MIME message container with the given subject for the given session. 280 * 281 * @param session the mail sesion 282 * @param subject the subject of the message 283 * 284 * @return the MIME message with FROM, TO, DATE and SUBJECT headers (without content) 285 * 286 * @throws MessagingException if the message cannot be created 287 */ 288 public Message createMessage(Session session, String subject) throws MessagingException { 289 MimeMessage msg = new MimeMessage(session); 290 msg.setFrom(new InternetAddress(from)); 291 msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to, false)); 292 msg.setSentDate(new Date()); 293 msg.setSubject(subject); 294 return msg; 295 } 296 297 /** 298 * Prints a dump of the given message to System.out. 299 * 300 * @param msg the message to be dumped to System.out 301 * 302 * @throws IOException if an I/O error occurs 303 */ 304 static void printMessage(Message msg) throws IOException { 305 System.out.println("------------------------------------------------------------------"); 306 System.out.println("Message dump: \n"); 307 try { 308 msg.writeTo(System.out); 309 } catch (MessagingException ex) { 310 throw new IOException(ex.getMessage()); 311 } 312 System.out.println("\n------------------------------------------------------------------"); 313 } 314 315 316 /** 317 * The main method. 318 */ 319 public static void main(String[] argv) throws IOException { 320 double iaikProviderVersion = DemoUtil.getIaikProviderVersion(); 321 if (iaikProviderVersion <= 3.18) { 322 System.err.println("This demo requires a IAIK provider version > 3.18! Your IAIK provider version is " + iaikProviderVersion + "."); 323 } else { 324 DemoSMimeUtil.initDemos(); 325 (new SMimeV3SHA2withDSADemo()).start(); 326 System.out.println("\nReady!"); 327 } 328 DemoUtil.waitKey(); 329 } 330 }