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/ecc/SMimeV4BrainpoolDemo.java 3 12.02.25 17:59 Dbratko $
059 // $Revision: 3 $
060 //
061
062 package demo.smime.ecc;
063
064 import java.security.PrivateKey;
065
066 import javax.activation.DataHandler;
067 import javax.mail.Session;
068
069 import demo.DemoSMimeUtil;
070 import demo.DemoUtil;
071 import demo.cms.ecc.ECCDemoUtil;
072 import demo.cms.ecc.keystore.CMSEccKeyStore;
073 import iaik.asn1.structures.AlgorithmID;
074 import iaik.cms.CMSAlgorithmID;
075 import iaik.utils.KeyAndCertificate;
076 import iaik.x509.X509Certificate;
077
078 /**
079 * This class demonstrates the usage of the IAIK S/MIME implementation. It shows how to create
080 * signed and/or (authenticated) encrypted S/MIMEv4 messages using ECC keys with Berainpool curves
081 * and how to parse them and verify the signatures and decrypt the content, respectively.
082 * <p>
083 * Although Brainpool curves may not be widely used with S/MIME applications they are, e.g., recommended
084 * by the German Federal Office for Information Security (BSI) for their Technical Guideline BSI TR-03116
085 * defining cryptographic requirements for projects of the Federal Government.
086 * Note that whereas S/MIME in general uses AEAD cipher modes like GCM with the <code>AuthEnvelopedData</code>
087 * content type, BSI TR-03116 specifies GCM for use with the <code>EnvelopedData</code> type. For that
088 * reason GCM is used with <code>EnvelopedData</code> in this demo (in difference to the parent
089 * {@link SMimeV4EccDemo SMimeV4EccDemo} which uses GCM with the <code>AuthEnvelopedData</code> type.
090 *
091 * <p>
092 * Additionally to <code>iaik_cms.jar</code> you also must have
093 * <code>iaik_jce_(full).jar</code> (IAIK-JCE, <a href =
094 * "https://sic.tech/products/core-crypto-toolkits/jca-jce/" target="_blank">
095 * https://sic.tech/products/core-crypto-toolkits/jca-jce/</a>),
096 * and <code>iaik_eccelarate.jar</code> (IAIK-ECCelerate<sup><small>TM</small></sup>, <a href =
097 * "https://sic.tech/products/core-crypto-toolkits/eccelerate/" target="_blank">
098 * https://sic.tech/products/core-crypto-toolkits/eccelerate/</a>)
099 * in your classpath.
100 * <p>
101 * To run this demo the following packages are required:
102 * <ul>
103 * <li>
104 * <code>iaik_cms.jar</code>
105 * </li>
106 * <li>
107 * <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>).
108 * </li>
109 * <li>
110 * <code>iaik_eccelerate.jar</code> (<a href="https://sic.tech/products/core-crypto-toolkits/eccelerate/" target="_blank">IAIK ECC Library</a>).
111 * </li>
112 * <li>
113 * <code>mail.jar</code> (<a href="http://www.oracle.com/technetwork/java/javamail/index.html" target="_blank">JavaMail API</a>).
114 * </li>
115 * <li>
116 * <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).
117 * </li>
118 * </ul>
119 *
120 * This demo requires Java 7 or later.
121 */
122 public class SMimeV4BrainpoolDemo extends SMimeV4EccDemo {
123
124
125 /**
126 * Default constructor.
127 */
128 public SMimeV4BrainpoolDemo() {
129
130 System.out.println();
131 System.out.println("********************************************************************************************");
132 System.out.println("* SMimeV4EccDemo demo *");
133 System.out.println("* (shows how to create and parse (verify, decrypt) signed and encrypted S/MIMEv4 messages) *");
134 System.out.println("********************************************************************************************");
135 System.out.println();
136
137 }
138
139
140 /**
141 * Starts the demo.
142 *
143 * @throws Exception if an error occurs
144 */
145 public void start() throws Exception {
146
147 // get the default Session
148 Session session = DemoSMimeUtil.getSession();
149
150 // Create a demo Multipart
151 DataHandler multipart = createMultipart();
152
153 // get signer key and certs
154 KeyAndCertificate[] signerKeyAndCerts = {
155 // Brainpool P-224
156 new KeyAndCertificate(
157 CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA,
158 CMSEccKeyStore.SZ_224_BRAINPOOL_SIGN),
159 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA,
160 CMSEccKeyStore.SZ_224_BRAINPOOL_SIGN)),
161
162 // Brainpool P-256
163 new KeyAndCertificate(
164 CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA,
165 CMSEccKeyStore.SZ_256_BRAINPOOL_SIGN),
166 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA,
167 CMSEccKeyStore.SZ_256_BRAINPOOL_SIGN)),
168 // Brainpool P-384
169 new KeyAndCertificate(
170 CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA,
171 CMSEccKeyStore.SZ_384_BRAINPOOL_SIGN),
172 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA,
173 CMSEccKeyStore.SZ_384_BRAINPOOL_SIGN)),
174 // Brainpool P-512
175 new KeyAndCertificate(
176 CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA,
177 CMSEccKeyStore.SZ_512_BRAINPOOL_SIGN),
178 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA,
179 CMSEccKeyStore.SZ_512_BRAINPOOL_SIGN)),
180
181 };
182
183 // the digest and signature algorithms to be used
184 AlgorithmID[][] digestAndSignatureAlgorithms = new AlgorithmID[][] {
185 { CMSAlgorithmID.sha224, CMSAlgorithmID.ecdsa_With_SHA224 },
186 { CMSAlgorithmID.sha256, CMSAlgorithmID.ecdsa_With_SHA256 },
187 { CMSAlgorithmID.sha384, CMSAlgorithmID.ecdsa_With_SHA384 },
188 { CMSAlgorithmID.sha512, CMSAlgorithmID.ecdsa_With_SHA512 },
189 };
190
191
192 /**************************************************************************/
193 /* */
194 /* Signing Demo */
195 /* */
196 /**************************************************************************/
197
198 final int DIGEST_ALG = 0;
199 final int SIGNATURE_ALG = 1;
200 for (int i = 0; i < digestAndSignatureAlgorithms.length; i++) {
201 AlgorithmID digestAlg = digestAndSignatureAlgorithms[i][DIGEST_ALG];
202 AlgorithmID signatureAlg = digestAndSignatureAlgorithms[i][SIGNATURE_ALG];
203 PrivateKey signerKey = signerKeyAndCerts[i].getPrivateKey();
204 X509Certificate[] signerCerts = signerKeyAndCerts[i].getCertificateChain();
205 System.out.println("Running signing demo for " + signatureAlg.getName());
206 startSigningDemo(session,
207 multipart,
208 digestAlg,
209 signatureAlg,
210 signerKey,
211 signerCerts);
212 }
213
214 // (authenticated) encryption demos
215
216 // get recipient certs
217 X509Certificate[] recipientCerts = {
218 // Brainpool P-224
219 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
220 CMSEccKeyStore.SZ_224_BRAINPOOL_CRYPT_1)[0],
221 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
222 CMSEccKeyStore.SZ_224_BRAINPOOL_CRYPT_2)[0],
223 // Brainpool P-256
224 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
225 CMSEccKeyStore.SZ_256_BRAINPOOL_CRYPT_1)[0],
226 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
227 CMSEccKeyStore.SZ_256_BRAINPOOL_CRYPT_2)[0],
228 // Brainpool P-384
229 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
230 CMSEccKeyStore.SZ_384_BRAINPOOL_CRYPT_1)[0],
231 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
232 CMSEccKeyStore.SZ_384_BRAINPOOL_CRYPT_2)[0],
233 //Brainpool P-512
234 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
235 CMSEccKeyStore.SZ_512_BRAINPOOL_CRYPT_1)[0],
236 CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDH,
237 CMSEccKeyStore.SZ_512_BRAINPOOL_CRYPT_2)[0],
238
239 };
240
241 // the key encryption algorithms to be used
242 AlgorithmID[] keyEAs = {
243 AlgorithmID.dhSinglePass_stdDH_sha224kdf_scheme,
244 AlgorithmID.dhSinglePass_stdDH_sha256kdf_scheme,
245 AlgorithmID.dhSinglePass_stdDH_sha384kdf_scheme,
246 AlgorithmID.dhSinglePass_stdDH_hkdf_sha256_scheme,
247 AlgorithmID.dhSinglePass_stdDH_hkdf_sha384_scheme,
248 AlgorithmID.dhSinglePass_stdDH_hkdf_sha512_scheme,
249 };
250 // key wrap algorithms
251 AlgorithmID[] keyWrapAlgs = {
252 CMSAlgorithmID.cms_aes128_wrap,
253 CMSAlgorithmID.cms_aes192_wrap,
254 CMSAlgorithmID.cms_aes256_wrap,
255 };
256 // whether to encrypt or authenticated encrypt
257 boolean[] doAuthEncrypt = { false, true };
258 for (int i = 0; i < keyEAs.length; i++) {
259 AlgorithmID[] contentEAs;
260 AlgorithmID keyEA = keyEAs[i];
261 for (int j = 0; j < keyWrapAlgs.length; j++) {
262 AlgorithmID keyWrapAlg = keyWrapAlgs[j];
263 int kekLength;
264 int keyLength;
265 if (keyWrapAlg.equals(CMSAlgorithmID.cms_aes192_wrap)) {
266 kekLength = 192;
267 keyLength = 192;
268 contentEAs = new AlgorithmID[] { AlgorithmID.aes192_GCM, AlgorithmID.aes192_CCM };
269 } else if (keyWrapAlg.equals(CMSAlgorithmID.cms_aes128_wrap)) {
270 kekLength = 128;
271 keyLength = 128;
272 contentEAs = new AlgorithmID[] { AlgorithmID.aes128_GCM, AlgorithmID.aes128_CCM };
273 } else {
274 kekLength = 256;
275 keyLength = 256;
276 contentEAs = new AlgorithmID[] { AlgorithmID.aes256_GCM, AlgorithmID.aes256_CCM, AlgorithmID.chacha20Poly1305 };
277 }
278
279 for (int k = 0; k < contentEAs.length; k++) {
280
281 /**************************************************************************/
282 /* */
283 /* (Authenticated) Encryption Demo */
284 /* */
285 /**************************************************************************/
286
287 AlgorithmID contentEA = contentEAs[k];
288 // in practice we may not create one message for recipients with different strength;
289 // however, for simplicity we use all recipients here
290 System.out.println("Running encryption demo for " +
291 keyEA.getName() + " with " + keyWrapAlg.getName() +" and " + contentEA.getName());
292 startEncryptionDemo(session,
293 contentEA,
294 keyLength,
295 keyEA,
296 keyWrapAlg,
297 kekLength,
298 false,
299 recipientCerts);
300
301
302 /**************************************************************************/
303 /* */
304 /* Signing and (Authenticated) Encryption Demo */
305 /* */
306 /**************************************************************************/
307
308 for (int l = 0; l < digestAndSignatureAlgorithms.length; l++) {
309 AlgorithmID digestAlg = digestAndSignatureAlgorithms[l][DIGEST_ALG];
310 AlgorithmID signatureAlg = digestAndSignatureAlgorithms[l][SIGNATURE_ALG];
311 PrivateKey signerKey = signerKeyAndCerts[l].getPrivateKey();
312 X509Certificate[] signerCerts = signerKeyAndCerts[l].getCertificateChain();
313 System.out.println("Running signing and encryption and demo for " + signatureAlg.getName());
314 startSigningAndEncryptionDemo(session,
315 multipart,
316 digestAlg,
317 signatureAlg,
318 contentEA,
319 keyLength,
320 keyEA,
321 keyWrapAlg,
322 kekLength,
323 false,
324 signerKey,
325 signerCerts,
326 recipientCerts);
327 }
328 }
329 }
330 }
331
332 }
333
334 /**
335 * The main method.
336 */
337 public static void main(String[] argv) throws Exception {
338
339 String jdkVersion = (String) System.getProperty("java.version");
340 if (jdkVersion.compareTo("1.7") >= 0) {
341 DemoSMimeUtil.initDemos();
342 // add ECC provider
343 ECCDemoUtil.installIaikEccProvider();
344
345 (new SMimeV4BrainpoolDemo()).start();
346 System.out.println("\nReady!");
347 } else {
348 System.err.println("This demo requires Java 7 or later!");
349 }
350 DemoUtil.waitKey();
351 }
352 }