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/ess/SecurityLabelDemo.java 17 12.02.25 17:59 Dbratko $ 059 // $Revision: 17 $ 060 // 061 062 package demo.smime.ess; 063 064 import iaik.asn1.structures.AlgorithmID; 065 import iaik.asn1.structures.Attribute; 066 import iaik.cms.Utils; 067 import iaik.smime.SMimeSignerInfo; 068 import iaik.smime.SignedContent; 069 import iaik.smime.ess.ESSSecurityLabel; 070 import iaik.smime.ess.SecurityLabelException; 071 import iaik.x509.X509Certificate; 072 073 import java.io.ByteArrayInputStream; 074 import java.io.ByteArrayOutputStream; 075 import java.io.IOException; 076 import java.io.InputStream; 077 import java.security.PrivateKey; 078 import java.security.SignatureException; 079 import java.util.Date; 080 081 import javax.mail.Message; 082 import javax.mail.MessagingException; 083 import javax.mail.Session; 084 import javax.mail.internet.InternetAddress; 085 import javax.mail.internet.MimeMessage; 086 087 import demo.DemoSMimeUtil; 088 import demo.DemoUtil; 089 import demo.keystore.CMSKeyStore; 090 091 /** 092 * Demonstrates the usage of the S/MIME-ESS SecurityLabel attribute. 093 * The {@link iaik.smime.ess.ESSSecurityLabel SecurityLabel} attribute may be 094 * included as signed attribute in a {@link iaik.cms.SignerInfo SignerInfo} for 095 * providing some kind of "access control" mechanism for the contents of a message. 096 * <p> 097 * This demo uses a simple {@link demo.smime.ess.MySecurityLabelHandler 098 * SecurityLabelHandler} that only implements a simple security policy based on 099 * the default security classifications "unmarked", "unclassified", "restricted", 100 * "confidential", "secret", "top-secret". Since the SignedData message created 101 * by this demo only contains an ESS {@link iaik.smime.ess.ESSSecurityLabel 102 * SecurityLabel} attribute with classification "confidential", only this 103 * classification is processed by the {@link demo.smime.ess.MySecurityLabelHandler 104 * demo handler}. "unmarked" and "unclassified" are handled as "not critical" 105 * content (i.e. the content can be accessed by any one), "secret", "top-secret" 106 * lock the content (i.e. it is not displayed), and "restricted" and 107 * "confidential" popup a confirmation dialog reminding the recipient about 108 * the confidentiality of the message content. 109 * <p> 110 * To run this demo the following packages are required: 111 * <ul> 112 * <li> 113 * <code>iaik_cms.jar</code> 114 * </li> 115 * <li> 116 * <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>). 117 * </li> 118 * <li> 119 * <code>mail.jar</code> (<a href="http://www.oracle.com/technetwork/java/javamail/index.html" target="_blank">JavaMail API</a>). 120 * </li> 121 * <li> 122 * <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). 123 * </li> 124 * </ul> 125 * 126 * @see demo.smime.ess.MySecurityLabelHandler 127 * @see iaik.smime.ess.ESSSecurityLabel 128 */ 129 public class SecurityLabelDemo { 130 131 // whether to print dump all generates test messages to System.out 132 final static boolean PRINT_MESSAGES = false; 133 134 String firstName = "John"; 135 String lastName = "SMime"; 136 String to = "smimetest@iaik.at"; // email recipient 137 String from = "smimetest@iaik.at"; // email sender 138 String host = "mailhost"; // name of the mailhost 139 140 X509Certificate[] signerCertificates; // list of certificates to include in the S/MIME message 141 X509Certificate signerCertificate; // certificate of the signer/sender 142 PrivateKey signerPrivateKey; // private key of the signer/sender 143 X509Certificate encryptionCertOfSigner; // signer uses different certificate for encryption 144 145 146 /** 147 * Default constructor. Reads certificates and keys from the demo keystore. 148 */ 149 public SecurityLabelDemo() { 150 151 System.out.println(); 152 System.out.println("******************************************************************************************"); 153 System.out.println("* SecurityLabelDemo demo *"); 154 System.out.println("* (shows how to handle the ESS SecurityLabel attribute) *"); 155 System.out.println("******************************************************************************************"); 156 System.out.println(); 157 158 // get the certificates from the KeyStore 159 signerCertificates = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1); 160 signerPrivateKey = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1); 161 signerCertificate = signerCertificates[0]; 162 encryptionCertOfSigner = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1)[0]; 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 Message msg; // the message to send 177 ByteArrayOutputStream baos = new ByteArrayOutputStream(); // we write to a stream 178 ByteArrayInputStream bais; // we read from a stream 179 180 msg = createSignedMessage(session); 181 System.out.println("creating implicitly signed message..."); 182 baos.reset(); 183 // send, write 184 msg.saveChanges(); 185 msg.writeTo(baos); 186 187 // receive, parse 188 bais = new ByteArrayInputStream(baos.toByteArray()); 189 msg = new MimeMessage(session, bais); 190 if (PRINT_MESSAGES) { 191 printMessage(msg); 192 } 193 parseMessage(msg); 194 195 } catch (Exception ex) { 196 ex.printStackTrace(); 197 throw new RuntimeException(ex.toString()); 198 } 199 } 200 201 /** 202 * Creates a MIME message container with the given subject for the given session. 203 * 204 * @param session the mail sesion 205 * @param subject the subject of the message 206 * 207 * @return the MIME message with FROM, TO, DATE and SUBJECT headers (without content) 208 * 209 * @throws MessagingException if the message cannot be created 210 */ 211 public Message createMessage(Session session, String subject) throws MessagingException { 212 MimeMessage msg = new MimeMessage(session); 213 msg.setFrom(new InternetAddress(from)); 214 msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to, false)); 215 msg.setSentDate(new Date()); 216 msg.setSubject(subject); 217 return msg; 218 } 219 220 /** 221 * Creates a signed message containing an ESS SecurityLabel attribute. 222 * 223 * @param session the mail session 224 * @return the signed message 225 * 226 * @throws Exception if an error occurs when creating the message 227 */ 228 public Message createSignedMessage(Session session) throws Exception { 229 230 String subject = "IAIK-S/MIME: SecurityLabelDemo (Explicitly Signed)"; 231 StringBuffer buf = new StringBuffer(); 232 buf.append("This is an explicitly signed message\n"); 233 buf.append("containing an ESSSecurityLabel attribute.\n"); 234 235 Message msg = createMessage(session, subject); 236 237 SignedContent sc = new SignedContent(true); 238 // set the content 239 sc.setText(buf.toString()); 240 241 // set the signer certificates 242 sc.setCertificates(signerCertificates); 243 // set SignerInfo 244 SMimeSignerInfo signerInfo = new SMimeSignerInfo(signerCertificate, 245 (AlgorithmID)AlgorithmID.sha256.clone(), 246 (AlgorithmID)AlgorithmID.rsaEncryption.clone(), 247 signerPrivateKey, 248 encryptionCertOfSigner, 249 true); 250 251 // add SecurityLabel attribute 252 ESSSecurityLabel securityLabel = new ESSSecurityLabel(MySecurityLabelHandler.MY_SECURITY_POLICY_ID); 253 securityLabel.setSecurityClassification(ESSSecurityLabel.CONFIDENTIAL); 254 securityLabel.setPrivacyMarkString("HIGH CONFIDENTIAL DATA MATERIAL! RESTRICTED USER ACCESS"); 255 signerInfo.addSignedAttribute(new Attribute(securityLabel)); 256 sc.addSigner(signerInfo); 257 msg.setContent(sc, sc.getContentType()); 258 // let the SignedContent update some message headers 259 sc.setHeaders(msg); 260 return msg; 261 } 262 263 /** 264 * Parses the signed message, verifies the signature and processes the SecurityLabel 265 * attribute. 266 * 267 * @param msg the message to be parsed 268 * 269 * @throws IOException if an I/O related problem occurs 270 * @throws MessagingException if there is a problem with the message format 271 * @throws SignatureException if the signature verification failes 272 */ 273 public void parseMessage(Message msg) throws IOException, MessagingException, SignatureException { 274 // we know that we have a signed message 275 SignedContent sc = (SignedContent)msg.getContent(); 276 // set a SecurityLabelHandler 277 sc.setSecurityLabelHandler(new MySecurityLabelHandler()); 278 // verify signature 279 X509Certificate signer = null; 280 try { 281 signer = sc.verify(); 282 System.out.println("This message is signed from: "+signer.getSubjectDN()); 283 } catch (SignatureException ex) { 284 throw new SignatureException("Signature verification error: " + ex.toString()); 285 } 286 // try to access the content data 287 try { 288 Object content = sc.getContent(); 289 System.out.println("Included content:"); 290 // depending on JavaMail API version we may have a String or a InputStream 291 if (content instanceof String) { 292 System.out.println(content); 293 } else if (content instanceof InputStream) { 294 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 295 Utils.copyStream((InputStream)content, baos, null); 296 System.out.println(new String(baos.toByteArray())); 297 } 298 } catch (SecurityLabelException ex) { 299 System.out.println(ex.getMessage()); 300 } 301 } 302 303 304 /** 305 * Prints a dump of the given message to System.out. 306 * 307 * @param msg the message to be dumped to System.out 308 */ 309 private static void printMessage(Message msg) throws IOException { 310 System.out.println("------------------------------------------------------------------"); 311 System.out.println("Message dump: \n"); 312 try { 313 msg.writeTo(System.out); 314 } catch (MessagingException ex) { 315 throw new IOException(ex.getMessage()); 316 } 317 System.out.println("\n------------------------------------------------------------------"); 318 } 319 320 321 /** 322 * The main method. 323 */ 324 public static void main(String[] argv) throws IOException { 325 326 DemoSMimeUtil.initDemos(); 327 try { 328 (new SecurityLabelDemo()).start(); 329 } catch (Exception ex) { 330 ex.printStackTrace(); 331 } 332 333 System.out.println("\nReady!"); 334 DemoUtil.waitKey(); 335 336 } 337 }