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/MLADemo.java 49 12.02.25 17:59 Dbratko $ 059 // $Revision: 49 $ 060 // 061 062 package demo.smime.ess; 063 064 import iaik.asn1.CodingException; 065 import iaik.asn1.structures.AlgorithmID; 066 import iaik.asn1.structures.Attribute; 067 import iaik.asn1.structures.Attributes; 068 import iaik.cms.CMSSignatureException; 069 import iaik.cms.IssuerAndSerialNumber; 070 import iaik.cms.KeyTransRecipientInfo; 071 import iaik.cms.RecipientInfo; 072 import iaik.cms.SignerInfo; 073 import iaik.cms.Utils; 074 import iaik.smime.EncryptedContent; 075 import iaik.smime.SMimeBodyPart; 076 import iaik.smime.SMimeException; 077 import iaik.smime.SMimeMultipart; 078 import iaik.smime.SMimeUtil; 079 import iaik.smime.SignedContent; 080 import iaik.smime.ess.ESSException; 081 import iaik.smime.ess.EntityIdentifier; 082 import iaik.smime.ess.MLData; 083 import iaik.smime.ess.MLExpansionHistory; 084 import iaik.smime.ess.MLReceiptPolicy; 085 import iaik.smime.ess.utils.ESSLayerException; 086 import iaik.smime.ess.utils.ESSLayers; 087 import iaik.smime.ess.utils.KeyStoreDatabase; 088 import iaik.smime.ess.utils.MLA; 089 import iaik.utils.CryptoUtils; 090 import iaik.x509.X509Certificate; 091 092 import java.io.ByteArrayInputStream; 093 import java.io.ByteArrayOutputStream; 094 import java.io.IOException; 095 import java.security.NoSuchAlgorithmException; 096 import java.security.PrivateKey; 097 import java.util.Date; 098 099 import javax.activation.DataHandler; 100 import javax.activation.DataSource; 101 import javax.activation.FileDataSource; 102 import javax.mail.BodyPart; 103 import javax.mail.Message; 104 import javax.mail.MessagingException; 105 import javax.mail.Multipart; 106 import javax.mail.Session; 107 import javax.mail.internet.InternetAddress; 108 import javax.mail.internet.MimeBodyPart; 109 import javax.mail.internet.MimeMessage; 110 111 import demo.DemoSMimeUtil; 112 import demo.DemoUtil; 113 import demo.keystore.CMSKeyStore; 114 import demo.keystore.CMSKeyStoreConstants; 115 116 /** 117 * A ESS mailing list agent (MLA) demo. 118 * Demonstrates the usage of the {@link iaik.smime.ess.utils.MLA MLA} utility by 119 * means of the examples given in <a href="https://www.rfc-editor.org/rfc/rfc2634.html" target = "_blank">RFC2634</a>, 120 * section 4.2.1: 121 * <pre> 122 * 4.2.1 Examples of Rule Processing 123 * 124 * The following examples help explain the rules above: 125 * 126 * 1) A message (S1(Original Content)) (where S = SignedData) is sent to 127 * the MLA in which the signedData layer does not include an 128 * MLExpansionHistory attribute. The MLA verifies and fully processes 129 * the signedAttributes in S1. The MLA decides that there is not an 130 * original, received "outer" signedData layer since it finds the 131 * original content, but never finds an envelopedData and never finds 132 * an mlExpansionHistory attribute. The MLA calculates a new 133 * signedData layer, S2, resulting in the following message sent to 134 * the ML recipients: (S2(S1(Original Content))). The MLA includes an 135 * mlExpansionHistory attribute in S2. 136 * 137 * 2) A message (S3(S2(S1(Original Content)))) is sent to the MLA in 138 * which none of the signedData layers includes an MLExpansionHistory 139 * attribute. The MLA verifies and fully processes the 140 * signedAttributes in S3, S2 and S1. The MLA decides that there is 141 * not an original, received "outer" signedData layer since it finds 142 * the original content, but never finds an envelopedData and never 143 * finds an mlExpansionHistory attribute. The MLA calculates a new 144 * signedData layer, S4, resulting in the following 145 * message sent to the ML recipients: 146 * (S4(S3(S2(S1(Original Content))))). The MLA includes an 147 * mlExpansionHistory attribute in S4. 148 * 149 * 3) A message (E1(S1(Original Content))) (where E = envelopedData) is 150 * sent to the MLA in which S1 does not include an MLExpansionHistory 151 * attribute. The MLA decides that there is not an original, 152 * received "outer" signedData layer since it finds the E1 as the 153 * outer layer. The MLA expands the recipientInformation in E1. The 154 * MLA calculates a new signedData layer, S2, resulting in the 155 * following message sent to the ML recipients: 156 * (S2(E1(S1(Original Content)))). The MLA includes an 157 * mlExpansionHistory attribute in S2. 158 * 159 * 4) A message (S2(E1(S1(Original Content)))) is sent to the MLA in 160 * which S2 includes an MLExpansionHistory attribute. The MLA verifies 161 * the signature and fully processes the signedAttributes in S2. The 162 * MLA finds the mlExpansionHistory attribute in S2, so it decides 163 * that S2 is the "outer" signedData. The MLA remembers the 164 * signedAttributes included in S2 for later inclusion in the new 165 * outer signedData that it applies to the message. The MLA strips off 166 * S2. The MLA then expands the recipientInformation in E1 (this 167 * invalidates the signature in S2 which is why it was stripped). The 168 * nMLA calculates a new signedData layer, S3, resulting in the 169 * following message sent to the ML recipients: (S3(E1(S1(Original 170 * Content)))). The MLA includes in S3 the attributes from S2 (unless 171 * it specifically replaces an attribute value) including an updated 172 * mlExpansionHistory attribute. 173 * 174 * 5) A message (S3(S2(E1(S1(Original Content))))) is sent to the MLA in 175 * which none of the signedData layers include an MLExpansionHistory 176 * attribute. The MLA verifies the signature and fully processes the 177 * signedAttributes in S3 and S2. When the MLA encounters E1, then it 178 * decides that S2 is the "outer" signedData since S2 encapsulates E1. 179 * The MLA remembers the signedAttributes included in S2 for later 180 * inclusion in the new outer signedData that it applies to the 181 * message. The MLA strips off S3 and S2. The MLA then expands the 182 * recipientInformation in E1 (this invalidates the signatures in S3 183 * and S2 which is why they were stripped). The MLA calculates a new 184 * signedData layer, S4, resulting in the following message sent to 185 * the ML recipients: (S4(E1(S1(Original Content)))). The MLA 186 * includes in S4 the attributes from S2 (unless it specifically 187 * replaces an attribute value) and includes a new 188 * mlExpansionHistory attribute. 189 * 190 * 6) A message (S3(S2(E1(S1(Original Content))))) is sent to the MLA in 191 * which S3 includes an MLExpansionHistory attribute. In this case, 192 * the MLA verifies the signature and fully processes the 193 * signedAttributes in S3. The MLA finds the mlExpansionHistory in S3, 194 * so it decides that S3 is the "outer" signedData. The MLA remembers 195 * the signedAttributes included in S3 for later inclusion in the new 196 * outer signedData that it applies to the message. The MLA keeps on 197 * parsing encapsulated layers because it must determine if there are 198 * any eSSSecurityLabel attributes contained within. The MLA verifies 199 * the signature and fully processes the signedAttributes in S2. When 200 * the MLA encounters E1, then it strips off S3 and S2. The MLA then 201 * expands the recipientInformation in E1 (this invalidates the 202 * signatures in S3 and S2 which is why they were stripped). The MLA 203 * calculates a new signedData layer, S4, resulting in the following 204 * message sent to the ML recipients: (S4(E1(S1(Original Content)))). 205 * The MLA includes in S4 the attributes from S3 (unless it 206 * specifically replaces an attribute value) including an updated 207 * mlExpansionHistory attribute. 208 * </pre> 209 * To run this demo the following packages are required: 210 * <ul> 211 * <li> 212 * <code>iaik_cms.jar</code> 213 * </li> 214 * <li> 215 * <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>). 216 * </li> 217 * <li> 218 * <code>mail.jar</code> (<a href="http://www.oracle.com/technetwork/java/javamail/index.html" target="_blank">JavaMail API</a>). 219 * </li> 220 * <li> 221 * <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). 222 * </li> 223 * </ul> 224 * 225 * @see iaik.smime.ess.MLExpansionHistory 226 * @see iaik.smime.ess.MLData 227 * @see iaik.smime.ess.MLReceiptPolicy 228 * @see iaik.smime.ess.utils.MLA 229 */ 230 public class MLADemo { 231 // whether to print dump all generates test messages to System.out 232 final static boolean DUMP_MESSAGES = false; 233 234 // the first party (that sends a message to the MLA) 235 String senderName_ = "IAIK Demo Sender"; 236 // the second party (MLA) 237 String mlaName_ = "IAIK Demo ML Agent"; 238 // the third final party (that receives a message from the MLA) 239 String recipientName_ = "IAIK Demo Recipient"; 240 // we use the same email address for all parties 241 String senderAddress_ = "\""+senderName_+"\" <smimetest@iaik.at>"; 242 String mlaAddress_ = "\""+mlaName_+"\" <smimetest@iaik.at>"; 243 String recipientAddress_ = "\""+recipientName_+"\" <smimetest@iaik.at>"; 244 String host_ = "mailhost"; // name of the mailhost 245 246 // required certificate; read from the demo keystore 247 X509Certificate[] signerCertificatesOfS1_; // signer certificates of entity S1 248 PrivateKey signerPrivateKeyOfS1_; // signer private key of entity S1 249 X509Certificate[] signerCertificatesOfS2_; // signer certificates of entity S2 250 PrivateKey signerPrivateKeyOfS2_; // signer private key of entity S2 251 X509Certificate[] signerCertificatesOfS3_; // signer certificates of entity S3 252 PrivateKey signerPrivateKeyOfS3_; // signer private key of entity S3 253 X509Certificate[] signerCertificatesOfMLA_; // signer certificates of MLA 254 PrivateKey signerPrivateKeyOfMLA_; // signer private key of MLA 255 X509Certificate[] encryptionCertificatesOfMLA_; // encryption certificates of MLA 256 PrivateKey encryptionPrivateKeyOfMLA_; // encryption private key of MLA 257 X509Certificate[] certificatesOfMLA_; // all (signer + encryption) certificates of the MLA 258 X509Certificate[] encryptionCertificatesOfE1_; // encryption certificates of entity E1 259 PrivateKey encryptionPrivateKeyOfE1_; // encryption private key of entity E1 260 X509Certificate[] recipientCertificates_; // certificates of the final recipient if the MLA encrypts again 261 PrivateKey recipientPrivateKey_; // private key of the final recipient if the MLA encrypts again 262 263 264 // keystore data base of the MLA 265 KeyStoreDatabase keyStoreDatabase_; 266 // MLA 267 MLA mla_; 268 // MLA id 269 EntityIdentifier mlaID_; 270 271 /** 272 * Empty default constructor. Reads all required keys and certificates 273 * from the demo keystore (created by running @link demo.keystore.SetupCMSKeySrore) 274 * stored at "cms.keystore" in your current working directoy. Inits the ML agent. 275 */ 276 public MLADemo() { 277 278 System.out.println(); 279 System.out.println("******************************************************************************************"); 280 System.out.println("* MLADemo *"); 281 System.out.println("* (shows the usage of the IAIK-CMS MLA utility for running an ESS mail list agent) *"); 282 System.out.println("******************************************************************************************"); 283 System.out.println(); 284 285 try { 286 keyStoreDatabase_ = new KeyStoreDatabase(); 287 // get the certificates from the KeyStore 288 signerCertificatesOfS1_ = CMSKeyStore.getCertificateChain(CMSKeyStore.DSA, CMSKeyStore.SZ_2048_SIGN_1); 289 signerPrivateKeyOfS1_ = CMSKeyStore.getPrivateKey(CMSKeyStore.DSA, CMSKeyStore.SZ_2048_SIGN_1); 290 signerCertificatesOfS2_ = CMSKeyStore.getCertificateChain(CMSKeyStore.DSA, CMSKeyStore.SZ_3072_SIGN); 291 signerPrivateKeyOfS2_ = CMSKeyStore.getPrivateKey(CMSKeyStore.DSA, CMSKeyStore.SZ_3072_SIGN); 292 signerCertificatesOfS3_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_2); 293 signerPrivateKeyOfS3_ = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_2); 294 signerCertificatesOfMLA_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_3); 295 signerPrivateKeyOfMLA_ = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_3); 296 encryptionCertificatesOfMLA_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1); 297 encryptionPrivateKeyOfMLA_ = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1); 298 encryptionCertificatesOfE1_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2); 299 encryptionPrivateKeyOfE1_ = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2); 300 recipientCertificates_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_3); 301 recipientPrivateKey_ = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_3); 302 303 // add the certificates and keys of the MLA to its key data base 304 keyStoreDatabase_.addKey(signerPrivateKeyOfMLA_, signerCertificatesOfMLA_, CMSKeyStoreConstants.RSA_2048_SIGN_1); 305 keyStoreDatabase_.addKey(encryptionPrivateKeyOfMLA_, encryptionCertificatesOfMLA_, CMSKeyStoreConstants.RSA_2048_CRYPT_1); 306 307 // init MLA 308 mlaID_ = new EntityIdentifier(new IssuerAndSerialNumber(signerCertificatesOfMLA_[0])); 309 mla_ = new MLA(mlaID_); 310 mla_.setDebugStream("MLA", System.out); 311 // to whom the MLA wants to send an encrypted message 312 mla_.setEncryptionInfo(null, 313 new RecipientInfo[] { new KeyTransRecipientInfo(recipientCertificates_[0], (AlgorithmID)AlgorithmID.rsaEncryption.clone()) }, 314 (AlgorithmID)AlgorithmID.aes256_CBC.clone(), 315 256); 316 mla_.setDebugStream("MLA", System.out); 317 mla_.setKeyDatabase(keyStoreDatabase_); 318 // do not continue to resolve a message if there is an invalid signature in a signed layer 319 mla_.setStopOnInvalidSignature(true); 320 System.out.println("MLA signing cert is: " + signerCertificatesOfMLA_[0].getSubjectDN()); 321 System.out.println("MLA entity identifier is:\n" + mlaID_ + "\n"); 322 } catch (Exception ex) { 323 ex.printStackTrace(); 324 throw new RuntimeException(ex.toString()); 325 } 326 327 } 328 329 /** 330 * Runs the demo samples. 331 */ 332 public void start() { 333 334 try { 335 336 // get the default Session 337 Session session = DemoSMimeUtil.getSession(); 338 339 // Create a demo Multipart 340 MimeBodyPart mbp1 = new SMimeBodyPart(); 341 mbp1.setText("This is a test of the IAIK-CMS S/MIME ESS MLA implementation.\n"); 342 // try to test an attachment 343 MimeBodyPart attachment = new SMimeBodyPart(); 344 attachment.setDataHandler(new DataHandler(new FileDataSource("test.html"))); 345 attachment.setFileName("test.html"); 346 Multipart mp = new SMimeMultipart(); 347 mp.addBodyPart(mbp1); 348 mp.addBodyPart(attachment); 349 350 // whether to create implcit (content included) or explicit signed messages 351 boolean implicit = true; 352 System.out.println("Implicit demos"); 353 354 // keep original datasource for comparison 355 MimeMessage tmpMsg = new MimeMessage(session); 356 tmpMsg.setContent(mp); 357 tmpMsg.saveChanges(); 358 byte[] dsBytes = getDataSource(tmpMsg.getDataHandler()); 359 360 System.out.println("Testing sample 4.2.1,1) from RFC 2634: S1(O) ==> S2(S1(O))"); 361 test_S1_O(session, mp, dsBytes, implicit); 362 363 System.out.println("Testing sample 4.2.1,2) from RFC 2634: S3(S2(S1(O))) ==> S4(S3(S2(S1(O))))"); 364 test_S3_S2_S1_O(session, mp, dsBytes, implicit); 365 366 System.out.println("Testing sample 4.2.1,3) from RFC 2634: E1(S1(O)) ==> S2(E1(S1(O)))"); 367 test_E1_S1_O(session, mp, dsBytes, implicit); 368 369 System.out.println("Testing sample 4.2.1,4) from RFC 2634: S2(E1(S1(O))) ==> S3(E1(S1(O)))"); 370 test_S2_E1_S1_O(session, mp, dsBytes, implicit); 371 372 System.out.println("Testing sample 4.2.1,5) from RFC 2634: S3(S2(E1(S1(O)))) ==> S4(E1(S1(O)))"); 373 test_S3_S2_E1_S1_O(session, mp, dsBytes, implicit, false); 374 375 System.out.println("Testing sample 4.2.1,6) from RFC 2634: S3(S2(E1(S1(O)))) ==> S4(E1(S1(O)))"); 376 test_S3_S2_E1_S1_O(session, mp, dsBytes, implicit, true); 377 378 implicit = false; 379 System.out.println("Explicit demos"); 380 381 System.out.println("Testing sample 4.2.1,1) from RFC 2634: S1(O) ==> S2(S1(O))"); 382 test_S1_O(session, mp, dsBytes, implicit); 383 384 System.out.println("Testing sample 4.2.1,2) from RFC 2634: S3(S2(S1(O))) ==> S4(S3(S2(S1(O))))"); 385 test_S3_S2_S1_O(session, mp, dsBytes, implicit); 386 387 System.out.println("Testing sample 4.2.1,3) from RFC 2634: E1(S1(O)) ==> S2(E1(S1(O)))"); 388 test_E1_S1_O(session, mp, dsBytes, implicit); 389 390 System.out.println("Testing sample 4.2.1,4) from RFC 2634: S2(E1(S1(O))) ==> S3(E1(S1(O)))"); 391 test_S2_E1_S1_O(session, mp, dsBytes, implicit); 392 393 System.out.println("Testing sample 4.2.1,5) from RFC 2634: S3(S2(E1(S1(O)))) ==> S4(E1(S1(O)))"); 394 test_S3_S2_E1_S1_O(session, mp, dsBytes, implicit, false); 395 396 System.out.println("Testing sample 4.2.1,6) from RFC 2634: S3(S2(E1(S1(O)))) ==> S4(E1(S1(O)))"); 397 test_S3_S2_E1_S1_O(session, mp, dsBytes, implicit, true); 398 399 System.out.println("Ready!"); 400 401 } catch (Exception ex) { 402 ex.printStackTrace(); 403 throw new RuntimeException(ex.toString()); 404 } 405 } 406 407 /** 408 * Tests the MLA behaviour for a simple signed message according to sample 4.2.1,1) of 409 * <a href="https://www.rfc-editor.org/rfc/rfc2634.html" target = "_blank">RFC2634</a>: 410 * <pre> 411 * A message (S1(Original Content)) (where S = SignedData) is sent to 412 * the MLA in which the signedData layer does not include an 413 * MLExpansionHistory attribute. The MLA verifies and fully processes 414 * the signedAttributes in S1. The MLA decides that there is not an 415 * original, received "outer" signedData layer since it finds the 416 * original content, but never finds an envelopedData and never finds 417 * an mlExpansionHistory attribute. The MLA calculates a new 418 * signedData layer, S2, resulting in the following message sent to 419 * the ML recipients: (S2(S1(Original Content))). The MLA includes an 420 * mlExpansionHistory attribute in S2. 421 * </pre> 422 * 423 * @param session the current mail session 424 * @param mp the multipart content 425 * @param dsBytes the original content dataSorce bytes for comparison 426 * @param implicit whether implicit (content included) or explicit signing shall be used 427 * 428 * @throws Exception if an error coours 429 */ 430 public void test_S1_O(Session session, Multipart mp, byte[] dsBytes, boolean implicit) throws Exception { 431 // RFC2634, 4.2.1, 1) S1(Original Content) ==> MLA(S1(Original Content) 432 ByteArrayOutputStream baos = new ByteArrayOutputStream(); // we write to a stream 433 ByteArrayInputStream bais; // we read from a stream 434 435 // 1. send signed message to MLA 436 System.out.println("1. Creating signed message and send it to MLA..."); 437 Message msg = createMessage(session, senderAddress_, mlaAddress_); 438 msg.setSubject("RFC2634, 4.2.1, 1) S1(Original Content)"); 439 SignedContent sc = create_S1_O(mp, 440 mp.getContentType(), 441 implicit, 442 signerCertificatesOfS1_, 443 signerPrivateKeyOfS1_, 444 (AlgorithmID)AlgorithmID.sha256.clone(), 445 (AlgorithmID)AlgorithmID.dsaWithSHA256.clone(), 446 null); 447 msg.setContent(sc, sc.getContentType()); 448 sc.setHeaders(msg); 449 msg.saveChanges(); 450 baos.reset(); 451 msg.writeTo(baos); 452 // 2. MLA: receives messages, processes it and creates and sends a new signed message 453 System.out.println("2. MLA: Processing message..."); 454 bais = new ByteArrayInputStream(baos.toByteArray()); 455 msg = new MimeMessage(session, bais); 456 if (DUMP_MESSAGES) { 457 System.out.println("Received message:"); 458 dumpMessage(msg); 459 } 460 sc = processMessageForMLA(msg, implicit, "S1_O"); 461 System.out.println("MLA: Sending signed message to new recipient."); 462 msg = createMessage(session, mlaAddress_, recipientAddress_); 463 msg.setSubject("RFC2634, 4.2.1, 1) MLA(S1(Original Content)"); 464 msg.setContent(sc, sc.getContentType()); 465 sc.setHeaders(msg); 466 baos.reset(); 467 msg.writeTo(baos); 468 // 3. final recipient: receives message from MLA, parses it and verifies the signature 469 System.out.println("3. Final recipient: Parsing message received from MLA..."); 470 bais = new ByteArrayInputStream(baos.toByteArray()); 471 msg = new MimeMessage(session, bais); 472 if (DUMP_MESSAGES) { 473 dumpMessage(msg); 474 } 475 // message must be signed by MLA: S2(S1(O)), checking signature S2 476 Object content = msg.getContent(); 477 if ((content instanceof SignedContent == false)) { 478 throw new ESSException("Error: received message is not signed!"); 479 } 480 System.out.println("First layer of message is signed. Verifying signature."); 481 DataHandler dh = verify((SignedContent)content, signerCertificatesOfMLA_[0]); 482 // read MLExpansionHistory attribute, must contain one MLData entry 483 System.out.println("Reading MLExpansionHistory attribute."); 484 readMLExpansionHistory((SignedContent)content, 1); 485 // second layer must be signed, too 486 content = dh.getContent(); 487 if ((content instanceof SignedContent == false)) { 488 throw new ESSException("Error: second layer of received message is not signed!"); 489 } 490 System.out.println("Second layer of message is signed. Verifying signature."); 491 dh = verify((SignedContent)content, signerCertificatesOfS1_[0]); 492 // check content 493 if (CryptoUtils.equalsBlock(dsBytes, getDataSource(dh)) == false) { 494 throw new Exception("Error: Original content changed!"); 495 } 496 dumpContent(dh); 497 } 498 499 500 /** 501 * Tests the MLA behaviour for a triple signed message according to sample 4.2.1,2) of 502 * <a href="https://www.rfc-editor.org/rfc/rfc2634.html" target = "_blank">RFC2634</a>: 503 * <pre> 504 * A message (S3(S2(S1(Original Content)))) is sent to the MLA in 505 * which none of the signedData layers includes an MLExpansionHistory 506 * attribute. The MLA verifies and fully processes the 507 * signedAttributes in S3, S2 and S1. The MLA decides that there is 508 * not an original, received "outer" signedData layer since it finds 509 * the original content, but never finds an envelopedData and never 510 * finds an mlExpansionHistory attribute. The MLA calculates a new 511 * signedData layer, S4, resulting in the following message sent to 512 * the ML recipients: (S4(S3(S2(S1(Original Content))))). The MLA 513 * includes an mlExpansionHistory attribute in S4. 514 * </pre> 515 * 516 * @param session the current mail session 517 * @param mp the multipart content 518 * @param dsBytes the original content dataSorce bytes for comparison 519 * @param implicit whether implicit (content included) or explicit signing shall be used 520 * 521 * @throws Exception if an error coours 522 */ 523 public void test_S3_S2_S1_O(Session session, Multipart mp, byte[] dsBytes, boolean implicit) throws Exception { 524 // RFC2634, 4.2.1, 2) S3(S2(S1(Original Content))) ==> MLA(S3(S2(S1(Original Content)))) 525 ByteArrayOutputStream baos = new ByteArrayOutputStream(); // we write to a stream 526 ByteArrayInputStream bais; // we read from a stream 527 528 // 1. send signed message to MLA 529 System.out.println("1. Creating signed message and send it to MLA..."); 530 Message msg = createMessage(session, senderAddress_, mlaAddress_); 531 msg.setSubject("RFC2634, 4.2.1, 2) S3(S2(S1(Original Content)))"); 532 SignedContent sc = create_S3_S2_S1_O(mp, 533 mp.getContentType(), 534 implicit, 535 signerCertificatesOfS1_, 536 signerPrivateKeyOfS1_, 537 (AlgorithmID)AlgorithmID.sha256.clone(), 538 (AlgorithmID)AlgorithmID.dsaWithSHA256.clone(), 539 null, 540 implicit, 541 signerCertificatesOfS2_, 542 signerPrivateKeyOfS2_, 543 (AlgorithmID)AlgorithmID.sha256.clone(), 544 (AlgorithmID)AlgorithmID.dsaWithSHA256.clone(), 545 null, 546 implicit, 547 signerCertificatesOfS3_, 548 signerPrivateKeyOfS3_, 549 (AlgorithmID)AlgorithmID.sha256.clone(), 550 (AlgorithmID)AlgorithmID.rsaEncryption.clone(), 551 null); 552 msg.setContent(sc, sc.getContentType()); 553 sc.setHeaders(msg); 554 msg.saveChanges(); 555 baos.reset(); 556 msg.writeTo(baos); 557 // 2. MLA: receives messages, processes it and creates and sends a new signed message 558 System.out.println("2. MLA: Processing message..."); 559 bais = new ByteArrayInputStream(baos.toByteArray()); 560 msg = new MimeMessage(session, bais); 561 if (DUMP_MESSAGES) { 562 System.out.println("Received message:"); 563 dumpMessage(msg); 564 } 565 sc = processMessageForMLA(msg, implicit, "S3_S2_S1_O"); 566 System.out.println("MLA: Sending signed message to new recipient."); 567 msg = createMessage(session, mlaAddress_, recipientAddress_); 568 msg.setSubject("RFC2634, 4.2.1, 2) MLA(S3(S2(S1(Original Content))))"); 569 msg.setContent(sc, sc.getContentType()); 570 sc.setHeaders(msg); 571 baos.reset(); 572 msg.writeTo(baos); 573 // 3. final recipient: receives message from MLA, parses it and verifies the signature 574 System.out.println("3. Final recipient: Parsing message received from MLA..."); 575 bais = new ByteArrayInputStream(baos.toByteArray()); 576 msg = new MimeMessage(session, bais); 577 if (DUMP_MESSAGES) { 578 dumpMessage(msg); 579 } 580 // message must be signed by MLA: S4(S3(S2(S1(O)))), checking signature S2 581 Object content = msg.getContent(); 582 if ((content instanceof SignedContent == false)) { 583 throw new ESSException("Error: received message is not signed!"); 584 } 585 System.out.println("First layer of message is signed. Verifying signature."); 586 DataHandler dh = verify((SignedContent)content, signerCertificatesOfMLA_[0]); 587 // read MLExpansionHistory attribute, must contain one MLData entry 588 System.out.println("Reading MLExpansionHistory attribute."); 589 readMLExpansionHistory((SignedContent)content, 1); 590 // second layer must be signed, too 591 content = dh.getContent(); 592 if ((content instanceof SignedContent == false)) { 593 throw new ESSException("Error: second layer of received message is not signed!"); 594 } 595 System.out.println("Second layer of message is signed. Verifying signature."); 596 dh = verify((SignedContent)content, signerCertificatesOfS3_[0]); 597 // third layer must be signed, too 598 content = dh.getContent(); 599 if ((content instanceof SignedContent == false)) { 600 throw new ESSException("Error: third layer of received message is not signed!"); 601 } 602 System.out.println("Third layer of message is signed. Verifying signature."); 603 dh = verify((SignedContent)content, signerCertificatesOfS2_[0]); 604 // fourth layer must be signed, too 605 content = dh.getContent(); 606 if ((content instanceof SignedContent == false)) { 607 throw new ESSException("Error: fourth layer of received message is not signed!"); 608 } 609 System.out.println("Fourth layer of message is signed. Verifying signature."); 610 dh = verify((SignedContent)content, signerCertificatesOfS1_[0]); 611 // check content 612 if (CryptoUtils.equalsBlock(dsBytes, getDataSource(dh)) == false) { 613 throw new Exception("Error: Original content changed!"); 614 } 615 dumpContent(dh); 616 } 617 618 /** 619 * Tests the MLA behaviour for a encrypted and signed signed message according to 620 * sample 4.2.1,3) of <a href="https://www.rfc-editor.org/rfc/rfc2634.html" target = "_blank">RFC2634</a>: 621 * <pre> 622 * A message (E1(S1(Original Content))) (where E = envelopedData) is 623 * sent to the MLA in which S1 does not include an MLExpansionHistory 624 * attribute. The MLA decides that there is not an original, 625 * received "outer" signedData layer since it finds the E1 as the 626 * outer layer. The MLA expands the recipientInformation in E1. The 627 * MLA calculates a new signedData layer, S2, resulting in the 628 * following message sent to the ML recipients: 629 * (S2(E1(S1(Original Content)))). The MLA includes an 630 * mlExpansionHistory attribute in S2. 631 * </pre> 632 * 633 * @param session the current mail session 634 * @param mp the multipart content 635 * @param dsBytes the original content dataSorce bytes for comparison 636 * @param implicit whether implicit (content included) or explicit signing shall be used 637 * 638 * @throws Exception if an error coours 639 */ 640 public void test_E1_S1_O(Session session, Multipart mp, byte[] dsBytes, boolean implicit) throws Exception { 641 // RFC2634, 4.2.1, 3) E1(S1(Original Content)) ==> MLA(E1(S1(Original Content))) 642 ByteArrayOutputStream baos = new ByteArrayOutputStream(); // we write to a stream 643 ByteArrayInputStream bais; // we read from a stream 644 645 // 1. send signed and encrypted message to MLA 646 System.out.println("1. Creating signed and encrypted message and send it to MLA..."); 647 Message msg = createMessage(session, senderAddress_, mlaAddress_); 648 msg.setSubject("RFC2634, 4.2.1, 3) E1(S1(Original Content))"); 649 EncryptedContent ec = create_E1_S1_O(mp, 650 mp.getContentType(), 651 implicit, 652 signerCertificatesOfS1_, 653 signerPrivateKeyOfS1_, 654 (AlgorithmID)AlgorithmID.sha256.clone(), 655 (AlgorithmID)AlgorithmID.dsaWithSHA256.clone(), 656 null, 657 encryptionCertificatesOfMLA_[0], 658 (AlgorithmID)AlgorithmID.rsaEncryption, 659 (AlgorithmID)AlgorithmID.aes128_CBC.clone(), 660 128); 661 msg.setContent(ec, ec.getContentType()); 662 ec.setHeaders(msg); 663 msg.saveChanges(); 664 baos.reset(); 665 msg.writeTo(baos); 666 // 2. MLA: receives messages, processes it and creates and sends a new signed message 667 System.out.println("2. MLA: Processing message..."); 668 bais = new ByteArrayInputStream(baos.toByteArray()); 669 msg = new MimeMessage(session, bais); 670 if (DUMP_MESSAGES) { 671 System.out.println("Received message:"); 672 dumpMessage(msg); 673 } 674 SignedContent sc = processMessageForMLA(msg, implicit, "E1_S1_O"); 675 System.out.println("MLA: Sending signed message to new recipient."); 676 msg = createMessage(session, mlaAddress_, recipientAddress_); 677 msg.setSubject("RFC2634, 4.2.1, 3) MLA(E1(S1(Original Content)))"); 678 msg.setContent(sc, sc.getContentType()); 679 sc.setHeaders(msg); 680 baos.reset(); 681 msg.writeTo(baos); 682 // 3. final recipient: receives message from MLA, parses it 683 System.out.println("3. Final recipient: Parsing message received from MLA..."); 684 bais = new ByteArrayInputStream(baos.toByteArray()); 685 msg = new MimeMessage(session, bais); 686 if (DUMP_MESSAGES) { 687 dumpMessage(msg); 688 } 689 // message must be signed by MLA: S2(E1(S1(O))), checking signature S2 690 Object content = msg.getContent(); 691 if ((content instanceof SignedContent == false)) { 692 throw new ESSException("Error: received message is not signed!"); 693 } 694 System.out.println("First layer of message is signed. Verifying signature."); 695 DataHandler dh = verify((SignedContent)content, signerCertificatesOfMLA_[0]); 696 // read MLExpansionHistory attribute, must contain one MLData entry 697 System.out.println("Reading MLExpansionHistory attribute."); 698 readMLExpansionHistory((SignedContent)content, 1); 699 // second layer must be encrypted 700 content = dh.getContent(); 701 if ((content instanceof EncryptedContent == false)) { 702 throw new ESSException("Error: second layer of received message is not encrypted!"); 703 } 704 System.out.println("Second layer of message is encrypted. Trying to decrypt."); 705 dh = decrypt((EncryptedContent)content, recipientPrivateKey_, recipientCertificates_[0]); 706 // third layer must be signed, too 707 content = dh.getContent(); 708 if ((content instanceof SignedContent == false)) { 709 throw new ESSException("Error: second layer of received message is not signed!"); 710 } 711 System.out.println("Third layer of message is signed. Verifying signature."); 712 dh = verify((SignedContent)content, signerCertificatesOfS1_[0]); 713 // check content 714 if (CryptoUtils.equalsBlock(dsBytes, getDataSource(dh)) == false) { 715 throw new Exception("Error: Original content changed!"); 716 } 717 dumpContent(dh); 718 } 719 720 /** 721 * Tests the MLA behaviour for signed encrypted and signed signed message according to 722 * sample 4.2.1,4) of <a href="https://www.rfc-editor.org/rfc/rfc2634.html" target = "_blank">RFC2634</a>: 723 * <pre> 724 * A message (S2(E1(S1(Original Content)))) is sent to the MLA in 725 * which S2 includes an MLExpansionHistory attribute. The MLA verifies 726 * the signature and fully processes the signedAttributes in S2. The 727 * MLA finds the mlExpansionHistory attribute in S2, so it decides 728 * that S2 is the "outer" signedData. The MLA remembers the 729 * signedAttributes included in S2 for later inclusion in the new 730 * outer signedData that it applies to the message. The MLA strips off 731 * S2. The MLA then expands the recipientInformation in E1 (this 732 * invalidates the signature in S2 which is why it was stripped). The 733 * nMLA calculates a new signedData layer, S3, resulting in the 734 * following message sent to the ML recipients: (S3(E1(S1(Original 735 * Content)))). The MLA includes in S3 the attributes from S2 (unless 736 * it specifically replaces an attribute value) including an updated 737 * mlExpansionHistory attribute. 738 * </pre> 739 * 740 * @param session the current mail session 741 * @param mp the multipart content 742 * @param dsBytes the original content dataSorce bytes for comparison 743 * @param implicit whether implicit (content included) or explicit signing shall be used 744 * 745 * @throws Exception if an error coours 746 */ 747 public void test_S2_E1_S1_O(Session session, Multipart mp, byte[] dsBytes, boolean implicit) throws Exception { 748 // RFC2634, 4.2.1, 4) S2(E1(S1(Original Content))) ==> MLA(E1(S1(Original Content))) 749 ByteArrayOutputStream baos = new ByteArrayOutputStream(); // we write to a stream 750 ByteArrayInputStream bais; // we read from a stream 751 752 // 1. send signed and encrypted and signed message to MLA 753 System.out.println("1. Creating signed and encrypted/signed message and send it to MLA..."); 754 Message msg = createMessage(session, senderAddress_, mlaAddress_); 755 msg.setSubject("RFC2634, 4.2.1, 4) S2(E1(S1(Original Content)))"); 756 SignedContent sc = create_S2_E1_S1_0(mp, 757 mp.getContentType(), 758 implicit, 759 signerCertificatesOfS1_, 760 signerPrivateKeyOfS1_, 761 (AlgorithmID)AlgorithmID.sha256.clone(), 762 (AlgorithmID)AlgorithmID.dsaWithSHA256.clone(), 763 null, 764 encryptionCertificatesOfMLA_[0], 765 (AlgorithmID)AlgorithmID.rsaEncryption.clone(), 766 (AlgorithmID)AlgorithmID.aes128_CBC.clone(), 767 128, 768 implicit, 769 signerCertificatesOfS2_, 770 signerPrivateKeyOfS2_, 771 (AlgorithmID)AlgorithmID.sha256.clone(), 772 (AlgorithmID)AlgorithmID.dsaWithSHA256.clone(), 773 createMLExpansionHistory(signerCertificatesOfS2_[0], new Date(), null)); 774 msg.setContent(sc, sc.getContentType()); 775 sc.setHeaders(msg); 776 msg.saveChanges(); 777 baos.reset(); 778 msg.writeTo(baos); 779 // 2. MLA: receives messages, processes it and creates and sends a new signed message 780 System.out.println("2. MLA: Processing message..."); 781 bais = new ByteArrayInputStream(baos.toByteArray()); 782 msg = new MimeMessage(session, bais); 783 if (DUMP_MESSAGES) { 784 System.out.println("Received message:"); 785 dumpMessage(msg); 786 } 787 sc = processMessageForMLA(msg, implicit, "S2_E1_S1_0"); 788 System.out.println("MLA: Sending signed message to new recipient."); 789 msg = createMessage(session, mlaAddress_, recipientAddress_); 790 msg.setSubject("RFC2634, 4.2.1, 4) MLA(E1(S1(Original Content)))"); 791 msg.setContent(sc, sc.getContentType()); 792 sc.setHeaders(msg); 793 baos.reset(); 794 msg.writeTo(baos); 795 // 3. final recipient: receives message from MLA, parses it 796 System.out.println("3. Final recipient: Parsing message received from MLA..."); 797 bais = new ByteArrayInputStream(baos.toByteArray()); 798 msg = new MimeMessage(session, bais); 799 if (DUMP_MESSAGES) { 800 dumpMessage(msg); 801 } 802 // message must be signed by MLA: S3(E1(S1(O))), checking signature S3 803 Object content = msg.getContent(); 804 if ((content instanceof SignedContent == false)) { 805 throw new ESSException("Error: received message is not signed!"); 806 } 807 System.out.println("First layer of message is signed. Verifying signature."); 808 DataHandler dh = verify((SignedContent)content, signerCertificatesOfMLA_[0]); 809 // read MLExpansionHistory attribute, must contain one MLData entry 810 System.out.println("Reading MLExpansionHistory attributes."); 811 readMLExpansionHistory((SignedContent)content, 2); 812 // second layer must be encrypted 813 content = dh.getContent(); 814 if ((content instanceof EncryptedContent == false)) { 815 throw new ESSException("Error: second layer of received message is not encrypted!"); 816 } 817 System.out.println("Second layer of message is encrypted. Trying to decrypt."); 818 dh = decrypt((EncryptedContent)content, recipientPrivateKey_, recipientCertificates_[0]); 819 // third layer must be signed, too 820 content = dh.getContent(); 821 if ((content instanceof SignedContent == false)) { 822 throw new ESSException("Error: second layer of received message is not signed!"); 823 } 824 System.out.println("Third layer of message is signed. Verifying signature."); 825 dh = verify((SignedContent)content, signerCertificatesOfS1_[0]); 826 // check content 827 if (CryptoUtils.equalsBlock(dsBytes, getDataSource(dh)) == false) { 828 throw new Exception("Error: Original content changed!"); 829 } 830 dumpContent(dh); 831 } 832 833 /** 834 * Tests the MLA behaviour for double signed encrypted and signed signed message 835 * according to sample 4.2.1,5) of <a href="https://www.rfc-editor.org/rfc/rfc2634.html" target = "_blank">RFC2634</a>: 836 * <pre> 837 * A message (S3(S2(E1(S1(Original Content))))) is sent to the MLA in 838 * which none of the signedData layers include an MLExpansionHistory 839 * attribute. The MLA verifies the signature and fully processes the 840 * signedAttributes in S3 and S2. When the MLA encounters E1, then it 841 * decides that S2 is the "outer" signedData since S2 encapsulates E1. 842 * The MLA remembers the signedAttributes included in S2 for later 843 * inclusion in the new outer signedData that it applies to the 844 * message. The MLA strips off S3 and S2. The MLA then expands the 845 * recipientInformation in E1 (this invalidates the signatures in S3 846 * and S2 which is why they were stripped). The MLA calculates a new 847 * signedData layer, S4, resulting in the following message sent to 848 * the ML recipients: (S4(E1(S1(Original Content)))). The MLA 849 * includes in S4 the attributes from S2 (unless it specifically 850 * replaces an attribute value) and includes a new 851 * mlExpansionHistory attribute. 852 * </pre> 853 * 854 * @param session the current mail session 855 * @param mp the multipart content 856 * @param dsBytes the original content dataSorce bytes for comparison 857 * @param implicit whether implicit (content included) or explicit signing shall be used 858 * @param includeMLExpansionHistoryInS3 whether to include an MLExpansionHistory in the 859 * the outermost signed layer (S3) of the original 860 * message 861 * 862 * @throws Exception if an error coours 863 */ 864 public void test_S3_S2_E1_S1_O(Session session, 865 Multipart mp, 866 byte[] dsBytes, 867 boolean implicit, 868 boolean includeMLExpansionHistoryInS3) throws Exception { 869 // RFC2634, 4.2.1, 5) S3(S2(E1(S1(Original Content)))) ==> MLA(E1(S1(Original Content))) 870 ByteArrayOutputStream baos = new ByteArrayOutputStream(); // we write to a stream 871 ByteArrayInputStream bais; // we read from a stream 872 873 // 1. send double signed and encrypted and signed message to MLA 874 System.out.println("1. Creating double signed and encrypted/signed message and send it to MLA..."); 875 Message msg = createMessage(session, senderAddress_, mlaAddress_); 876 msg.setSubject("RFC2634, 4.2.1, 5) S3(S2(E1(S1(Original Content))))"); 877 SignedContent sc = create_S3_S2_E1_S1_0(mp, 878 mp.getContentType(), 879 implicit, 880 signerCertificatesOfS1_, 881 signerPrivateKeyOfS1_, 882 (AlgorithmID)AlgorithmID.sha256.clone(), 883 (AlgorithmID)AlgorithmID.dsaWithSHA256.clone(), 884 null, 885 encryptionCertificatesOfMLA_[0], 886 (AlgorithmID)AlgorithmID.rsaEncryption.clone(), 887 (AlgorithmID)AlgorithmID.aes128_CBC.clone(), 888 128, 889 implicit, 890 signerCertificatesOfS2_, 891 signerPrivateKeyOfS2_, 892 (AlgorithmID)AlgorithmID.sha256.clone(), 893 (AlgorithmID)AlgorithmID.dsaWithSHA256.clone(), 894 null, 895 implicit, 896 signerCertificatesOfS3_, 897 signerPrivateKeyOfS3_, 898 (AlgorithmID)AlgorithmID.sha256.clone(), 899 (AlgorithmID)AlgorithmID.rsaEncryption.clone(), 900 (includeMLExpansionHistoryInS3 ? 901 createMLExpansionHistory(signerCertificatesOfS3_[0], new Date(), null) : 902 null)); 903 msg.setContent(sc, sc.getContentType()); 904 sc.setHeaders(msg); 905 msg.saveChanges(); 906 baos.reset(); 907 msg.writeTo(baos); 908 // 2. MLA: receives messages, processes it and creates and sends a new signed message 909 System.out.println("2. MLA: Processing message..."); 910 bais = new ByteArrayInputStream(baos.toByteArray()); 911 msg = new MimeMessage(session, bais); 912 if (DUMP_MESSAGES) { 913 System.out.println("Received message:"); 914 dumpMessage(msg); 915 } 916 sc = processMessageForMLA(msg, implicit, "S3_S2_E1_S1_0"); 917 System.out.println("MLA: Sending signed message to new recipient."); 918 msg = createMessage(session, mlaAddress_, recipientAddress_); 919 msg.setSubject("RFC2634, 4.2.1, 5) MLA(E1(S1(Original Content)))"); 920 msg.setContent(sc, sc.getContentType()); 921 sc.setHeaders(msg); 922 baos.reset(); 923 msg.writeTo(baos); 924 // 3. final recipient: receives message from MLA, parses it 925 System.out.println("3. Final recipient: Parsing message received from MLA..."); 926 bais = new ByteArrayInputStream(baos.toByteArray()); 927 msg = new MimeMessage(session, bais); 928 if (DUMP_MESSAGES) { 929 dumpMessage(msg); 930 } 931 // message must be signed by MLA: S4(E1(S1(O))), checking signature S4 932 Object content = msg.getContent(); 933 if ((content instanceof SignedContent == false)) { 934 throw new ESSException("Error: received message is not signed!"); 935 } 936 System.out.println("First layer of message is signed. Verifying signature."); 937 DataHandler dh = verify((SignedContent)content, signerCertificatesOfMLA_[0]); 938 // read MLExpansionHistory attribute, must contain one MLData entry 939 System.out.println("Reading MLExpansionHistory attributes."); 940 readMLExpansionHistory((SignedContent)content, includeMLExpansionHistoryInS3 ? 2 : 1); 941 // second layer must be encrypted 942 content = dh.getContent(); 943 if ((content instanceof EncryptedContent == false)) { 944 throw new ESSException("Error: second layer of received message is not encrypted!"); 945 } 946 System.out.println("Second layer of message is encrypted. Trying to decrypt."); 947 dh = decrypt((EncryptedContent)content, recipientPrivateKey_, recipientCertificates_[0]); 948 // third layer must be signed, too 949 content = dh.getContent(); 950 if ((content instanceof SignedContent == false)) { 951 throw new ESSException("Error: second layer of received message is not signed!"); 952 } 953 System.out.println("Third layer of message is signed. Verifying signature."); 954 dh = verify((SignedContent)content, signerCertificatesOfS1_[0]); 955 // check content 956 if (CryptoUtils.equalsBlock(dsBytes, getDataSource(dh)) == false) { 957 throw new Exception("Error: Original content changed!"); 958 } 959 dumpContent(dh); 960 } 961 962 /** 963 * Creates a new MimeMessage without content and sets the From:, To:, and Date: headers. 964 * 965 * @param session the current mail session 966 * @param from the address of the sender of the message 967 * @param to the address of the indented message recipient 968 * @return the new created MimeMessage 969 * @throws MessagingException if an error occurs when setting the message headers 970 */ 971 public Message createMessage(Session session, String from, String to) throws MessagingException { 972 MimeMessage msg = new MimeMessage(session); 973 msg.setFrom(new InternetAddress(from)); 974 msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to, false)); 975 msg.setSentDate(new Date()); 976 return msg; 977 } 978 979 /** 980 * Creates a SignedContent. 981 * 982 * @param content the content to be signed 983 * @param contentType the MIME type of the content 984 * @param implicit whether to create an implicit (application/pkcs7-mime) or 985 * explicit (multipart/signed) message 986 * @param signerCertificates the certificate chain of the signer 987 * @param signerPrivateKey the private key to be used for signing the content 988 * @param digestAlg the algorithm to be used for digest calculation 989 * @param signatureAlg the algorithm to be used for signature calculation 990 * @param mlExpansionHistory MLExpansionHistory attribute to be added; maybe null 991 * 992 * @return the SignedContent 993 * 994 * @throws MessagingException if a problem occurs when creating the SignedContent 995 */ 996 public SignedContent createSignedContent(Object content, 997 String contentType, 998 boolean implicit, 999 X509Certificate[] signerCertificates, 1000 PrivateKey signerPrivateKey, 1001 AlgorithmID digestAlg, 1002 AlgorithmID signatureAlg, 1003 MLExpansionHistory mlExpansionHistory) 1004 throws MessagingException { 1005 1006 SignedContent sc = new SignedContent(implicit); 1007 sc.setContent(content, contentType); 1008 sc.setCertificates(signerCertificates); 1009 try { 1010 // create a set of standard attributes 1011 Attributes attributes = SMimeUtil.makeStandardAttributes(); 1012 if (mlExpansionHistory != null) { 1013 attributes.addAttribute(new Attribute(mlExpansionHistory)); 1014 } 1015 sc.addSigner(signerPrivateKey, signerCertificates[0], digestAlg, signatureAlg, attributes.toArray()); 1016 } catch (NoSuchAlgorithmException ex) { 1017 throw new MessagingException("Algorithm not supported: " + ex.getMessage(), ex); 1018 } catch (CodingException ex) { 1019 throw new MessagingException("Error in attribute encoding: " + ex.getMessage()); 1020 } catch (SMimeException ex) { 1021 throw new MessagingException("Error adding attributes: " + ex.toString()); 1022 } 1023 1024 return sc; 1025 } 1026 1027 /** 1028 * Creates an EncryptedContent. 1029 * 1030 * @param content the content to be encrypted 1031 * @param contentType the MIME type of the content 1032 * @param recipientCertificate the encryption certificate of the recipient 1033 * @param cekEncrAlg the algorithm to be used for encrypting the symmetric content encryption key 1034 * (e.g. AlgorithmID.rsaEncryption) 1035 * @param contentEncrAlg the symmetric key to be used for encrypting the content, e.g. AlgorithmID.aes256_CBC 1036 * @param cekLength the length of the temporary content encryption key to be generated (e.g. 256) 1037 * 1038 * @return the EncryptedContent 1039 * 1040 * @throws MessagingException if a problem occurs when creating the EncryptedContent 1041 */ 1042 public EncryptedContent createEncryptedContent(Object content, 1043 String contentType, 1044 X509Certificate recipientCertificate, 1045 AlgorithmID cekEncrAlg, 1046 AlgorithmID contentEncrAlg, 1047 int cekLength) throws MessagingException { 1048 1049 EncryptedContent ec = new EncryptedContent(); 1050 ec.setContent(content, contentType); 1051 // encrypt for the recipient 1052 ec.addRecipient(recipientCertificate, cekEncrAlg); 1053 try { 1054 ec.setEncryptionAlgorithm(contentEncrAlg, cekLength); 1055 } catch (NoSuchAlgorithmException ex) { 1056 throw new MessagingException("Content encryption algorithm not supported: " + ex.getMessage()); 1057 } 1058 1059 return ec; 1060 } 1061 1062 /** 1063 * Signs the given content. 1064 * 1065 * @param content the content to be signed 1066 * @param contentType the MIME type of the content 1067 * @param implicitS1 whether to create an implicit (application/pkcs7-mime) or 1068 * explicit (multipart/signed) message 1069 * @param signerCertificatesS1 the certificate chain of the signer 1070 * @param signerPrivateKeyS1 the private key to be used for signing the content 1071 * @param digestAlgS1 the algorithm to be used for digest calculation 1072 * @param signatureAlgS1 the algorithm to be used for signature calculation 1073 * @param mlExpansionHistoryS1 MLExpansionHistory attribute to be added; maybe null 1074 * 1075 * @return the SignedContent 1076 * 1077 * @throws MessagingException if a problem occurs when creating the SignedContent 1078 */ 1079 public SignedContent create_S1_O(Object content, 1080 String contentType, 1081 boolean implicitS1, 1082 X509Certificate[] signerCertificatesS1, 1083 PrivateKey signerPrivateKeyS1, 1084 AlgorithmID digestAlgS1, 1085 AlgorithmID signatureAlgS1, 1086 MLExpansionHistory mlExpansionHistoryS1) 1087 throws MessagingException { 1088 1089 return createSignedContent(content, 1090 contentType, 1091 implicitS1, 1092 signerCertificatesS1, 1093 signerPrivateKeyS1, 1094 digestAlgS1, 1095 signatureAlgS1, 1096 mlExpansionHistoryS1); 1097 } 1098 1099 /** 1100 * Triple-signs the given content. 1101 * 1102 * @param content the content to be signed 1103 * @param contentType the MIME type of the content 1104 * @param implicitS1 if the first signature shall be implicit (application/pkcs7-mime) or 1105 * explicit (multipart/signed) 1106 * @param signerCertificatesS1 the certificate chain of the first signer 1107 * @param signerPrivateKeyS1 the private key of the first signer 1108 * @param digestAlgS1 the digest algorithm to be used for digest calculation by the innermost SignedContent 1109 * @param signatureAlgS1 the algorithm to be used for signature calculation by the innermost SignedContent 1110 * @param mlExpansionHistoryS1 MLExpansionHistory attribute to be added to the innermost SignedContent; maybe null 1111 * @param implicitS2 if the second signature shall be implicit (application/pkcs7-mime) or 1112 * explicit (multipart/signed) 1113 * @param signerCertificatesS2 the certificate chain of the second signer 1114 * @param signerPrivateKeyS2 the private key of the second signer 1115 * @param digestAlgS2 the digest algorithm to be used for digest calculation by the middle SignedContent 1116 * @param signatureAlgS2 the algorithm to be used for signature calculation by the middle SignedContent 1117 * @param mlExpansionHistoryS2 MLExpansionHistory attribute to be added to the middle SignedContent; maybe null 1118 * @param implicitS3 if the first signature shall be implicit (application/pkcs7-mime) or 1119 * explicit (multipart/signed) 1120 * @param signerCertificatesS3 the certificate chain of the third signer 1121 * @param signerPrivateKeyS3 the private key of the third signer 1122 * @param digestAlgS3 the digest algorithm to be used for digest calculation by the outermost SignedContent 1123 * @param signatureAlgS3 the algorithm to be used for signature calculation by the outermost SignedContent 1124 * @param mlExpansionHistoryS3 MLExpansionHistory attribute to be added for the outermost SignedContent; maybe null 1125 * 1126 * @return the SignedContent 1127 * 1128 * @throws MessagingException if a problem occurs when creating the SignedContent 1129 */ 1130 public SignedContent create_S3_S2_S1_O(Object content, 1131 String contentType, 1132 boolean implicitS1, 1133 X509Certificate[] signerCertificatesS1, 1134 PrivateKey signerPrivateKeyS1, 1135 AlgorithmID digestAlgS1, 1136 AlgorithmID signatureAlgS1, 1137 MLExpansionHistory mlExpansionHistoryS1, 1138 boolean implicitS2, 1139 X509Certificate[] signerCertificatesS2, 1140 PrivateKey signerPrivateKeyS2, 1141 AlgorithmID digestAlgS2, 1142 AlgorithmID signatureAlgS2, 1143 MLExpansionHistory mlExpansionHistoryS2, 1144 boolean implicitS3, 1145 X509Certificate[] signerCertificatesS3, 1146 PrivateKey signerPrivateKeyS3, 1147 AlgorithmID digestAlgS3, 1148 AlgorithmID signatureAlgS3, 1149 MLExpansionHistory mlExpansionHistoryS3) 1150 throws MessagingException { 1151 SignedContent s1 = create_S1_O(content, contentType, 1152 implicitS1, signerCertificatesS1, signerPrivateKeyS1, digestAlgS1, signatureAlgS1, mlExpansionHistoryS1); 1153 SignedContent s2 = createSignedContent(s1, s1.getContentType(), 1154 implicitS2, signerCertificatesS2, signerPrivateKeyS2, digestAlgS2, signatureAlgS2, mlExpansionHistoryS2); 1155 return createSignedContent(s2, s2.getContentType(), 1156 implicitS3, signerCertificatesS3, signerPrivateKeyS3, digestAlgS3, signatureAlgS3, mlExpansionHistoryS3); 1157 } 1158 1159 /** 1160 * Encrypts and signs the given content. 1161 * 1162 * @param content the content to be signed 1163 * @param contentType the MIME type of the content 1164 * @param implicitS1 whether to create an implicit (application/pkcs7-mime) or 1165 * explicit (multipart/signed) message 1166 * @param signerCertificatesS1 the certificate chain of the signer 1167 * @param signerPrivateKeyS1 the private key to be used for signing the content 1168 * @param digestAlgS1 the algorithm to be used for digest calculation 1169 * @param signatureAlgS1 the algorithm to be used for signature calculation 1170 * @param mlExpansionHistoryS1 MLExpansionHistory attribute to be added; maybe null 1171 * @param recipientCertificate the encryption certificate of the recipient 1172 * @param cekEncrAlg the algorithm to be used for encrypting the symmetric content encryption key 1173 * (e.g. AlgorithmID.rsaEncryption) 1174 * @param contentEncrAlg the symmetric key to be used for encrypting the content, e.g. AlgorithmID.aes256_CBC 1175 * @param cekLength the length of the temporary content encryption key to be generated (e.g. 256) 1176 * 1177 * @return the signed and encrypted message 1178 * 1179 * @throws MessagingException if a problem occurs when creating the SignedContent or EncryptedContent 1180 */ 1181 public EncryptedContent create_E1_S1_O(Object content, 1182 String contentType, 1183 boolean implicitS1, 1184 X509Certificate[] signerCertificatesS1, 1185 PrivateKey signerPrivateKeyS1, 1186 AlgorithmID digestAlgS1, 1187 AlgorithmID signatureAlgS1, 1188 MLExpansionHistory mlExpansionHistoryS1, 1189 X509Certificate recipientCertificate, 1190 AlgorithmID cekEncrAlg, 1191 AlgorithmID contentEncrAlg, 1192 int cekLength) 1193 throws MessagingException { 1194 1195 SignedContent s1 = create_S1_O(content, contentType, 1196 implicitS1, signerCertificatesS1, signerPrivateKeyS1, digestAlgS1, signatureAlgS1, mlExpansionHistoryS1); 1197 return createEncryptedContent(s1, s1.getContentType(), 1198 recipientCertificate, cekEncrAlg, contentEncrAlg, cekLength); 1199 } 1200 1201 1202 /** 1203 * Signs and encrypts and signs the given content. 1204 * 1205 * @param content the content to be signed 1206 * @param contentType the MIME type of the content 1207 * @param implicitS1 if the first signature shall be implicit (application/pkcs7-mime) or 1208 * explicit (multipart/signed) 1209 * @param signerCertificatesS1 the certificate chain of the first signer 1210 * @param signerPrivateKeyS1 the private key of the first signer 1211 * @param digestAlgS1 the digest algorithm to be used for digest calculation by the innermost SignedContent 1212 * @param signatureAlgS1 the algorithm to be used for signature calculation by the innermost SignedContent 1213 * @param mlExpansionHistoryS1 MLExpansionHistory attribute to be added to the innermost SignedContent; maybe null 1214 * @param recipientCertificate the encryption certificate of the recipient 1215 * @param cekEncrAlg the algorithm to be used for encrypting the symmetric content encryption key 1216 * (e.g. AlgorithmID.rsaEncryption) 1217 * @param contentEncrAlg the symmetric key to be used for encrypting the content, e.g. AlgorithmID.aes256_CBC 1218 * @param cekLength the length of the temporary content encryption key to be generated (e.g. 256) 1219 * @param implicitS2 if the second signature shall be implicit (application/pkcs7-mime) or 1220 * explicit (multipart/signed) 1221 * @param signerCertificatesS2 the certificate chain of the second signer 1222 * @param signerPrivateKeyS2 the private key of the second signer 1223 * @param digestAlgS2 the digest algorithm to be used for digest calculation by the outer SignedContent 1224 * @param signatureAlgS2 the algorithm to be used for signature calculation by the outer SignedContent 1225 * @param mlExpansionHistoryS2 MLExpansionHistory attribute to be added to the outer SignedContent; maybe null 1226 * 1227 * @return the signed and encrypted and signed message 1228 * 1229 * @throws MessagingException if a problem occurs when creating a SignedContent or EncryptedContent 1230 */ 1231 public SignedContent create_S2_E1_S1_0(Object content, 1232 String contentType, 1233 boolean implicitS1, 1234 X509Certificate[] signerCertificatesS1, 1235 PrivateKey signerPrivateKeyS1, 1236 AlgorithmID digestAlgS1, 1237 AlgorithmID signatureAlgS1, 1238 MLExpansionHistory mlExpansionHistoryS1, 1239 X509Certificate recipientCertificate, 1240 AlgorithmID cekEncrAlg, 1241 AlgorithmID contentEncrAlg, 1242 int cekLength, 1243 boolean implicitS2, 1244 X509Certificate[] signerCertificatesS2, 1245 PrivateKey signerPrivateKeyS2, 1246 AlgorithmID digestAlgS2, 1247 AlgorithmID signatureAlgS2, 1248 MLExpansionHistory mlExpansionHistoryS2) 1249 throws MessagingException { 1250 1251 EncryptedContent e1 = create_E1_S1_O(content, 1252 contentType, 1253 implicitS1, 1254 signerCertificatesS1, 1255 signerPrivateKeyS1, 1256 digestAlgS1, 1257 signatureAlgS1, 1258 mlExpansionHistoryS1, 1259 recipientCertificate, 1260 cekEncrAlg, 1261 contentEncrAlg, 1262 cekLength); 1263 return createSignedContent(e1, e1.getContentType(), 1264 implicitS2, signerCertificatesS2, signerPrivateKeyS2, digestAlgS2, signatureAlgS2, mlExpansionHistoryS2); 1265 } 1266 1267 /** 1268 * Signs and encrypts and double-signs the given content. 1269 * 1270 * @param content the content to be signed 1271 * @param contentType the MIME type of the content 1272 * @param implicitS1 if the first signature shall be implicit (application/pkcs7-mime) or 1273 * explicit (multipart/signed) 1274 * @param signerCertificatesS1 the certificate chain of the first signer 1275 * @param signerPrivateKeyS1 the private key of the first signer 1276 * @param digestAlgS1 the digest algorithm to be used for digest calculation by the innermost SignedContent 1277 * @param signatureAlgS1 the algorithm to be used for signature calculation by the innermost SignedContent 1278 * @param mlExpansionHistoryS1 MLExpansionHistory attribute to be added to the innermost SignedContent; maybe null 1279 * @param recipientCertificate the encryption certificate of the recipient 1280 * @param cekEncrAlg the algorithm to be used for encrypting the symmetric content encryption key 1281 * (e.g. AlgorithmID.rsaEncryption) 1282 * @param contentEncrAlg the symmetric key to be used for encrypting the content, e.g. AlgorithmID.aes256_CBC 1283 * @param cekLength the length of the temporary content encryption key to be generated (e.g. 256) 1284 * @param implicitS2 if the second signature shall be implicit (application/pkcs7-mime) or 1285 * explicit (multipart/signed) 1286 * @param signerCertificatesS2 the certificate chain of the second signer 1287 * @param signerPrivateKeyS2 the private key of the second signer 1288 * @param digestAlgS2 the digest algorithm to be used for digest calculation by the middle SignedContent 1289 * @param signatureAlgS2 the algorithm to be used for signature calculation by the middle SignedContent 1290 * @param mlExpansionHistoryS2 MLExpansionHistory attribute to be added to the middle SignedContent; maybe null 1291 * @param implicitS3 if the first signature shall be implicit (application/pkcs7-mime) or 1292 * explicit (multipart/signed) 1293 * @param signerCertificatesS3 the certificate chain of the third signer 1294 * @param signerPrivateKeyS3 the private key of the third signer 1295 * @param digestAlgS3 the digest algorithm to be used for digest calculation by the outermost SignedContent 1296 * @param signatureAlgS3 the algorithm to be used for signature calculation by the outermost SignedContent 1297 * @param mlExpansionHistoryS3 MLExpansionHistory attribute to be added for the outermost SignedContent; maybe null 1298 * 1299 * @return the signed and encrypted and double-signed message 1300 * 1301 * @throws MessagingException if a problem occurs when creating a SignedContent or EncryptedContent 1302 */ 1303 public SignedContent create_S3_S2_E1_S1_0(Object content, 1304 String contentType, 1305 boolean implicitS1, 1306 X509Certificate[] signerCertificatesS1, 1307 PrivateKey signerPrivateKeyS1, 1308 AlgorithmID digestAlgS1, 1309 AlgorithmID signatureAlgS1, 1310 MLExpansionHistory mlExpansionHistoryS1, 1311 X509Certificate recipientCertificate, 1312 AlgorithmID cekEncrAlg, 1313 AlgorithmID contentEncrAlg, 1314 int cekLength, 1315 boolean implicitS2, 1316 X509Certificate[] signerCertificatesS2, 1317 PrivateKey signerPrivateKeyS2, 1318 AlgorithmID digestAlgS2, 1319 AlgorithmID signatureAlgS2, 1320 MLExpansionHistory mlExpansionHistoryS2, 1321 boolean implicitS3, 1322 X509Certificate[] signerCertificatesS3, 1323 PrivateKey signerPrivateKeyS3, 1324 AlgorithmID digestAlgS3, 1325 AlgorithmID signatureAlgS3, 1326 MLExpansionHistory mlExpansionHistoryS3) 1327 throws MessagingException { 1328 1329 SignedContent s2 = create_S2_E1_S1_0(content, 1330 contentType, 1331 implicitS1, 1332 signerCertificatesS1, 1333 signerPrivateKeyS1, 1334 digestAlgS1, 1335 signatureAlgS1, 1336 mlExpansionHistoryS1, 1337 recipientCertificate, 1338 cekEncrAlg, 1339 contentEncrAlg, 1340 cekLength, 1341 implicitS2, 1342 signerCertificatesS2, 1343 signerPrivateKeyS2, 1344 digestAlgS2, 1345 signatureAlgS2, 1346 mlExpansionHistoryS2) ; 1347 1348 return createSignedContent(s2, s2.getContentType(), 1349 implicitS3, signerCertificatesS3, signerPrivateKeyS3, digestAlgS3, signatureAlgS3, mlExpansionHistoryS3); 1350 } 1351 1352 /** 1353 * Decrypts the encrypted content with the given key of the identified recipient. 1354 * 1355 * @param ec the EncryptedContent to be decrypted 1356 * @param privateKey the private key to be used to decrypt the encrypted content 1357 * @param certificate the certificate identifying the recipient for which to decrypt the encrypted content 1358 * 1359 * @return the DataHandler holding the recovered (decrypted) content 1360 * 1361 * @throws SMimeException if an error occurs while decrypting the content 1362 */ 1363 public DataHandler decrypt(EncryptedContent ec, PrivateKey privateKey, X509Certificate certificate) 1364 throws SMimeException { 1365 try { 1366 ec.decryptSymmetricKey(privateKey, certificate); 1367 return ec.getDataHandler(); 1368 } catch (Exception ex) { 1369 throw new SMimeException(ex.toString()); 1370 } 1371 } 1372 1373 /** 1374 * Verifies the signature of the given SignedContent and returns the inherent content data. 1375 * 1376 * @param sc the SignedContent to be verified 1377 * @param signerCert the certificate of the signer (to check if the message has been signed 1378 * by the expected entity) 1379 * @return the inherent content data 1380 * @throws CMSSignatureException if the signature is invalid 1381 * @throws ESSException if an error occurs when accessing the inherent content or 1382 * the message has been signed by an unexpected entity 1383 * @throws MessagingException if an error occurs when accessing the content 1384 */ 1385 public DataHandler verify(SignedContent sc, X509Certificate signerCert) 1386 throws CMSSignatureException, MessagingException, ESSException { 1387 1388 X509Certificate signer = sc.verify(); 1389 System.out.println("Signature ok from: "+signer.getSubjectDN()); 1390 if (signer.equals(signerCert) == false) { 1391 throw new ESSException("Error: message signed by wrong entity (" + signer.getSubjectDN() + ").\nExpected " 1392 + signerCert.getSubjectDN()); 1393 } 1394 return sc.getDataHandler(); 1395 } 1396 1397 /** 1398 * Dumps the content of the original multipart message. 1399 * 1400 * @param dh the dataHandler supplying the content of the original message 1401 * @throws IOException if an I/O error occurs while dumping the content 1402 * @throws MessagingException if an error occurs while reading the body parts of the message 1403 */ 1404 public void dumpContent(DataHandler dh) throws IOException, MessagingException { 1405 Multipart mp = (Multipart)dh.getContent(); 1406 System.out.println("Content is multipart (" + mp.getContentType() + ")."); 1407 BodyPart bp1 = mp.getBodyPart(0); 1408 System.out.println("Content of first bodypart (" + bp1.getContentType() + "):"); 1409 System.out.println(bp1.getContent()); 1410 BodyPart bp2 = mp.getBodyPart(1); 1411 System.out.println("Content of second bodypart (" + bp2.getContentType() + "):"); 1412 System.out.println(bp2.getContent()); 1413 1414 } 1415 1416 public SignedContent processMessageForMLA(Message msg, boolean implicit, String debugID) throws ESSLayerException, ESSException { 1417 1418 // resolve the message into its layers 1419 ESSLayers layers = mla_.resolve(msg, debugID); 1420 try { 1421 return mla_.createSignedContent(signerPrivateKeyOfMLA_, 1422 new Date(), 1423 signerCertificatesOfMLA_[0], 1424 signerCertificatesOfMLA_, 1425 (AlgorithmID)AlgorithmID.sha256.clone(), 1426 (AlgorithmID)AlgorithmID.rsaEncryption.clone(), 1427 encryptionCertificatesOfMLA_[0], 1428 true, 1429 implicit, 1430 layers); 1431 } catch (Exception ex) { 1432 throw new ESSException("Error signing content: " + ex.toString()); 1433 } 1434 } 1435 1436 /** 1437 * Gets the data source encoding from the given data handler. 1438 * 1439 * @param dh the data handler from which to get the data source 1440 * 1441 * @return the dataSource encoding; used for comparison 1442 * 1443 * @throws IOExceptio if an error occurs when reading the datasource 1444 */ 1445 private byte[] getDataSource(DataHandler dh) throws IOException { 1446 DataSource ds = dh.getDataSource(); 1447 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 1448 Utils.copyStream(ds.getInputStream(), baos, null); 1449 return baos.toByteArray(); 1450 } 1451 1452 1453 1454 /** 1455 * Creates a MLExpansionHistory containing only one MLData for 1456 * the given MLA with given expansion time and MLReceiptPolicy. 1457 * 1458 * @param mlaCertificate the certificate of the MLA from which to create the 1459 * MLData EntityIdentiifier of type IssuerAndSerialNumber 1460 * @param expansionTime the expansion time 1461 * @param mlReceiptPolicy the MLReceiptPolicy; may be null 1462 * 1463 * @return the newly created MLExpansionHistory 1464 */ 1465 public static MLExpansionHistory createMLExpansionHistory(X509Certificate mlaCertificate, 1466 Date expansionTime, 1467 MLReceiptPolicy mlReceiptPolicy) { 1468 1469 IssuerAndSerialNumber ias = new IssuerAndSerialNumber(mlaCertificate); 1470 MLData mlData = new MLData(new EntityIdentifier(ias), expansionTime); 1471 mlData.setMLReceiptPolicy(mlReceiptPolicy); 1472 return new MLExpansionHistory(mlData); 1473 } 1474 1475 /** 1476 * Reads the MLExpansionHistory attribute from the given signed data and dumps the 1477 * included MLData structures. 1478 * 1479 * @param signedContent the (MLA created) SignedContent to be parsed for the MLExpansionHistory 1480 * attribute 1481 * @param count the (expected) number of MLData entries included in the MLExpansionHistory attribute 1482 * 1483 * @throws Exception if an error occurs when parsing the MLExpansionHistory attribute, or if 1484 * no MLExpansionHistory attribute is inlcuded or if the MLExpansionHistory 1485 * does contain an unexpected number of MLData entries 1486 */ 1487 public static void readMLExpansionHistory(SignedContent signedContent, int count) throws Exception { 1488 SignerInfo signerInfo = signedContent.getSignerInfos()[0]; 1489 MLExpansionHistory mlExpansionHistory = (MLExpansionHistory)signerInfo.getSignedAttributeValue(MLExpansionHistory.oid); 1490 if (mlExpansionHistory == null) { 1491 throw new Exception("Missing MLExpansionHistory attribute"); 1492 } 1493 int size = mlExpansionHistory.countMLDataEntries(); 1494 if (count != size) { 1495 throw new Exception("Invalid number (" + size + ") of MLData entries. Expected " + count); 1496 } 1497 System.out.println(mlExpansionHistory.toString(true)); 1498 } 1499 1500 /** 1501 * Prints a dump of the given message to System.out. 1502 * 1503 * @param msg the message to be dumped to System.out 1504 */ 1505 private static void dumpMessage(Message msg) throws IOException { 1506 System.out.println("******************************************************************"); 1507 System.out.println("Message dump: \n"); 1508 try { 1509 msg.writeTo(System.out); 1510 } catch (MessagingException ex) { 1511 throw new IOException(ex.getMessage()); 1512 } 1513 System.out.println("\n******************************************************************"); 1514 } 1515 1516 /** 1517 * Main method. 1518 */ 1519 public static void main(String[] argv) throws Exception { 1520 try { 1521 DemoSMimeUtil.initDemos(); 1522 (new MLADemo()).start(); 1523 } catch (Exception ex) { 1524 ex.printStackTrace(); 1525 } 1526 DemoUtil.waitKey(); 1527 } 1528 }