001// Copyright (C) 2002 IAIK 002// https://sic.tech/ 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// This source is provided for inspection purposes and recompilation only, 011// unless specified differently in a contract with IAIK. This source has to 012// be kept in strict confidence and must not be disclosed to any third party 013// under any circumstances. Redistribution in source and binary forms, with 014// or without modification, are <not> permitted in any case! 015// 016// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 017// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 018// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 019// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 020// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 021// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 022// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 023// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 024// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 025// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 026// SUCH DAMAGE. 027// 028// $Header: /IAIK-CMS/current/src/demo/smime/ecc/SMimeV4BrainpoolDemo.java 3 12.02.25 17:59 Dbratko $ 029// $Revision: 3 $ 030// 031 032package demo.smime.ecc; 033 034import java.security.PrivateKey; 035 036import jakarta.activation.DataHandler; 037import jakarta.mail.Session; 038 039import demo.DemoSMimeUtil; 040import demo.DemoUtil; 041import demo.cms.ecc.ECCDemoUtil; 042import demo.cms.ecc.keystore.CMSEccKeyStore; 043import iaik.asn1.structures.AlgorithmID; 044import iaik.cms.CMSAlgorithmID; 045import iaik.utils.KeyAndCertificate; 046import iaik.x509.X509Certificate; 047 048/** 049 * This class demonstrates the usage of the IAIK S/MIME implementation. It shows how to create 050 * signed and/or (authenticated) encrypted S/MIMEv4 messages using ECC keys with Berainpool curves 051 * and how to parse them and verify the signatures and decrypt the content, respectively. 052 * <p> 053 * Although Brainpool curves may not be widely used with S/MIME applications they are, e.g., recommended 054 * by the German Federal Office for Information Security (BSI) for their Technical Guideline BSI TR-03116 055 * defining cryptographic requirements for projects of the Federal Government. 056 * Note that whereas S/MIME in general uses AEAD cipher modes like GCM with the <code>AuthEnvelopedData</code> 057 * content type, BSI TR-03116 specifies GCM for use with the <code>EnvelopedData</code> type. For that 058 * reason GCM is used with <code>EnvelopedData</code> in this demo (in difference to the parent 059 * {@link SMimeV4EccDemo SMimeV4EccDemo} which uses GCM with the <code>AuthEnvelopedData</code> type. 060 * 061 * <p> 062 * Additionally to <code>iaik_cms.jar</code> you also must have 063 * <code>iaik_jce_(full).jar</code> (IAIK-JCE, <a href = 064 * "https://sic.tech/products/core-crypto-toolkits/jca-jce/" target="_blank"> 065 * https://sic.tech/products/core-crypto-toolkits/jca-jce/</a>), 066 * and <code>iaik_eccelarate.jar</code> (IAIK-ECCelerate<sup><small>TM</small></sup>, <a href = 067 * "https://sic.tech/products/core-crypto-toolkits/eccelerate/" target="_blank"> 068 * https://sic.tech/products/core-crypto-toolkits/eccelerate/</a>) 069 * in your classpath. 070 * <p> 071 * To run this demo the following packages are required: 072 * <ul> 073 * <li> 074 * <code>iaik_cms.jar</code> 075 * </li> 076 * <li> 077 * <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>). 078 * </li> 079 * <li> 080 * <code>iaik_eccelerate.jar</code> (<a href="https://sic.tech/products/core-crypto-toolkits/eccelerate/" target="_blank">IAIK ECC Library</a>). 081 * </li> 082 * <li> 083 * <a href="https://jakarta.ee/specifications/mail/" target="_blank">Jakarta</a>/<a href="https://eclipse-ee4j.github.io/angus-mail/" target="_blank">Angus</a> Mail 084 * </li> 085 * <li> 086 * <a href="https://jakarta.ee/specifications/activation/" target="_blank">Jakarta Activation Framework</a> 087 * </li> 088 * </ul> 089 * 090 * This demo requires Java 7 or later. 091 */ 092public class SMimeV4BrainpoolDemo extends SMimeV4EccDemo { 093 094 095 /** 096 * Default constructor. 097 */ 098 public SMimeV4BrainpoolDemo() { 099 100 System.out.println(); 101 System.out.println("********************************************************************************************"); 102 System.out.println("* SMimeV4EccDemo demo *"); 103 System.out.println("* (shows how to create and parse (verify, decrypt) signed and encrypted S/MIMEv4 messages) *"); 104 System.out.println("********************************************************************************************"); 105 System.out.println(); 106 107 } 108 109 110 /** 111 * Starts the demo. 112 * 113 * @throws Exception if an error occurs 114 */ 115 public void start() throws Exception { 116 117 // get the default Session 118 Session session = DemoSMimeUtil.getSession(); 119 120 // Create a demo Multipart 121 DataHandler multipart = createMultipart(); 122 123 // get signer key and certs 124 KeyAndCertificate[] signerKeyAndCerts = { 125 // Brainpool P-224 126 new KeyAndCertificate( 127 CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, 128 CMSEccKeyStore.SZ_224_BRAINPOOL_SIGN), 129 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, 130 CMSEccKeyStore.SZ_224_BRAINPOOL_SIGN)), 131 132 // Brainpool P-256 133 new KeyAndCertificate( 134 CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, 135 CMSEccKeyStore.SZ_256_BRAINPOOL_SIGN), 136 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, 137 CMSEccKeyStore.SZ_256_BRAINPOOL_SIGN)), 138 // Brainpool P-384 139 new KeyAndCertificate( 140 CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, 141 CMSEccKeyStore.SZ_384_BRAINPOOL_SIGN), 142 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, 143 CMSEccKeyStore.SZ_384_BRAINPOOL_SIGN)), 144 // Brainpool P-512 145 new KeyAndCertificate( 146 CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, 147 CMSEccKeyStore.SZ_512_BRAINPOOL_SIGN), 148 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, 149 CMSEccKeyStore.SZ_512_BRAINPOOL_SIGN)), 150 151 }; 152 153 // the digest and signature algorithms to be used 154 AlgorithmID[][] digestAndSignatureAlgorithms = new AlgorithmID[][] { 155 { CMSAlgorithmID.sha224, CMSAlgorithmID.ecdsa_With_SHA224 }, 156 { CMSAlgorithmID.sha256, CMSAlgorithmID.ecdsa_With_SHA256 }, 157 { CMSAlgorithmID.sha384, CMSAlgorithmID.ecdsa_With_SHA384 }, 158 { CMSAlgorithmID.sha512, CMSAlgorithmID.ecdsa_With_SHA512 }, 159 }; 160 161 162 /**************************************************************************/ 163 /* */ 164 /* Signing Demo */ 165 /* */ 166 /**************************************************************************/ 167 168 final int DIGEST_ALG = 0; 169 final int SIGNATURE_ALG = 1; 170 for (int i = 0; i < digestAndSignatureAlgorithms.length; i++) { 171 AlgorithmID digestAlg = digestAndSignatureAlgorithms[i][DIGEST_ALG]; 172 AlgorithmID signatureAlg = digestAndSignatureAlgorithms[i][SIGNATURE_ALG]; 173 PrivateKey signerKey = signerKeyAndCerts[i].getPrivateKey(); 174 X509Certificate[] signerCerts = signerKeyAndCerts[i].getCertificateChain(); 175 System.out.println("Running signing demo for " + signatureAlg.getName()); 176 startSigningDemo(session, 177 multipart, 178 digestAlg, 179 signatureAlg, 180 signerKey, 181 signerCerts); 182 } 183 184 // (authenticated) encryption demos 185 186 // get recipient certs 187 X509Certificate[] recipientCerts = { 188 // Brainpool P-224 189 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH, 190 CMSEccKeyStore.SZ_224_BRAINPOOL_CRYPT_1)[0], 191 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH, 192 CMSEccKeyStore.SZ_224_BRAINPOOL_CRYPT_2)[0], 193 // Brainpool P-256 194 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH, 195 CMSEccKeyStore.SZ_256_BRAINPOOL_CRYPT_1)[0], 196 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH, 197 CMSEccKeyStore.SZ_256_BRAINPOOL_CRYPT_2)[0], 198 // Brainpool P-384 199 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH, 200 CMSEccKeyStore.SZ_384_BRAINPOOL_CRYPT_1)[0], 201 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH, 202 CMSEccKeyStore.SZ_384_BRAINPOOL_CRYPT_2)[0], 203 //Brainpool P-512 204 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH, 205 CMSEccKeyStore.SZ_512_BRAINPOOL_CRYPT_1)[0], 206 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH, 207 CMSEccKeyStore.SZ_512_BRAINPOOL_CRYPT_2)[0], 208 209 }; 210 211 // the key encryption algorithms to be used 212 AlgorithmID[] keyEAs = { 213 AlgorithmID.dhSinglePass_stdDH_sha224kdf_scheme, 214 AlgorithmID.dhSinglePass_stdDH_sha256kdf_scheme, 215 AlgorithmID.dhSinglePass_stdDH_sha384kdf_scheme, 216 AlgorithmID.dhSinglePass_stdDH_hkdf_sha256_scheme, 217 AlgorithmID.dhSinglePass_stdDH_hkdf_sha384_scheme, 218 AlgorithmID.dhSinglePass_stdDH_hkdf_sha512_scheme, 219 }; 220 // key wrap algorithms 221 AlgorithmID[] keyWrapAlgs = { 222 CMSAlgorithmID.cms_aes128_wrap, 223 CMSAlgorithmID.cms_aes192_wrap, 224 CMSAlgorithmID.cms_aes256_wrap, 225 }; 226 // whether to encrypt or authenticated encrypt 227 boolean[] doAuthEncrypt = { false, true }; 228 for (int i = 0; i < keyEAs.length; i++) { 229 AlgorithmID[] contentEAs; 230 AlgorithmID keyEA = keyEAs[i]; 231 for (int j = 0; j < keyWrapAlgs.length; j++) { 232 AlgorithmID keyWrapAlg = keyWrapAlgs[j]; 233 int kekLength; 234 int keyLength; 235 if (keyWrapAlg.equals(CMSAlgorithmID.cms_aes192_wrap)) { 236 kekLength = 192; 237 keyLength = 192; 238 contentEAs = new AlgorithmID[] { AlgorithmID.aes192_GCM, AlgorithmID.aes192_CCM }; 239 } else if (keyWrapAlg.equals(CMSAlgorithmID.cms_aes128_wrap)) { 240 kekLength = 128; 241 keyLength = 128; 242 contentEAs = new AlgorithmID[] { AlgorithmID.aes128_GCM, AlgorithmID.aes128_CCM }; 243 } else { 244 kekLength = 256; 245 keyLength = 256; 246 contentEAs = new AlgorithmID[] { AlgorithmID.aes256_GCM, AlgorithmID.aes256_CCM, AlgorithmID.chacha20Poly1305 }; 247 } 248 249 for (int k = 0; k < contentEAs.length; k++) { 250 251 /**************************************************************************/ 252 /* */ 253 /* (Authenticated) Encryption Demo */ 254 /* */ 255 /**************************************************************************/ 256 257 AlgorithmID contentEA = contentEAs[k]; 258 // in practice we may not create one message for recipients with different strength; 259 // however, for simplicity we use all recipients here 260 System.out.println("Running encryption demo for " + 261 keyEA.getName() + " with " + keyWrapAlg.getName() +" and " + contentEA.getName()); 262 startEncryptionDemo(session, 263 contentEA, 264 keyLength, 265 keyEA, 266 keyWrapAlg, 267 kekLength, 268 false, 269 recipientCerts); 270 271 272 /**************************************************************************/ 273 /* */ 274 /* Signing and (Authenticated) Encryption Demo */ 275 /* */ 276 /**************************************************************************/ 277 278 for (int l = 0; l < digestAndSignatureAlgorithms.length; l++) { 279 AlgorithmID digestAlg = digestAndSignatureAlgorithms[l][DIGEST_ALG]; 280 AlgorithmID signatureAlg = digestAndSignatureAlgorithms[l][SIGNATURE_ALG]; 281 PrivateKey signerKey = signerKeyAndCerts[l].getPrivateKey(); 282 X509Certificate[] signerCerts = signerKeyAndCerts[l].getCertificateChain(); 283 System.out.println("Running signing and encryption and demo for " + signatureAlg.getName()); 284 startSigningAndEncryptionDemo(session, 285 multipart, 286 digestAlg, 287 signatureAlg, 288 contentEA, 289 keyLength, 290 keyEA, 291 keyWrapAlg, 292 kekLength, 293 false, 294 signerKey, 295 signerCerts, 296 recipientCerts); 297 } 298 } 299 } 300 } 301 302 } 303 304 /** 305 * The main method. 306 */ 307 public static void main(String[] argv) throws Exception { 308 309 String jdkVersion = (String) System.getProperty("java.version"); 310 if (jdkVersion.compareTo("1.7") >= 0) { 311 DemoSMimeUtil.initDemos(); 312 // add ECC provider 313 ECCDemoUtil.installIaikEccProvider(); 314 315 (new SMimeV4BrainpoolDemo()).start(); 316 System.out.println("\nReady!"); 317 } else { 318 System.err.println("This demo requires Java 7 or later!"); 319 } 320 DemoUtil.waitKey(); 321 } 322}