JCE: initial implementation of WolfCryptUtil.convertKeyStoreToWKS()

pull/108/head
Chris Conlon 2025-03-18 16:43:37 -06:00
parent 783c9275de
commit 0834dbdafc
6 changed files with 907 additions and 5 deletions

View File

@ -234,8 +234,7 @@ SecretKey objects.
#### Converting Other KeyStore Formats to WKS #### Converting Other KeyStore Formats to WKS
The Java `keytool` application can be used to convert between KeyStore formats. The Java `keytool` application can be used to convert between KeyStore formats.
This can be easily used for example to convert a JKS KeyStore into a WKS This can be easily used to convert a JKS KeyStore into a WKS format KeyStore.
format KeyStore.
The following example command would convert a KeyStore in JKS format named The following example command would convert a KeyStore in JKS format named
`server.jks` to a KeyStore in WKS format named `server.wks`: `server.jks` to a KeyStore in WKS format named `server.wks`:
@ -248,6 +247,50 @@ keytool -importkeystore -srckeystore server.jks -destkeystore server.wks \
--providerpath /path/to/wolfcrypt-jni.jar --providerpath /path/to/wolfcrypt-jni.jar
``` ```
Additionally, wolfJCE provides a utility method `WolfCryptUtil.convertKeyStoreToWKS()`
that can be used programmatically to convert KeyStore formats. This method
supports converting from JKS, PKCS12, and WKS formats to WKS format. When
converting from WKS to WKS, the method efficiently returns the same input
stream without performing any conversion.
The method automatically detects the input KeyStore format and handles the
conversion appropriately. It supports the following features:
- Automatic format detection (WKS, JKS, PKCS12)
- Preservation of all certificates and keys from the source KeyStore
- Support for both key entries (with certificate chains) and certificate-only entries
- Efficient handling of WKS input (returns same stream)
- Proper stream handling with mark/reset support for large KeyStores
**FIPS NOTE:** This utility method will call Sun provider code for JKS
and PKCS12. This means that if using wolfCrypt FIPS, these calls will make
calls into non-FIPS compliant cryptography for the conversion. Please take
this into consideration when being used in a FIPS compliant environment.
Example usage:
```java
import com.wolfssl.provider.jce.WolfCryptUtil;
import java.io.InputStream;
import java.security.KeyStore;
/* Load your source KeyStore (JKS, PKCS12, or WKS) */
InputStream sourceStream = ...;
char[] password = "your_password".toCharArray();
/* Convert to WKS format, fail on insert errors */
InputStream wksStream = WolfCryptUtil.convertKeyStoreToWKS(sourceStream, password, true);
/* Load the converted WKS KeyStore */
KeyStore wksStore = KeyStore.getInstance("WKS", "wolfJCE");
wksStore.load(wksStream, password);
```
The method respects the Security properties `wolfjce.mapJKStoWKS` and
`wolfjce.mapPKCS12toWKS` when performing conversions. If these properties are
set to "true", the method will use reflection to find the Sun provider
implementations for JKS and PKCS12 to use for conversion.
To list entries inside a WKS keystore using the `keytool`, a command To list entries inside a WKS keystore using the `keytool`, a command
similar to the following can be used (with the `-list` option): similar to the following can be used (with the `-list` option):
@ -388,7 +431,7 @@ ant build system, please see the main README.md included in this package.
wolfSSL (company) has it's own set of code signing certificates from Oracle wolfSSL (company) has it's own set of code signing certificates from Oracle
that allow wolfJCE to be authenticated in the Oracle JDK. With each release that allow wolfJCE to be authenticated in the Oracle JDK. With each release
of wolfJCE, wolfSSL ships a couple pre-signed versions of the of wolfJCE, wolfSSL ships a couple pre-signed versions of the
wolfcrypt-jni.jar”, located at: 'wolfcrypt-jni.jar", located at:
wolfcrypt-jni-X.X.X/lib/signed/debug/wolfcrypt-jni.jar wolfcrypt-jni-X.X.X/lib/signed/debug/wolfcrypt-jni.jar
wolfcrypt-jni-X.X.X/lib/signed/release/wolfcrypt-jni.jar wolfcrypt-jni-X.X.X/lib/signed/release/wolfcrypt-jni.jar

View File

@ -82,6 +82,7 @@ infer --fail-on-issue run -- javac \
src/main/java/com/wolfssl/provider/jce/WolfCryptRandom.java \ src/main/java/com/wolfssl/provider/jce/WolfCryptRandom.java \
src/main/java/com/wolfssl/provider/jce/WolfCryptSecretKeyFactory.java \ src/main/java/com/wolfssl/provider/jce/WolfCryptSecretKeyFactory.java \
src/main/java/com/wolfssl/provider/jce/WolfCryptSignature.java \ src/main/java/com/wolfssl/provider/jce/WolfCryptSignature.java \
src/main/java/com/wolfssl/provider/jce/WolfCryptUtil.java \
src/main/java/com/wolfssl/provider/jce/WolfSSLKeyStore.java src/main/java/com/wolfssl/provider/jce/WolfSSLKeyStore.java
RETVAL=$? RETVAL=$?

View File

@ -0,0 +1,390 @@
/* WolfCryptUtil.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
*/
package com.wolfssl.provider.jce;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.Enumeration;
/**
* Utility class containing helper functions for wolfCrypt JCE provider.
*/
public class WolfCryptUtil {
/**
* Maximum size of the keystore buffer to mark. We try to set this
* high enough to handle any large keystore. Although there is no
* upper limit on the size of a keystore, looking at the JDK 23 cacerts
* KeyStore file, that is 190kB. We leave ample room for growth here
* with 512kB.
*/
private static final int MAX_KEYSTORE_SIZE = 512 * 1024;
/**
* Chunk size for reading the keystore. We use 4kB as a happy medium
* between memory usage and performance.
*/
private static final int KEYSTORE_CHUNK_SIZE = 4 * 1024;
/**
* Internal method for logging output.
*
* @param msg message to be logged
*/
private static synchronized void log(String msg) {
WolfCryptDebug.log(WolfCryptUtil.class, WolfCryptDebug.INFO,
() -> msg);
}
/**
* Converts a Java KeyStore (JKS or PKCS12) to a WolfSSLKeyStore (WKS)
* format.
*
* This method detects the type of the input KeyStore (WKS, JKS, or PKCS12)
* and converts it to WKS format if needed. All certificates and keys from
* the source KeyStore are transferred to the destination KeyStore. If the
* input KeyStore is already of type WKS, the method will return the same
* InputStream.
*
* @param stream Input stream containing a WKS, JKS, or PKCS12 KeyStore
* @param oldPassword Password used to decrypt KeyStore entries.
* @param newPassword Password used to encrypt KeyStore entries. When used
* with wolfCrypt FIPS, this password needs to meet FIPS minimum
* HMAC key size requirements and must be at least 14 characters.
* @param failOnInsertErrors If true, throw an exception if an error occurs
* during the insertion of a certificate or key into the newly
* created WKS KeyStore. If false, log the error and continue
* inserting the remaining entries. When used with wolfCrypt FIPS,
* entries can fail to insert into WKS KeyStore due to FIPS
* restrictions on the algorithms used.
* @return InputStream containing the newly created WKS KeyStore
* @throws IOException If an I/O error occurs
* @throws NoSuchProviderException If required security providers are not
* available or if reflection operations fail when accessing the
* original KeyStore implementations
*/
public static InputStream convertKeyStoreToWKS(InputStream stream,
char[] oldPassword, char[] newPassword, boolean failOnInsertErrors)
throws IOException, NoSuchProviderException {
boolean mapJksToWks = false;
boolean mapPkcs12ToWks = false;
boolean wksFound = false;
boolean jksFound = false;
KeyStore sourceStore = null;
log("converting KeyStore InputStream to WKS format");
if (stream == null) {
throw new IllegalArgumentException("Input stream cannot be null");
}
if (oldPassword == null) {
throw new IllegalArgumentException("Old password cannot be null");
}
if (newPassword == null) {
throw new IllegalArgumentException("New password cannot be null");
}
/* Make sure wolfJCE provider is available and registered */
Provider wolfJCE = Security.getProvider("wolfJCE");
if (wolfJCE == null) {
Security.addProvider(new WolfCryptProvider());
}
try {
/* Check if wolfJCE has mapped JKS or PKCS12 to WKS */
String mapJksToWksStr =
Security.getProperty("wolfjce.mapJKStoWKS");
if (mapJksToWksStr != null && !mapJksToWksStr.isEmpty() &&
mapJksToWksStr.equalsIgnoreCase("true")) {
mapJksToWks = true;
}
String mapPkcs12ToWksStr =
Security.getProperty("wolfjce.mapPKCS12toWKS");
if (mapPkcs12ToWksStr != null && !mapPkcs12ToWksStr.isEmpty() &&
mapPkcs12ToWksStr.equalsIgnoreCase("true")) {
mapPkcs12ToWks = true;
}
log("JKS to WKS mapping enabled: " + mapJksToWks);
log("PKCS12 to WKS mapping enabled: " + mapPkcs12ToWks);
/* Since we will be doing KeyStore type detection by trying to
* read the KeyStore, we want to make sure we have the ability
* to mark() the stream. If we don't have the ability, we copy
* the stream into a ByteArrayOutputStream and then into a
* ByteArrayInputStream which is markable. */
if (!stream.markSupported()) {
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int numRead;
byte[] data = new byte[KEYSTORE_CHUNK_SIZE];
while ((numRead = stream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, numRead);
}
buffer.flush();
stream = new ByteArrayInputStream(buffer.toByteArray());
} catch (IOException e) {
throw new IOException("Failed to read stream contents", e);
}
}
/* Mark the current position in the stream */
stream.mark(MAX_KEYSTORE_SIZE);
/* Try WKS */
try {
sourceStore = KeyStore.getInstance("WKS", "wolfJCE");
sourceStore.load(stream, oldPassword);
wksFound = true;
log("Input KeyStore is already in WKS format");
} catch (KeyStoreException | NoSuchAlgorithmException |
CertificateException | IOException e) {
/* Not a WKS KeyStore, continue with other formats */
} finally {
stream.reset();
}
/* Try JKS */
if (!wksFound) {
try {
if (mapJksToWks) {
/* If JKS is mapped to WKS, use reflection to get the
* Sun provider's JKS implementation */
try {
sourceStore = getJksKeyStoreFromSunProvider();
} catch (ReflectiveOperationException |
KeyStoreException ex) {
throw new NoSuchProviderException(
"Failed to get JKS implementation via " +
"reflection from Sun provider: " +
ex.getMessage());
}
} else {
sourceStore = KeyStore.getInstance("JKS");
}
sourceStore.load(stream, oldPassword);
jksFound = true;
log("Input KeyStore is in JKS format");
} catch (IOException | NoSuchAlgorithmException |
CertificateException e) {
/* Not a JKS KeyStore, continue with other formats */
} finally {
stream.reset();
}
}
/* Try PKCS12 */
if (!wksFound && !jksFound) {
try {
if (mapPkcs12ToWks) {
/* If PKCS12 is mapped to WKS, use reflection to get
* the Sun provider's PKCS12 implementation */
try {
sourceStore = getPkcs12KeyStoreFromSunProvider();
} catch (ReflectiveOperationException |
KeyStoreException ex) {
throw new NoSuchProviderException(
"Failed to get PKCS12 implementation via " +
"reflection from Sun provider: " +
ex.getMessage());
}
} else {
sourceStore = KeyStore.getInstance("PKCS12");
}
sourceStore.load(stream, oldPassword);
log("Input KeyStore is in PKCS12 format");
} catch (KeyStoreException | NoSuchAlgorithmException |
CertificateException ex) {
throw new IOException(
"Input KeyStore is neither WKS, JKS nor " +
"PKCS12 KeyStore format", ex);
} finally {
stream.reset();
}
}
/* Create destination WKS KeyStore */
KeyStore destStore = KeyStore.getInstance("WKS", "wolfJCE");
destStore.load(null, newPassword);
log("Creating destination WKS KeyStore to populate");
/* Copy all entries from source to destination */
Enumeration<String> aliases = sourceStore.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
if (sourceStore.isKeyEntry(alias)) {
/* Handle key entries (may include a certificate chain) */
try {
Key key = sourceStore.getKey(alias, oldPassword);
Certificate[] chain =
sourceStore.getCertificateChain(alias);
destStore.setKeyEntry(alias, key, newPassword, chain);
} catch (UnrecoverableKeyException | KeyStoreException e) {
if (failOnInsertErrors) {
throw new IOException("Failed to copy key entry: " +
alias, e);
} else {
log("Failed to copy key entry: " + alias +
", continuing with next entry");
}
}
} else if (sourceStore.isCertificateEntry(alias)) {
/* Handle certificate-only entries */
try {
Certificate cert = sourceStore.getCertificate(alias);
destStore.setCertificateEntry(alias, cert);
} catch (KeyStoreException e) {
if (failOnInsertErrors) {
throw new IOException(
"Failed to copy certificate entry: " +
alias, e);
} else {
log("Failed to copy certificate entry: " + alias +
", continuing with next entry");
}
}
}
}
log("Copied all entries from source to destination KeyStore");
/* Write the WKS KeyStore to a byte array and return as
* InputStream */
ByteArrayOutputStream baos = new ByteArrayOutputStream();
destStore.store(baos, newPassword);
return new ByteArrayInputStream(baos.toByteArray());
} catch (KeyStoreException | NoSuchAlgorithmException |
CertificateException e) {
throw new IOException("Error during KeyStore conversion", e);
}
}
/**
* Get the Sun provider JKS KeyStore implementation using reflection.
* This is used when wolfJCE has registered itself as the JKS provider
* using the Security property "wolfjce.mapJKStoWKS".
*
* @return A KeyStore instance from the Sun provider for JKS format
* @throws ReflectiveOperationException If reflection fails
* @throws KeyStoreException If the KeyStore cannot be created
*/
private static KeyStore getJksKeyStoreFromSunProvider()
throws ReflectiveOperationException, KeyStoreException {
/* Try to find the Sun provider */
Provider sunProvider = Security.getProvider("SUN");
if (sunProvider == null) {
throw new KeyStoreException("SUN provider not available");
}
try {
/* Try to get the KeyStore from the explicit provider first */
return KeyStore.getInstance("JKS", sunProvider);
} catch (Exception e) {
/* Fallback to using reflection if the first approach fails */
/* Load the JKS KeyStore class directly from the Sun provider */
Class<?> jksKeyStoreClass =
Class.forName("sun.security.provider.JavaKeyStore$JKS");
Constructor<?> constructor =
jksKeyStoreClass.getDeclaredConstructor();
constructor.setAccessible(true);
KeyStore ks = (KeyStore) constructor.newInstance();
/* Initialize the KeyStore */
Method engineInitMethod =
jksKeyStoreClass.getDeclaredMethod("engineInit");
engineInitMethod.setAccessible(true);
engineInitMethod.invoke(ks);
return ks;
}
}
/**
* Get the Sun provider PKCS12 KeyStore implementation using reflection.
* This is used when wolfJCE has registered itself as the PKCS12 provider
* using the Security property "wolfjce.mapPKCS12toWKS".
*
* @return A KeyStore instance from the Sun provider for PKCS12 format
* @throws ReflectiveOperationException If reflection fails
* @throws KeyStoreException If the KeyStore cannot be created
*/
private static KeyStore getPkcs12KeyStoreFromSunProvider()
throws ReflectiveOperationException, KeyStoreException {
/* Try to find the SunJSSE provider */
Provider sunJsseProvider = Security.getProvider("SunJSSE");
if (sunJsseProvider == null) {
/* Try Sun provider as fallback */
sunJsseProvider = Security.getProvider("SUN");
if (sunJsseProvider == null) {
throw new KeyStoreException(
"Neither SunJSSE nor SUN provider available");
}
}
try {
/* Try to get the KeyStore through the provider first */
return KeyStore.getInstance("PKCS12", sunJsseProvider);
} catch (Exception e) {
/* Fallback to using reflection if the first approach fails */
/* Load the PKCS12 KeyStore class */
Class<?> pkcs12KeyStoreClass =
Class.forName("sun.security.pkcs12.PKCS12KeyStore");
Constructor<?> constructor =
pkcs12KeyStoreClass.getDeclaredConstructor();
constructor.setAccessible(true);
KeyStore ks = (KeyStore) constructor.newInstance();
/* Initialize the KeyStore */
Method engineInitMethod =
pkcs12KeyStoreClass.getDeclaredMethod("engineInit");
engineInitMethod.setAccessible(true);
engineInitMethod.invoke(ks);
return ks;
}
}
}

View File

@ -0,0 +1,468 @@
/* WolfCryptUtilsTest.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
*/
package com.wolfssl.provider.jce.test;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.File;
import java.security.Security;
import java.util.Arrays;
import java.security.Provider;
import java.security.KeyStore;
import com.wolfssl.provider.jce.WolfCryptProvider;
import com.wolfssl.provider.jce.WolfCryptUtil;
import com.wolfssl.wolfcrypt.Fips;
/**
* Test suite for WolfCryptUtils.convertKeyStoreToWKS method.
*
* Tests converting JKS KeyStore to WKS format and error handling.
*/
public class WolfCryptUtilTest {
/* Common test password for test KeyStores */
private static final char[] PASSWORD = "wolfsslpassword".toCharArray();
private static final String WKS_PROVIDER = "wolfJCE";
private static final String TEST_ALIAS = "server";
private static final String TEST_JKS_PATH = "examples/certs/server.jks";
private static final String TEST_P12_PATH = "examples/certs/client.p12";
private static final String TEST_WKS_PATH = "examples/certs/server.wks";
private static final char[] CACERTS_PASSWORD = "changeit".toCharArray();
/* Original security property values */
private static String origMapJksToWks = null;
private static String origMapPkcs12ToWks = null;
@Rule(order = Integer.MIN_VALUE)
public TestRule testWatcher = new TestWatcher() {
protected void starting(Description desc) {
System.out.println("\t" + desc.getMethodName());
}
};
@BeforeClass
public static void setUpClass() {
System.out.println("JCE WolfCryptUtils Class");
/* Register wolfJCE provider if not already done */
Provider wolfJCE = Security.getProvider(WKS_PROVIDER);
if (wolfJCE == null) {
Security.insertProviderAt(new WolfCryptProvider(), 1);
}
/* Store original security property values */
origMapJksToWks = Security.getProperty("wolfjce.mapJKStoWKS");
origMapPkcs12ToWks = Security.getProperty("wolfjce.mapPKCS12toWKS");
/* Make sure we set them to known values at the start */
Security.setProperty("wolfjce.mapJKStoWKS", "false");
Security.setProperty("wolfjce.mapPKCS12toWKS", "false");
}
@AfterClass
public static void tearDownClass() {
/* Restore original security property values */
if (origMapJksToWks != null) {
Security.setProperty("wolfjce.mapJKStoWKS", origMapJksToWks);
} else {
Security.setProperty("wolfjce.mapJKStoWKS", "false");
}
if (origMapPkcs12ToWks != null) {
Security.setProperty("wolfjce.mapPKCS12toWKS", origMapPkcs12ToWks);
} else {
Security.setProperty("wolfjce.mapPKCS12toWKS", "false");
}
}
/**
* Helper method to load a KeyStore file into a ByteArrayInputStream
* @param path Path to the KeyStore file
* @return ByteArrayInputStream containing the KeyStore data
* @throws Exception if file cannot be read
*/
private static synchronized ByteArrayInputStream loadKeyStoreFile(
String path) throws Exception {
FileInputStream fis = new FileInputStream(path);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
fis.close();
return new ByteArrayInputStream(baos.toByteArray());
}
/**
* Helper method to find the Java cacerts file
* @return Path to cacerts file if found, null otherwise
*/
private static String findCacertsFile() {
String javaHome = System.getProperty("java.home");
if (javaHome == null) {
return null;
}
/* Common locations for cacerts file */
String[] possiblePaths = {
/* Standard locations */
javaHome + "/lib/security/cacerts",
javaHome + "/jre/lib/security/cacerts",
/* Android locations */
javaHome + "/etc/security/cacerts",
/* Windows specific */
javaHome + "\\lib\\security\\cacerts",
javaHome + "\\jre\\lib\\security\\cacerts"
};
for (String path : possiblePaths) {
File file = new File(path);
if (file.exists() && file.isFile()) {
return path;
}
}
return null;
}
/**
* Test with null input stream (should throw an exception)
*/
@Test
public void testNullInputStream() {
try {
WolfCryptUtil.convertKeyStoreToWKS(null, PASSWORD, PASSWORD, true);
fail("Should have thrown an exception for null input stream");
} catch (IllegalArgumentException e) {
/* Expected exception */
assertTrue("Exception message should indicate null input stream",
e.getMessage().contains("null"));
} catch (Exception e) {
fail("Unexpected exception type: " + e.getClass().getName());
}
}
/**
* Test with null password (should throw an exception)
*/
@Test
public void testNullPassword() {
/* Create a dummy keystore for testing */
try {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, PASSWORD);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ks.store(baos, PASSWORD);
ByteArrayInputStream bais =
new ByteArrayInputStream(baos.toByteArray());
WolfCryptUtil.convertKeyStoreToWKS(bais, PASSWORD, null, true);
fail("Should have thrown an exception for null password");
} catch (IllegalArgumentException e) {
/* Expected exception */
assertTrue("Exception message should indicate null password",
e.getMessage().contains("null"));
} catch (Exception e) {
fail("Unexpected exception type: " + e.getClass().getName());
}
}
/**
* Test converting JKS to WKS with mapJKStoWKS=false
*/
@Test
public void testConvertJksToWksWithoutMapping() throws Exception {
/* Store original property value */
String origValue = Security.getProperty("wolfjce.mapJKStoWKS");
try {
Security.setProperty("wolfjce.mapJKStoWKS", "false");
/* Load test JKS KeyStore */
ByteArrayInputStream jksStream = loadKeyStoreFile(TEST_JKS_PATH);
/* Convert to WKS */
ByteArrayInputStream wksStream =
(ByteArrayInputStream)WolfCryptUtil.convertKeyStoreToWKS(
jksStream, PASSWORD, PASSWORD, true);
/* Load the converted WKS KeyStore */
KeyStore wksStore = KeyStore.getInstance("WKS", "wolfJCE");
wksStore.load(wksStream, PASSWORD);
/* Verify the key and certificate were properly converted */
assertTrue("Key entry should exist",
wksStore.isKeyEntry(TEST_ALIAS));
assertNotNull("Private key should exist",
wksStore.getKey(TEST_ALIAS, PASSWORD));
assertNotNull("Certificate chain should exist",
wksStore.getCertificateChain(TEST_ALIAS));
assertEquals("Certificate chain should have length 2",
2, wksStore.getCertificateChain(TEST_ALIAS).length);
} finally {
/* Restore original property value */
if (origValue != null) {
Security.setProperty("wolfjce.mapJKStoWKS", origValue);
} else {
Security.setProperty("wolfjce.mapJKStoWKS", "false");
}
}
}
/**
* Test converting JKS to WKS with mapJKStoWKS=true
*/
@Test
public void testConvertJksToWksWithMapping() throws Exception {
/* Store original property value */
String origValue = Security.getProperty("wolfjce.mapJKStoWKS");
try {
Security.setProperty("wolfjce.mapJKStoWKS", "true");
/* Load test JKS KeyStore */
ByteArrayInputStream jksStream = loadKeyStoreFile(TEST_JKS_PATH);
/* Convert to WKS */
ByteArrayInputStream wksStream =
(ByteArrayInputStream)WolfCryptUtil.convertKeyStoreToWKS(
jksStream, PASSWORD, PASSWORD, true);
/* Load the converted WKS KeyStore */
KeyStore wksStore = KeyStore.getInstance("WKS", "wolfJCE");
wksStore.load(wksStream, PASSWORD);
/* Verify the key and certificate were properly converted */
assertTrue("Key entry should exist",
wksStore.isKeyEntry(TEST_ALIAS));
assertNotNull("Private key should exist",
wksStore.getKey(TEST_ALIAS, PASSWORD));
assertNotNull("Certificate chain should exist",
wksStore.getCertificateChain(TEST_ALIAS));
assertEquals("Certificate chain should have length 2",
2, wksStore.getCertificateChain(TEST_ALIAS).length);
} finally {
/* Restore original property value */
if (origValue != null) {
Security.setProperty("wolfjce.mapJKStoWKS", origValue);
} else {
Security.setProperty("wolfjce.mapJKStoWKS", "false");
}
}
}
/**
* Test converting PKCS12 to WKS with mapPKCS12toWKS=false
*/
@Test
public void testConvertP12ToWksWithoutMapping() throws Exception {
/* Store original property value */
String origValue = Security.getProperty("wolfjce.mapPKCS12toWKS");
try {
Security.setProperty("wolfjce.mapPKCS12toWKS", "false");
/* Load test PKCS12 KeyStore */
ByteArrayInputStream p12Stream = loadKeyStoreFile(TEST_P12_PATH);
/* Convert to WKS */
ByteArrayInputStream wksStream =
(ByteArrayInputStream)WolfCryptUtil.convertKeyStoreToWKS(
p12Stream, PASSWORD, PASSWORD, true);
/* Load the converted WKS KeyStore */
KeyStore wksStore = KeyStore.getInstance("WKS", "wolfJCE");
wksStore.load(wksStream, PASSWORD);
/* Verify both entries were properly converted */
assertTrue("RSA key entry should exist",
wksStore.isKeyEntry("client"));
assertTrue("ECC key entry should exist",
wksStore.isKeyEntry("client-ecc"));
/* Verify RSA key and certificate */
assertNotNull("RSA private key should exist",
wksStore.getKey("client", PASSWORD));
assertNotNull("RSA certificate chain should exist",
wksStore.getCertificateChain("client"));
assertEquals("RSA certificate chain should have length 1",
1, wksStore.getCertificateChain("client").length);
/* Verify ECC key and certificate */
assertNotNull("ECC private key should exist",
wksStore.getKey("client-ecc", PASSWORD));
assertNotNull("ECC certificate chain should exist",
wksStore.getCertificateChain("client-ecc"));
assertEquals("ECC certificate chain should have length 1",
1, wksStore.getCertificateChain("client-ecc").length);
} finally {
/* Restore original property value */
if (origValue != null) {
Security.setProperty("wolfjce.mapPKCS12toWKS", origValue);
} else {
Security.setProperty("wolfjce.mapPKCS12toWKS", "false");
}
}
}
/**
* Test converting PKCS12 to WKS with mapPKCS12toWKS=true
*/
@Test
public void testConvertP12ToWksWithMapping() throws Exception {
/* Store original property value */
String origValue = Security.getProperty("wolfjce.mapPKCS12toWKS");
try {
Security.setProperty("wolfjce.mapPKCS12toWKS", "true");
/* Load test PKCS12 KeyStore */
ByteArrayInputStream p12Stream = loadKeyStoreFile(TEST_P12_PATH);
/* Convert to WKS */
ByteArrayInputStream wksStream =
(ByteArrayInputStream)WolfCryptUtil.convertKeyStoreToWKS(
p12Stream, PASSWORD, PASSWORD, true);
/* Load the converted WKS KeyStore */
KeyStore wksStore = KeyStore.getInstance("WKS", "wolfJCE");
wksStore.load(wksStream, PASSWORD);
/* Verify both entries were properly converted */
assertTrue("RSA key entry should exist",
wksStore.isKeyEntry("client"));
assertTrue("ECC key entry should exist",
wksStore.isKeyEntry("client-ecc"));
/* Verify RSA key and certificate */
assertNotNull("RSA private key should exist",
wksStore.getKey("client", PASSWORD));
assertNotNull("RSA certificate chain should exist",
wksStore.getCertificateChain("client"));
assertEquals("RSA certificate chain should have length 1",
1, wksStore.getCertificateChain("client").length);
/* Verify ECC key and certificate */
assertNotNull("ECC private key should exist",
wksStore.getKey("client-ecc", PASSWORD));
assertNotNull("ECC certificate chain should exist",
wksStore.getCertificateChain("client-ecc"));
assertEquals("ECC certificate chain should have length 1",
1, wksStore.getCertificateChain("client-ecc").length);
} finally {
/* Restore original property value */
if (origValue != null) {
Security.setProperty("wolfjce.mapPKCS12toWKS", origValue);
} else {
Security.setProperty("wolfjce.mapPKCS12toWKS", "false");
}
}
}
/**
* Test converting WKS to WKS (should return same InputStream)
*/
@Test
public void testConvertWksToWks() throws Exception {
/* Load test WKS KeyStore */
ByteArrayInputStream wksStream = loadKeyStoreFile(TEST_WKS_PATH);
/* Convert WKS to WKS */
ByteArrayInputStream wksStreamB =
(ByteArrayInputStream)WolfCryptUtil.convertKeyStoreToWKS(
wksStream, PASSWORD, PASSWORD, true);
/* Verify the KeyStore can still be loaded */
KeyStore wksStore = KeyStore.getInstance("WKS", "wolfJCE");
wksStore.load(wksStreamB, PASSWORD);
/* Verify the key and certificate were preserved */
assertTrue("Key entry should exist", wksStore.isKeyEntry(TEST_ALIAS));
assertNotNull("Private key should exist",
wksStore.getKey(TEST_ALIAS, PASSWORD));
assertNotNull("Certificate chain should exist",
wksStore.getCertificateChain(TEST_ALIAS));
assertEquals("Certificate chain should have length 2",
2, wksStore.getCertificateChain(TEST_ALIAS).length);
}
/**
* Test converting Java cacerts to WKS format
*/
@Test
public void testConvertCacertsToWks() throws Exception {
boolean failOnInsertErrors = true;
char[] password = CACERTS_PASSWORD;
/* Find cacerts file */
String cacertsPath = findCacertsFile();
if (cacertsPath == null) {
System.out.println(
"Skipping testConvertCacertsToWks: cacerts file not found");
return;
}
/* If using FIPS mode, set failOnInsertErrors to false */
if (Fips.enabled) {
failOnInsertErrors = false;
password = (new String(CACERTS_PASSWORD) +
new String(CACERTS_PASSWORD)).toCharArray();
}
/* Load cacerts KeyStore */
ByteArrayInputStream cacertsStream = loadKeyStoreFile(cacertsPath);
/* Convert to WKS */
ByteArrayInputStream wksStream =
(ByteArrayInputStream)WolfCryptUtil.convertKeyStoreToWKS(
cacertsStream, CACERTS_PASSWORD, password, failOnInsertErrors);
/* Load the converted WKS KeyStore */
KeyStore wksStore = KeyStore.getInstance("WKS", "wolfJCE");
wksStore.load(wksStream, password);
/* Verify the KeyStore was converted and contains entries */
assertTrue("WKS KeyStore should contain entries",
wksStore.size() > 0);
}
}

View File

@ -43,7 +43,8 @@ import org.junit.runners.Suite.SuiteClasses;
WolfCryptKeyGeneratorTest.class, WolfCryptKeyGeneratorTest.class,
WolfCryptKeyPairGeneratorTest.class, WolfCryptKeyPairGeneratorTest.class,
WolfCryptPKIXCertPathValidatorTest.class, WolfCryptPKIXCertPathValidatorTest.class,
WolfSSLKeyStoreTest.class WolfSSLKeyStoreTest.class,
WolfCryptUtilTest.class
}) })
public class WolfJCETestSuite { } public class WolfJCETestSuite { }

View File

@ -1430,7 +1430,6 @@ public class WolfSSLKeyStoreTest {
assertEquals(1, store.size()); assertEquals(1, store.size());
} }
//CHRIS
@Test @Test
public void testLoadWKSasJKSFromFile() public void testLoadWKSasJKSFromFile()
throws KeyStoreException, IOException, FileNotFoundException, throws KeyStoreException, IOException, FileNotFoundException,