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/keystore/CMSKeyStore.java 29 12.02.25 17:58 Dbratko $ 059 // $Revision: 29 $ 060 // 061 062 package demo.keystore; 063 064 import iaik.cms.CertificateIdentifier; 065 import iaik.cms.KeyIdentifier; 066 import iaik.cms.SecurityProvider; 067 import iaik.smime.ess.utils.KeyStoreDatabase; 068 import iaik.utils.Util; 069 import iaik.x509.X509Certificate; 070 071 import java.io.File; 072 import java.io.FileInputStream; 073 import java.security.KeyStore; 074 import java.security.PrivateKey; 075 076 /** 077 * KeyStore repository used providing keys and certificates 078 * for the several CMS and S/MIME demos. 079 * <p> 080 * Reads and loads keys and certificates from an IaikKeyStore 081 * files and provides methods to access the keys and certificates 082 * based on algorithm name and algorithm type. 083 */ 084 public class CMSKeyStore implements CMSKeyStoreConstants { 085 086 /** 087 * Certificates. 088 */ 089 public static Object[][] certificates = new Object[5][12]; 090 /** 091 * Keys. 092 */ 093 public static PrivateKey[][] keys = new PrivateKey[5][12]; 094 /** 095 * Ca certificates. 096 */ 097 public static X509Certificate[] ca_certificates = new X509Certificate[3]; 098 /** 099 * Ca keys. 100 */ 101 public static PrivateKey[] ca_keys = new PrivateKey[3]; 102 103 /** 104 * Repository holding keys and certificates by their corresponding (certificate) ids. 105 * Used by class {@link demo.smime.DumpMessage DempMessgae} to search for recipient 106 * keys/certificates based on their recipient key (certificate) ids. 107 * For simplicity we use the {@link iaik.smime.ess.utils.KeyStoreDatabase KeyStoreDatabase} 108 * utility. 109 */ 110 private static KeyStoreDatabase recipientKeys_ = new KeyStoreDatabase(); 111 112 /** 113 * Adds a key and certificate by its key (certificate) ids to the given recipient keys/certs repositories. 114 * 115 * @param recipientKey the recipient key to be added 116 * @param recipientCertChain the recipient certificate chain 117 * 118 */ 119 public static void addRecipientKey(PrivateKey recipientKey, X509Certificate[] recipientCertChain) { 120 121 try { 122 recipientKeys_.addKey(recipientKey, recipientCertChain, null); 123 } catch (Exception e) { 124 System.err.println("Cannot add recipient key for " + recipientCertChain[0].getSubjectDN() + " " + e.toString()); 125 } 126 127 } 128 129 /** 130 * Gets a recipient key by the given key (certificate) id. 131 * 132 * @param keyId the key identifier 133 * 134 * @return the recipient key or <code>null</code> if no key for the given id can be found 135 * 136 */ 137 public static PrivateKey getRecipientKey(KeyIdentifier keyId) { 138 139 PrivateKey key = null; 140 try { 141 key = (PrivateKey)recipientKeys_.getKey(keyId); 142 } catch (Exception e) { 143 // ignore 144 } 145 return key; 146 147 } 148 149 /** 150 * Gets a recipient cert by the given certificate id from the given recipient certs repository. 151 * 152 * @param certId the certificate identifier 153 * 154 * @return the recipient cert or <code>null</code> if no cert for the given id can be found 155 * 156 */ 157 public static X509Certificate getRecipientCert(CertificateIdentifier certId) { 158 X509Certificate cert = null; 159 try { 160 cert = recipientKeys_.getCertificate(certId); 161 } catch (Exception e) { 162 // ignore 163 } 164 return cert; 165 } 166 167 /** 168 * Indices into the cert/key tables 169 */ 170 public final static int RSA = 0; 171 public final static int DSA = 1; 172 public final static int RSAPSS = 2; 173 public final static int ESDH = 3; 174 public final static int SSDH = 4; 175 176 177 public final static int SZ_1024_SIGN = 0; 178 public final static int SZ_2048_SIGN_1 = 1; 179 public final static int SZ_2048_SIGN_2 = 2; 180 public final static int SZ_2048_SIGN_3 = 3; 181 public final static int SZ_3072_SIGN = 4; 182 public final static int SZ_2048_CRYPT_1 = 5; 183 public final static int SZ_2048_CRYPT_2 = 6; 184 public final static int SZ_2048_CRYPT_3 = 7; 185 public final static int SZ_2048_SHA1_SIGN = 8; 186 public final static int SZ_2048_SHA256_SIGN = 9; 187 public final static int SZ_2048_SHA384_SIGN = 10; 188 public final static int SZ_2048_SHA512_SIGN = 11; 189 190 /** 191 * Certificate chain of demo time stamp server. 192 */ 193 static X509Certificate[] tsp_server_certs; 194 195 /** 196 * Key of demo time stamp server. 197 */ 198 static PrivateKey tsp_server_key; 199 200 /** 201 * Keystore. 202 */ 203 static KeyStore key_store; 204 205 /** 206 * The KeyStore file name. 207 */ 208 public static String ks_filename = KS_FILENAME; 209 210 211 212 /** 213 * Loads and inits keystore. 214 */ 215 static { 216 System.out.println("initializing KeyStore..."); 217 loadKeyStore(); 218 initKeyStore(); 219 System.out.println(); 220 } 221 222 /** 223 * Loads the keystore from the file ("cms.keystore"). 224 */ 225 private static void loadKeyStore() { 226 227 boolean createKeyStore = false; 228 // try to locate the KeyStore 229 // first check the current working directory 230 File ks = new File(KS_DIRECTORY, ks_filename); 231 if (!ks.exists()) { 232 createKeyStore = true; 233 // called from demo batch file (try parent directory) 234 File ksDir = new File(KS_DIRECTORY); 235 if (ksDir.exists()) { 236 String parentDir = ksDir.getParent(); 237 String pDir = parentDir.toLowerCase(); 238 if ((pDir.endsWith("cms")) || (pDir.endsWith("smime")) || 239 (pDir.endsWith("cmd")) || (pDir.endsWith("sh"))) { 240 File ksParent = new File(parentDir, ks_filename); 241 if (ksParent.exists()) { 242 ks = ksParent; 243 createKeyStore = false; 244 } 245 } 246 } 247 if (createKeyStore) { 248 // keystore does not exist ==> create new one 249 System.out.println(); 250 System.out.println(); 251 System.out.println("Can not find the KeyStore " + ks_filename + " in directory:"); 252 System.out.println(ks.getAbsolutePath()); 253 System.out.println("Generating key store!"); 254 try { 255 SetupCMSKeyStore.main(new String[] {}); 256 } catch (Exception ex) { 257 System.out.println("Unable to create KeyStore!"); 258 ex.printStackTrace(); 259 demo.DemoUtil.waitKey(); 260 System.exit(1); 261 } 262 } 263 } 264 265 FileInputStream fis = null; 266 // now try to create and load the KeyStore 267 try { 268 fis = new FileInputStream(ks); 269 key_store = SecurityProvider.getSecurityProvider().getKeyStore("IAIKKeyStore"); 270 key_store.load(fis, KS_PASSWORD); 271 fis.close(); 272 } catch (Exception ex) { 273 System.out.println("Unable to load KeyStore!"); 274 ex.printStackTrace(); 275 if (fis != null) { 276 try { 277 fis.close(); 278 } catch (Exception e) { 279 // ignore 280 } 281 } 282 demo.DemoUtil.waitKey(); 283 System.exit(1); 284 } 285 286 } 287 288 /** 289 * Initializes the keystore. 290 */ 291 public static void initKeyStore() { 292 293 try { 294 ca_certificates[RSA] = Util.convertCertificateChain(key_store.getCertificateChain(CA_RSA))[0]; 295 ca_keys[RSA] = (PrivateKey)key_store.getKey(CA_RSA, KS_PASSWORD); 296 ca_keys[RSAPSS] = (PrivateKey)key_store.getKey(CA_RSAPSS, KS_PASSWORD); 297 298 // RSA for signing 299 certificates[RSA][SZ_2048_SIGN_1] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_2048_SIGN_1)); 300 keys[RSA][SZ_2048_SIGN_1] = (PrivateKey)key_store.getKey(RSA_2048_SIGN_1, KS_PASSWORD); 301 certificates[RSA][SZ_2048_SIGN_2] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_2048_SIGN_2)); 302 keys[RSA][SZ_2048_SIGN_2] = (PrivateKey)key_store.getKey(RSA_2048_SIGN_2, KS_PASSWORD); 303 certificates[RSA][SZ_2048_SIGN_3] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_2048_SIGN_3)); 304 keys[RSA][SZ_2048_SIGN_3] = (PrivateKey)key_store.getKey(RSA_2048_SIGN_3, KS_PASSWORD); 305 // RSA for encrypting 306 certificates[RSA][SZ_2048_CRYPT_1] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_2048_CRYPT_1)); 307 keys[RSA][SZ_2048_CRYPT_1] = (PrivateKey)key_store.getKey(RSA_2048_CRYPT_1, KS_PASSWORD); 308 addRecipientKey(keys[RSA][SZ_2048_CRYPT_1], ((X509Certificate[])certificates[RSA][SZ_2048_CRYPT_1])); 309 certificates[RSA][SZ_2048_CRYPT_2] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_2048_CRYPT_2)); 310 keys[RSA][SZ_2048_CRYPT_2] = (PrivateKey)key_store.getKey(RSA_2048_CRYPT_2, KS_PASSWORD); 311 addRecipientKey(keys[RSA][SZ_2048_CRYPT_2], ((X509Certificate[])certificates[RSA][SZ_2048_CRYPT_2])); 312 certificates[RSA][SZ_2048_CRYPT_3] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_2048_CRYPT_3)); 313 keys[RSA][SZ_2048_CRYPT_3] = (PrivateKey)key_store.getKey(RSA_2048_CRYPT_3, KS_PASSWORD); 314 addRecipientKey(keys[RSA][SZ_2048_CRYPT_3], ((X509Certificate[])certificates[RSA][SZ_2048_CRYPT_3])); 315 } catch (Exception ex) { 316 System.out.println("RSA certificates not loaded: " + ex.getMessage()); 317 // ex.printStackTrace(); 318 } 319 320 try { 321 ca_certificates[DSA] = Util.convertCertificateChain(key_store.getCertificateChain(CA_DSA))[0]; 322 ca_keys[DSA] = (PrivateKey)key_store.getKey(CA_DSA, KS_PASSWORD); 323 certificates[DSA][SZ_1024_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(DSA_1024)); 324 keys[DSA][SZ_1024_SIGN] = (PrivateKey)key_store.getKey(DSA_1024, KS_PASSWORD); 325 } catch (Exception ex) { 326 System.out.println("DSA certificates not loaded: " + ex.getMessage()); 327 // ex.printStackTrace(); 328 } 329 330 try { 331 certificates[DSA][SZ_2048_SIGN_1] = Util.convertCertificateChain(key_store.getCertificateChain(DSA_2048)); 332 keys[DSA][SZ_2048_SIGN_1] = (PrivateKey)key_store.getKey(DSA_2048, KS_PASSWORD); 333 certificates[DSA][SZ_2048_SIGN_2] = Util.convertCertificateChain(key_store.getCertificateChain(DSA_2048)); 334 keys[DSA][SZ_2048_SIGN_2] = (PrivateKey)key_store.getKey(DSA_2048, KS_PASSWORD); 335 certificates[DSA][SZ_3072_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(DSA_3072)); 336 keys[DSA][SZ_3072_SIGN] = (PrivateKey)key_store.getKey(DSA_3072, KS_PASSWORD); 337 } catch (Exception ex) { 338 System.out.println("Unable to get DSA SHA-2 certificate from KeyStore: " + ex.getMessage()); 339 } 340 341 try { 342 certificates[ESDH][SZ_2048_CRYPT_1] = Util.convertCertificateChain(key_store.getCertificateChain(ESDH_2048_1)); 343 keys[ESDH][SZ_2048_CRYPT_1] = (PrivateKey)key_store.getKey(ESDH_2048_1, KS_PASSWORD); 344 addRecipientKey(keys[ESDH][SZ_2048_CRYPT_1], ((X509Certificate[])certificates[ESDH][SZ_2048_CRYPT_1])); 345 certificates[ESDH][SZ_2048_CRYPT_2] = Util.convertCertificateChain(key_store.getCertificateChain(ESDH_2048_2)); 346 keys[ESDH][SZ_2048_CRYPT_2] = (PrivateKey)key_store.getKey(ESDH_2048_2, KS_PASSWORD); 347 addRecipientKey(keys[ESDH][SZ_2048_CRYPT_2], ((X509Certificate[])certificates[ESDH][SZ_2048_CRYPT_2])); 348 certificates[SSDH][SZ_2048_CRYPT_1] = Util.convertCertificateChain(key_store.getCertificateChain(SSDH_2048_1)); 349 keys[SSDH][SZ_2048_CRYPT_1] = (PrivateKey)key_store.getKey(SSDH_2048_1, KS_PASSWORD); 350 addRecipientKey(keys[SSDH][SZ_2048_CRYPT_1], ((X509Certificate[])certificates[SSDH][SZ_2048_CRYPT_1])); 351 certificates[SSDH][SZ_2048_CRYPT_2] = Util.convertCertificateChain(key_store.getCertificateChain(SSDH_2048_2)); 352 keys[SSDH][SZ_2048_CRYPT_2] = (PrivateKey)key_store.getKey(SSDH_2048_2, KS_PASSWORD); 353 addRecipientKey(keys[SSDH][SZ_2048_CRYPT_2], ((X509Certificate[])certificates[SSDH][SZ_2048_CRYPT_2])); 354 } catch (Exception ex) { 355 System.out.println("Diffie-Hellman certificates not loaded: " + ex.getMessage()); 356 // ex.printStackTrace(); 357 } 358 359 // TSP server cert 360 try { 361 tsp_server_certs = Util.convertCertificateChain(key_store.getCertificateChain(TSP_SERVER)); 362 tsp_server_key = (PrivateKey)key_store.getKey(TSP_SERVER, KS_PASSWORD); 363 } catch (Exception ex) { 364 System.out.println("TSP server certificate not loaded: " + ex.getMessage()); 365 // ex.printStackTrace(); 366 } 367 368 // RSA-PSS 369 try { 370 371 ca_certificates[RSAPSS] = Util.convertCertificateChain(key_store.getCertificateChain(CA_RSAPSS))[0]; 372 ca_keys[RSAPSS] = (PrivateKey)key_store.getKey(CA_RSAPSS, KS_PASSWORD); 373 374 certificates[RSAPSS][SZ_2048_SHA1_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(RSAPSS_2048_SHA1_SIGN)); 375 keys[RSAPSS][SZ_2048_SHA1_SIGN] = (PrivateKey)key_store.getKey(RSAPSS_2048_SHA1_SIGN, KS_PASSWORD); 376 certificates[RSAPSS][SZ_2048_SHA256_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(RSAPSS_2048_SHA256_SIGN)); 377 keys[RSAPSS][SZ_2048_SHA256_SIGN] = (PrivateKey)key_store.getKey(RSAPSS_2048_SHA256_SIGN, KS_PASSWORD); 378 certificates[RSAPSS][SZ_2048_SHA384_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(RSAPSS_2048_SHA384_SIGN)); 379 keys[RSAPSS][SZ_2048_SHA384_SIGN] = (PrivateKey)key_store.getKey(RSAPSS_2048_SHA384_SIGN, KS_PASSWORD); 380 certificates[RSAPSS][SZ_2048_SHA512_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(RSAPSS_2048_SHA512_SIGN)); 381 keys[RSAPSS][SZ_2048_SHA512_SIGN] = (PrivateKey)key_store.getKey(RSAPSS_2048_SHA512_SIGN, KS_PASSWORD); 382 383 384 } catch (Exception ex) { 385 System.out.println("RSA-PSS certificates not loaded: " + ex.getMessage()); 386 // ex.printStackTrace(); 387 } 388 389 } 390 391 /** 392 * Returns the private key of a CA certificate. 393 * 394 * @param type {@link #RSA RSA} or {@link #DSA DSA} or {@link #ESDH ESDH} 395 * @param size the key size 396 * 397 * @return the key 398 */ 399 public static PrivateKey getPrivateKey(int type, int size) { 400 try { 401 return keys[type][size]; 402 } catch (ArrayIndexOutOfBoundsException ex) { 403 throw new RuntimeException("Wrong type or size!"); 404 } 405 } 406 407 /** 408 * Returns a demo user certificate. 409 * 410 * @param type {@link #RSA RSA} or {@link #DSA DSA} or {@link #ESDH ESDH} or {@link #SSDH SSDH} 411 * @param size the size of the corresponding key 412 * 413 * @return the certificate chain 414 */ 415 public static X509Certificate[] getCertificateChain(int type, int size) { 416 try { 417 return (X509Certificate[])certificates[type][size]; 418 } catch (ArrayIndexOutOfBoundsException ex) { 419 throw new RuntimeException("Wrong type or size!"); 420 } 421 } 422 423 /** 424 * Returns the private key of a CA certificate. 425 * 426 * @param type {@link #RSA RSA} or {@link #DSA DSA} 427 * 428 * @return the key 429 */ 430 public static PrivateKey getCaPrivateKey(int type) { 431 try { 432 return ca_keys[type]; 433 } catch (ArrayIndexOutOfBoundsException ex) { 434 throw new RuntimeException("Wrong type or size!"); 435 } 436 } 437 438 /** 439 * Returns a demo CA certificate. 440 * 441 * @param type {@link #RSA RSA} or {@link #DSA DSA} 442 * 443 * @return the ca certificate 444 */ 445 public static X509Certificate getCaCertificate(int type) { 446 try { 447 return ca_certificates[type]; 448 } catch (ArrayIndexOutOfBoundsException ex) { 449 throw new RuntimeException("Wrong type or size!"); 450 } 451 } 452 453 /** 454 * Returns the private key of the TSP demo server. 455 * 456 * @return the key 457 */ 458 public static PrivateKey getTspServerPrivateKey() { 459 return tsp_server_key; 460 } 461 462 /** 463 * Returns the certificate chain of the TSP demo server. 464 * 465 * @return the tsp server certificate 466 */ 467 public static X509Certificate[] getTspServerCertificate() { 468 return tsp_server_certs; 469 } 470 471 472 }