277 lines
10 KiB
Java
277 lines
10 KiB
Java
/* WolfSSLKeyStoreExample.java
|
|
*
|
|
* Copyright (C) 2006-2025 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSL.
|
|
*
|
|
* wolfSSL is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfSSL is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.FileNotFoundException;
|
|
import java.nio.file.Files;
|
|
import java.security.NoSuchAlgorithmException;
|
|
import java.security.Provider;
|
|
import java.security.Security;
|
|
import java.security.SecureRandom;
|
|
import java.security.KeyStore;
|
|
import java.security.PrivateKey;
|
|
import java.security.KeyFactory;
|
|
import java.security.KeyStoreException;
|
|
import java.security.cert.Certificate;
|
|
import java.security.cert.CertificateFactory;
|
|
import java.security.cert.CertificateException;
|
|
import java.security.spec.PKCS8EncodedKeySpec;
|
|
import java.security.spec.InvalidKeySpecException;
|
|
import javax.crypto.KeyGenerator;
|
|
import javax.crypto.SecretKey;
|
|
|
|
import com.wolfssl.provider.jce.WolfCryptProvider;
|
|
|
|
public class WolfSSLKeyStoreExample {
|
|
|
|
/* KeyStore password */
|
|
static String storePass = "wolfsslpassword";
|
|
|
|
/* KeyStore output file */
|
|
static String wksFile = "wolfssl.wks";
|
|
|
|
/* KeyStore type */
|
|
static String storeType = "WKS";
|
|
|
|
/* RSA server cert and private key */
|
|
static String serverCertRsaDer = "../../certs/server-cert.der";
|
|
static String serverRsaPkcs8Der = "../../certs/server-keyPkcs8.der";
|
|
|
|
/* ECC server cert and private key */
|
|
static String serverCertEccDer = "../../certs/server-ecc.der";
|
|
static String serverEccPkcs8Der = "../../certs/ecc-keyPkcs8.der";
|
|
|
|
/* RSA server cert chain */
|
|
static String intRsaServerCertDer =
|
|
"../../certs/intermediate/server-int-cert.pem";
|
|
static String intRsaInt1CertDer =
|
|
"../../certs/intermediate/ca-int-cert.pem";
|
|
static String intRsaInt2CertDer =
|
|
"../../certs/intermediate/ca-int2-cert.pem";
|
|
|
|
/* ECC server cert chain */
|
|
static String intEccServerCertDer =
|
|
"../../certs/intermediate/server-int-ecc-cert.der";
|
|
static String intEccInt1CertDer =
|
|
"../../certs/intermediate/ca-int-ecc-cert.der";
|
|
static String intEccInt2CertDer =
|
|
"../../certs/intermediate/ca-int2-ecc-cert.der";
|
|
|
|
/**
|
|
* Create and return PrivateKey object from file path to DER-encoded
|
|
* private key file.
|
|
*
|
|
* @param derFilePath file path to DER-encoded PKCS#8 private key file
|
|
* @param alg algorithm for KeyFactory instance (ex: "RSA", "EC")
|
|
*
|
|
* @return PrivateKey object created from file path given
|
|
*
|
|
* @throws IllegalArgumentException on bad argument or processing of arg
|
|
* @throws IOException on error converting File to Path
|
|
* @throws NoSuchAlgorithmException on bad "alg" when getting KeyFactory
|
|
* @throws InvalidKeySpecException on error generating PrivateKey object
|
|
* @throws Exception on other error
|
|
*/
|
|
private static PrivateKey DerFileToPrivateKey(String derFilePath,
|
|
String alg) throws IllegalArgumentException, IOException,
|
|
NoSuchAlgorithmException, InvalidKeySpecException,
|
|
InvalidKeySpecException {
|
|
|
|
byte[] fileBytes = null;
|
|
PKCS8EncodedKeySpec spec = null;
|
|
KeyFactory kf = null;
|
|
PrivateKey key = null;
|
|
|
|
if (derFilePath == null || derFilePath.isEmpty()) {
|
|
throw new IllegalArgumentException(
|
|
"Input DER file path is null or empty");
|
|
}
|
|
|
|
fileBytes = Files.readAllBytes(new File(derFilePath).toPath());
|
|
if (fileBytes == null || fileBytes.length == 0) {
|
|
throw new IllegalArgumentException(
|
|
"Bytes read from DER file is null or empty, bad file path?");
|
|
}
|
|
|
|
spec = new PKCS8EncodedKeySpec(fileBytes);
|
|
if (spec == null) {
|
|
throw new InvalidKeySpecException(
|
|
"Unable to create PKCS8EncodedKeySpec");
|
|
}
|
|
|
|
kf = KeyFactory.getInstance(alg);
|
|
key = kf.generatePrivate(spec);
|
|
|
|
return key;
|
|
}
|
|
|
|
/**
|
|
* Read in and convert certificate file to Certificate object.
|
|
*
|
|
* @param certPath path to DER-encoded certificate file
|
|
*
|
|
* @return new Certificate object representing certPath file
|
|
*
|
|
* @throws FileNotFoundException on error reading certPath file
|
|
* @throws CertificateException on error geting CertificateFactory or
|
|
* generating Certificate object
|
|
*/
|
|
private static Certificate CertFileToCertificate(String certPath)
|
|
throws FileNotFoundException, CertificateException {
|
|
|
|
CertificateFactory cf = null;
|
|
Certificate cert = null;
|
|
|
|
cf = CertificateFactory.getInstance("X.509");
|
|
cert = cf.generateCertificate(new FileInputStream(certPath));
|
|
|
|
return cert;
|
|
}
|
|
|
|
public static void InsertKeyStoreEntries(KeyStore store)
|
|
throws FileNotFoundException, KeyStoreException, IOException,
|
|
CertificateException, NoSuchAlgorithmException,
|
|
InvalidKeySpecException {
|
|
|
|
byte[] fileBytes = null;
|
|
PrivateKey privKey = null;
|
|
Certificate cert = null;
|
|
Certificate[] chain = null;
|
|
KeyGenerator kg = null;
|
|
SecretKey aesKey = null;
|
|
|
|
/* INSERT [1]: RSA cert only */
|
|
cert = CertFileToCertificate(serverCertRsaDer);
|
|
store.setCertificateEntry("serverRsa", cert);
|
|
|
|
/* INSERT [2]: RSA priv key + single cert */
|
|
privKey = DerFileToPrivateKey(serverRsaPkcs8Der, "RSA");
|
|
store.setKeyEntry("rsaCert", privKey,
|
|
storePass.toCharArray(), new Certificate[] { cert });
|
|
|
|
/* INSERT [5]: RSA priv key + cert chain */
|
|
chain = new Certificate[3];
|
|
cert = CertFileToCertificate(intRsaServerCertDer);
|
|
chain[0] = cert;
|
|
cert = CertFileToCertificate(intRsaInt2CertDer);
|
|
chain[1] = cert;
|
|
cert = CertFileToCertificate(intRsaInt1CertDer);
|
|
chain[2] = cert;
|
|
store.setKeyEntry("rsaChain", privKey, storePass.toCharArray(), chain);
|
|
|
|
/* INSERT [3]: ECC cert only */
|
|
cert = CertFileToCertificate(serverCertEccDer);
|
|
store.setCertificateEntry("serverEcc", cert);
|
|
|
|
/* INSERT [4]: ECC priv key + single cert */
|
|
privKey = DerFileToPrivateKey(serverEccPkcs8Der, "EC");
|
|
store.setKeyEntry("eccCert", privKey,
|
|
storePass.toCharArray(), new Certificate[] { cert });
|
|
|
|
/* INSERT [6]: ECC priv key + cert chain */
|
|
chain = new Certificate[3];
|
|
cert = CertFileToCertificate(intEccServerCertDer);
|
|
chain[0] = cert;
|
|
cert = CertFileToCertificate(intEccInt2CertDer);
|
|
chain[1] = cert;
|
|
cert = CertFileToCertificate(intEccInt1CertDer);
|
|
chain[2] = cert;
|
|
store.setKeyEntry("eccChain", privKey, storePass.toCharArray(), chain);
|
|
|
|
/* INSERT [7]: AES SecretKey */
|
|
/* If running this example with JKS type, JKS cannot import
|
|
* non-private keys. Only do for WKS type. */
|
|
if (storeType.equals("WKS")) {
|
|
kg = KeyGenerator.getInstance("AES");
|
|
kg.init(256, new SecureRandom());
|
|
aesKey = kg.generateKey();
|
|
store.setKeyEntry("aesKey", aesKey, storePass.toCharArray(), null);
|
|
}
|
|
}
|
|
|
|
public static void WriteKeyStoreToFile(KeyStore store)
|
|
throws FileNotFoundException, KeyStoreException, IOException,
|
|
NoSuchAlgorithmException, CertificateException {
|
|
|
|
FileOutputStream fos = new FileOutputStream(wksFile);
|
|
store.store(fos, storePass.toCharArray());
|
|
fos.close();
|
|
}
|
|
|
|
public static KeyStore ReadKeyStoreFromFile(String fileName)
|
|
throws KeyStoreException, FileNotFoundException, IOException,
|
|
NoSuchAlgorithmException, CertificateException {
|
|
|
|
KeyStore store = null;
|
|
|
|
store = KeyStore.getInstance(storeType);
|
|
store.load(new FileInputStream(fileName), storePass.toCharArray());
|
|
|
|
return store;
|
|
}
|
|
|
|
public static void main(String args [])
|
|
{
|
|
KeyStore store = null;
|
|
Provider p = null;
|
|
|
|
System.out.println("WolfSSLKeyStore (WKS) Example App\n");
|
|
|
|
/* Install wolfJCE */
|
|
Security.insertProviderAt(new WolfCryptProvider(), 1);
|
|
|
|
try {
|
|
store = KeyStore.getInstance(storeType);
|
|
store.load(null, storePass.toCharArray());
|
|
|
|
p = store.getProvider();
|
|
System.out.println("KeyStore('" + storeType + "') provider = " + p);
|
|
|
|
/* Insert variety of entry types */
|
|
System.out.println("\n-------------------------------------------");
|
|
System.out.println("Inserting entries into KeyStore");
|
|
System.out.println("-------------------------------------------");
|
|
InsertKeyStoreEntries(store);
|
|
|
|
/* Store KeyStore to file (wolfssl.wks) */
|
|
System.out.println("\n-------------------------------------------");
|
|
System.out.println("Writing KeyStore to file: " + wksFile);
|
|
System.out.println("-------------------------------------------");
|
|
WriteKeyStoreToFile(store);
|
|
|
|
/* Read KeyStore back in from file */
|
|
System.out.println("\n-------------------------------------------");
|
|
System.out.println("Reading KeyStore in from file: " + wksFile);
|
|
System.out.println("-------------------------------------------");
|
|
store = ReadKeyStoreFromFile(wksFile);
|
|
|
|
System.out.println("\nExample Finished Successfully");
|
|
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
|