Fixed indents, runBenchmark name, Delta table displays more and clear info

pull/95/head
Jack Tjaden 2025-01-21 16:00:16 -07:00
parent 45f14e5e7c
commit 1464f77315
1 changed files with 393 additions and 361 deletions

View File

@ -15,392 +15,424 @@ import com.wolfssl.provider.jce.WolfCryptProvider;
import com.wolfssl.wolfcrypt.FeatureDetect; import com.wolfssl.wolfcrypt.FeatureDetect;
public class CryptoBenchmark { public class CryptoBenchmark {
/* Constants for benchmark configuration */ /* Constants for benchmark configuration */
private static final int WARMUP_ITERATIONS = 5; private static final int WARMUP_ITERATIONS = 5;
private static final int TEST_ITERATIONS = 5; private static final int TEST_ITERATIONS = 5;
private static final int DATA_SIZE = 1024 * 1024; private static final int DATA_SIZE = 1024 * 1024;
private static final int AES_BLOCK_SIZE = 16; private static final int AES_BLOCK_SIZE = 16;
private static final int DES3_BLOCK_SIZE = 8; private static final int DES3_BLOCK_SIZE = 8;
private static final int GCM_TAG_LENGTH = 128; private static final int GCM_TAG_LENGTH = 128;
private static final int[] RSA_KEY_SIZES = {2048, 3072, 4096}; private static final int[] RSA_KEY_SIZES = {2048, 3072, 4096};
private static final int RSA_MIN_TIME_SECONDS = 1; /* minimum time to run each test */ private static final int RSA_MIN_TIME_SECONDS = 1; /* minimum time to run each test */
private static final int SMALL_MESSAGE_SIZE = 32; /* small message size for RSA ops */ private static final int SMALL_MESSAGE_SIZE = 32; /* small message size for RSA ops */
/* Class to store benchmark results */ /* Class to store benchmark results */
private static class BenchmarkResult { private static class BenchmarkResult {
/* Result fields */ /* Result fields */
String provider; String provider;
String operation; String operation;
double throughput; double throughput;
/* Constructor */ /* Constructor */
BenchmarkResult(String provider, String operation, double throughput) { BenchmarkResult(String provider, String operation, double throughput) {
this.provider = provider; this.provider = provider;
this.operation = operation; this.operation = operation;
this.throughput = throughput; this.throughput = throughput;
}
} }
}
/* List to store all benchmark results */ /* List to store all benchmark results */
private static final List<BenchmarkResult> results = new ArrayList<>(); private static final List<BenchmarkResult> results = new ArrayList<>();
/* Static AES key buffer */ /* Static AES key buffer */
private static final byte[] STATIC_AES_KEY = new byte[] { private static final byte[] STATIC_AES_KEY = new byte[] {
(byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67, (byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67,
(byte)0x89, (byte)0xab, (byte)0xcd, (byte)0xef, (byte)0x89, (byte)0xab, (byte)0xcd, (byte)0xef,
(byte)0xfe, (byte)0xde, (byte)0xba, (byte)0x98, (byte)0xfe, (byte)0xde, (byte)0xba, (byte)0x98,
(byte)0x76, (byte)0x54, (byte)0x32, (byte)0x10, (byte)0x76, (byte)0x54, (byte)0x32, (byte)0x10,
(byte)0x89, (byte)0xab, (byte)0xcd, (byte)0xef, (byte)0x89, (byte)0xab, (byte)0xcd, (byte)0xef,
(byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67, (byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67,
(byte)0xf0, (byte)0xf1, (byte)0xf2, (byte)0xf3, (byte)0xf0, (byte)0xf1, (byte)0xf2, (byte)0xf3,
(byte)0xf4, (byte)0xf5, (byte)0xf6, (byte)0xf7 (byte)0xf4, (byte)0xf5, (byte)0xf6, (byte)0xf7
}; };
/* Static DESede (Triple DES) key buffer */ /* Static DESede (Triple DES) key buffer */
private static final byte[] STATIC_DES3_KEY = new byte[] { private static final byte[] STATIC_DES3_KEY = new byte[] {
(byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67, (byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67,
(byte)0x89, (byte)0xab, (byte)0xcd, (byte)0xef, (byte)0x89, (byte)0xab, (byte)0xcd, (byte)0xef,
(byte)0xfe, (byte)0xdc, (byte)0xba, (byte)0x98, (byte)0xfe, (byte)0xdc, (byte)0xba, (byte)0x98,
(byte)0x76, (byte)0x54, (byte)0x32, (byte)0x10, (byte)0x76, (byte)0x54, (byte)0x32, (byte)0x10,
(byte)0x89, (byte)0xab, (byte)0xcd, (byte)0xef, (byte)0x89, (byte)0xab, (byte)0xcd, (byte)0xef,
(byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67 (byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67
}; };
private static byte[] generateTestData(int size) { private static byte[] generateTestData(int size) {
return new byte[size]; return new byte[size];
}
private static void printProviderInfo(Provider provider) {
System.out.printf("%s version: %.1f%n", provider.getName(), provider.getVersion());
}
private static void printDeltaTable() {
/* Variables for table generation */
Map<String, Map<String, Double>> groupedResults;
String operation;
Map<String, Double> providerResults;
double wolfSpeed;
String provider;
double otherSpeed;
double deltaValue;
double deltaPercent;
boolean isRSAOperation;
System.out.println("\nPerformance Delta (compared to wolfJCE)");
System.out.println("-----------------------------------------------------------------------------");
System.out.println("| Operation | Provider | Delta | Delta |");
System.out.println("| | | Value* | (%) |");
System.out.println("|------------------------------------------|----------|----------|----------|");
/* Group results by operation */
groupedResults = new HashMap<>();
for (BenchmarkResult result : results) {
groupedResults
.computeIfAbsent(result.operation, k -> new HashMap<>())
.put(result.provider, result.throughput);
} }
/* Calculate and print deltas */ private static void printProviderInfo(Provider provider) {
for (Map.Entry<String, Map<String, Double>> entry : groupedResults.entrySet()) { System.out.printf("%s version: %.1f%n", provider.getName(), provider.getVersion());
operation = entry.getKey(); }
providerResults = entry.getValue();
wolfSpeed = providerResults.getOrDefault("wolfJCE", 0.0);
isRSAOperation = operation.startsWith("RSA");
for (Map.Entry<String, Double> providerEntry : providerResults.entrySet()) { private static void printDeltaTable() {
provider = providerEntry.getKey(); /* Variables for table generation */
if (!provider.equals("wolfJCE")) { Map<String, Map<String, Double>> groupedResults;
otherSpeed = providerEntry.getValue(); Map<String, Double> providerResults;
double wolfSpeed;
String provider;
double otherSpeed;
double deltaValue;
double deltaPercent;
if (isRSAOperation) { System.out.println("\nPerformance Delta (compared to wolfJCE)");
deltaValue = wolfSpeed - otherSpeed; System.out.println("-----------------------------------------------------------------------------");
deltaPercent = ((wolfSpeed / otherSpeed) - 1.0) * 100; System.out.println("| Operation | Provider | Delta | Delta |");
} else { System.out.println("| | | Value* | (%) |");
deltaValue = wolfSpeed - otherSpeed; System.out.println("|------------------------------------------|----------|----------|----------|");
deltaPercent = ((wolfSpeed / otherSpeed) - 1.0) * 100;
}
System.out.printf("| %-40s | %-8s | %+8.2f | %+8.1f |%n", /* Group results by operation */
operation, groupedResults = new HashMap<>();
provider, for (BenchmarkResult result : results) {
deltaValue, groupedResults
deltaPercent); .computeIfAbsent(result.operation, k -> new HashMap<>())
.put(result.provider, result.throughput);
} }
}
}
System.out.println("-----------------------------------------------------------------------------");
System.out.println("* Delta Value: MiB/s for symmetric ciphers, operations/second for RSA");
}
private static void runBenchmark(String algorithm, String mode, String padding, /* Sort operations to group RSA operations together */
List<String> sortedOperations = new ArrayList<>(groupedResults.keySet());
Collections.sort(sortedOperations, (a, b) -> {
boolean aIsRSA = a.startsWith("RSA");
boolean bIsRSA = b.startsWith("RSA");
if (aIsRSA && !bIsRSA) return -1;
if (!aIsRSA && bIsRSA) return 1;
return a.compareTo(b);
});
/* Calculate and print deltas */
for (String operation : sortedOperations) {
providerResults = groupedResults.get(operation);
wolfSpeed = providerResults.getOrDefault("wolfJCE", 0.0);
boolean isRSAOperation = operation.startsWith("RSA");
for (Map.Entry<String, Double> providerEntry : providerResults.entrySet()) {
provider = providerEntry.getKey();
if (!provider.equals("wolfJCE")) {
otherSpeed = providerEntry.getValue();
if (isRSAOperation) {
deltaValue = wolfSpeed - otherSpeed;
deltaPercent = ((wolfSpeed / otherSpeed) - 1.0) * 100;
} else {
deltaValue = wolfSpeed - otherSpeed;
deltaPercent = ((wolfSpeed / otherSpeed) - 1.0) * 100;
}
System.out.printf("| %-40s | %-8s | %+8.2f | %+8.1f |%n",
operation,
provider,
deltaValue,
deltaPercent);
}
}
}
System.out.println("-----------------------------------------------------------------------------");
System.out.println("* Delta Value: MiB/s for symmetric ciphers, operations/second for RSA");
}
private static void runEncDecBenchmark(String algorithm, String mode, String padding,
String providerName) throws Exception { String providerName) throws Exception {
SecretKey key; SecretKey key;
byte[] ivBytes; byte[] ivBytes;
AlgorithmParameterSpec params; AlgorithmParameterSpec params;
byte[] testData; byte[] testData;
byte[] encryptedData = null; byte[] encryptedData = null;
double dataSizeMiB; double dataSizeMiB;
Cipher cipher; Cipher cipher;
String cipherName = algorithm + "/" + mode + "/" + padding; String cipherName = algorithm + "/" + mode + "/" + padding;
/* Timing variables */ /* Timing variables */
long startTime; long startTime;
long endTime; long endTime;
long encryptTime; long encryptTime;
long decryptTime; long decryptTime;
double encryptThroughput; double encryptThroughput;
double decryptThroughput; double decryptThroughput;
double encryptTimeMS; double encryptTimeMS;
double decryptTimeMS; double decryptTimeMS;
/* Use appropriate key based on algorithm */ /* Use appropriate key based on algorithm */
if (algorithm.equals("AES")) { if (algorithm.equals("AES")) {
key = new SecretKeySpec(STATIC_AES_KEY, "AES"); key = new SecretKeySpec(STATIC_AES_KEY, "AES");
} else if (algorithm.equals("DESede")) { } else if (algorithm.equals("DESede")) {
key = new SecretKeySpec(STATIC_DES3_KEY, "DESede"); key = new SecretKeySpec(STATIC_DES3_KEY, "DESede");
} else { } else {
throw new IllegalArgumentException("Unsupported algorithm: " + algorithm); throw new IllegalArgumentException("Unsupported algorithm: " + algorithm);
}
/* Generate random IV */
SecureRandom secureRandom = new SecureRandom();
if (algorithm.equals("AES")){
ivBytes = new byte[AES_BLOCK_SIZE];
secureRandom.nextBytes(ivBytes);
} else if (algorithm.equals("DESede")) {
ivBytes = new byte[DES3_BLOCK_SIZE];
secureRandom.nextBytes(ivBytes);
} else {
throw new IllegalArgumentException("Unsupported algorithm: " + algorithm);
}
if (mode.equals("GCM")) {
params = new GCMParameterSpec(GCM_TAG_LENGTH, ivBytes);
} else {
params = new IvParameterSpec(ivBytes);
}
testData = generateTestData(DATA_SIZE);
/* Initialize cipher with specific provider */
cipher = Cipher.getInstance(cipherName, providerName);
/* Warm up phase */
for (int i = 0; i < WARMUP_ITERATIONS; i++) {
if (mode.equals("GCM")) {
secureRandom.nextBytes(ivBytes);
params = new GCMParameterSpec(GCM_TAG_LENGTH, ivBytes);
}
cipher.init(Cipher.ENCRYPT_MODE, key, params);
encryptedData = cipher.doFinal(testData);
cipher.init(Cipher.DECRYPT_MODE, key, params);
cipher.doFinal(encryptedData);
}
/* Benchmark encryption */
startTime = System.nanoTime();
for (int i = 0; i < TEST_ITERATIONS; i++) {
if (mode.equals("GCM")) {
secureRandom.nextBytes(ivBytes);
params = new GCMParameterSpec(GCM_TAG_LENGTH, ivBytes);
}
cipher.init(Cipher.ENCRYPT_MODE, key, params);
encryptedData = cipher.doFinal(testData);
}
endTime = System.nanoTime();
encryptTime = (endTime - startTime) / TEST_ITERATIONS;
dataSizeMiB = (DATA_SIZE * TEST_ITERATIONS) / (1024.0 * 1024.0);
encryptTimeMS = encryptTime / 1000000.0;
encryptThroughput = (DATA_SIZE / (encryptTime / 1000000000.0)) / (1024.0 * 1024.0);
String testName = String.format("%s (%s)", cipherName, providerName);
System.out.printf("| %-40s | %8.3f | %8.3f | %8.3f |%n",
testName + " enc", dataSizeMiB, encryptTimeMS, encryptThroughput);
results.add(new BenchmarkResult(providerName, cipherName + " enc", encryptThroughput));
/* Benchmark decryption */
startTime = System.nanoTime();
for (int i = 0; i < TEST_ITERATIONS; i++) {
cipher.init(Cipher.DECRYPT_MODE, key, params);
cipher.doFinal(encryptedData);
}
endTime = System.nanoTime();
decryptTime = (endTime - startTime) / TEST_ITERATIONS;
decryptTimeMS = decryptTime / 1000000.0;
decryptThroughput = (DATA_SIZE / (decryptTime / 1000000000.0)) / (1024.0 * 1024.0);
System.out.printf("| %-40s | %8.3f | %8.3f | %8.3f |%n",
testName + " dec", dataSizeMiB, decryptTimeMS, decryptThroughput);
/* Store decryption result */
results.add(new BenchmarkResult(providerName, cipherName + " dec", decryptThroughput));
}
/* Print RSA results in simpler format */
private static void printRSAResults(int operations, double totalTime, String operation,
String providerName) {
double avgTimeMs = (totalTime * 1000.0) / operations;
double opsPerSec = operations / totalTime;
System.out.printf("%-12s %-8s %8d ops took %.3f sec, avg %.3f ms, %.3f ops/sec%n",
operation,
" ",
operations,
totalTime,
avgTimeMs,
opsPerSec);
/* Store results for delta table */
results.add(new BenchmarkResult(providerName, operation, opsPerSec));
}
/* Run RSA benchmarks */
private static void runRSABenchmark(String providerName, int keySize) throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", providerName);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", providerName);
byte[] testData = generateTestData(SMALL_MESSAGE_SIZE);
/* Key Generation benchmark */
keyGen.initialize(keySize);
int keyGenOps = 0;
long startTime = System.nanoTime();
double elapsedTime;
do {
keyGen.generateKeyPair();
keyGenOps++;
elapsedTime = (System.nanoTime() - startTime) / 1_000_000_000.0;
} while (elapsedTime < RSA_MIN_TIME_SECONDS);
String keyGenOp = String.format("RSA %d key gen", keySize);
printRSAResults(keyGenOps, elapsedTime, keyGenOp, providerName);
/* For 2048-bit keys, also test public/private operations */
if (keySize == 2048) {
KeyPair keyPair = keyGen.generateKeyPair();
/* Public key operations */
int publicOps = 0;
startTime = System.nanoTime();
do {
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
cipher.doFinal(testData);
publicOps++;
elapsedTime = (System.nanoTime() - startTime) / 1_000_000_000.0;
} while (elapsedTime < RSA_MIN_TIME_SECONDS);
printRSAResults(publicOps, elapsedTime, "RSA 2048 public", providerName);
/* Private key operations */
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
byte[] encrypted = cipher.doFinal(testData);
int privateOps = 0;
startTime = System.nanoTime();
do {
cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
cipher.doFinal(encrypted);
privateOps++;
elapsedTime = (System.nanoTime() - startTime) / 1_000_000_000.0;
} while (elapsedTime < RSA_MIN_TIME_SECONDS);
printRSAResults(privateOps, elapsedTime, "RSA 2048 private", providerName);
}
}
public static void main(String[] args) {
try {
/* Check if Bouncy Castle is available */
boolean hasBouncyCastle = false;
Provider bcProvider = null;
try {
Class<?> bcClass = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");
bcProvider = (Provider) bcClass.getDeclaredConstructor().newInstance();
hasBouncyCastle = true;
} catch (Exception e) {
/* Bouncy Castle not available */
}
/* Create provider list based on availability */
java.util.List<Provider> providerList = new java.util.ArrayList<>();
java.util.List<String> providerNameList = new java.util.ArrayList<>();
providerList.add(new WolfCryptProvider());
providerNameList.add("wolfJCE");
providerList.add(new com.sun.crypto.provider.SunJCE());
providerNameList.add("SunJCE");
if (hasBouncyCastle && bcProvider != null) {
providerList.add(bcProvider);
providerNameList.add("BC");
}
Provider[] providers = providerList.toArray(new Provider[0]);
String[] providerNames = providerNameList.toArray(new String[0]);
/* Print provider versions */
for (Provider provider : providers) {
printProviderInfo(provider);
}
System.out.println("-----------------------------------------------------------------------------");
System.out.println(" Symmetric Cipher Benchmark");
System.out.println("-----------------------------------------------------------------------------");
System.out.println("| Operation | Size MiB | ms | MiB/s |");
System.out.println("|------------------------------------------|----------|----------|----------|");
/* Run symmetric benchmarks */
for (int i = 0; i < providers.length; i++) {
Security.insertProviderAt(providers[i], 1);
runBenchmark("AES", "CBC", "NoPadding", providerNames[i]);
runBenchmark("AES", "CBC", "PKCS5Padding", providerNames[i]);
runBenchmark("AES", "GCM", "NoPadding", providerNames[i]);
if (FeatureDetect.Des3Enabled()) {
runBenchmark("DESede", "CBC", "NoPadding", providerNames[i]);
} }
if (i < providers.length - 1) { /* Generate random IV */
System.out.println("|------------------------------------------|----------|----------|----------|"); SecureRandom secureRandom = new SecureRandom();
if (algorithm.equals("AES")){
ivBytes = new byte[AES_BLOCK_SIZE];
secureRandom.nextBytes(ivBytes);
} else if (algorithm.equals("DESede")) {
ivBytes = new byte[DES3_BLOCK_SIZE];
secureRandom.nextBytes(ivBytes);
} else {
throw new IllegalArgumentException("Unsupported algorithm: " + algorithm);
} }
Security.removeProvider(providers[i].getName()); if (mode.equals("GCM")) {
} params = new GCMParameterSpec(GCM_TAG_LENGTH, ivBytes);
} else {
System.out.println("-----------------------------------------------------------------------------"); params = new IvParameterSpec(ivBytes);
/* Run RSA benchmarks */
System.out.println("\nRSA Benchmark Results");
System.out.println("-----------------------------------------------------------------------------");
for (Provider provider : providers) {
if (!provider.getName().equals("SunJCE")) {
Security.insertProviderAt(provider, 1);
System.out.println("\n" + provider.getName() + ":");
for (int keySize : RSA_KEY_SIZES) {
runRSABenchmark(provider.getName(), keySize);
}
Security.removeProvider(provider.getName());
} }
}
System.out.println("-----------------------------------------------------------------------------"); testData = generateTestData(DATA_SIZE);
/* Print delta table */ /* Initialize cipher with specific provider */
printDeltaTable(); cipher = Cipher.getInstance(cipherName, providerName);
} catch (Exception e) { /* Warm up phase */
System.err.println("Benchmark failed: " + e.getMessage()); for (int i = 0; i < WARMUP_ITERATIONS; i++) {
e.printStackTrace(); if (mode.equals("GCM")) {
secureRandom.nextBytes(ivBytes);
params = new GCMParameterSpec(GCM_TAG_LENGTH, ivBytes);
}
cipher.init(Cipher.ENCRYPT_MODE, key, params);
encryptedData = cipher.doFinal(testData);
cipher.init(Cipher.DECRYPT_MODE, key, params);
cipher.doFinal(encryptedData);
}
/* Benchmark encryption */
startTime = System.nanoTime();
for (int i = 0; i < TEST_ITERATIONS; i++) {
if (mode.equals("GCM")) {
secureRandom.nextBytes(ivBytes);
params = new GCMParameterSpec(GCM_TAG_LENGTH, ivBytes);
}
cipher.init(Cipher.ENCRYPT_MODE, key, params);
encryptedData = cipher.doFinal(testData);
}
endTime = System.nanoTime();
encryptTime = (endTime - startTime) / TEST_ITERATIONS;
dataSizeMiB = (DATA_SIZE * TEST_ITERATIONS) / (1024.0 * 1024.0);
encryptTimeMS = encryptTime / 1000000.0;
encryptThroughput = (DATA_SIZE / (encryptTime / 1000000000.0)) / (1024.0 * 1024.0);
String testName = String.format("%s (%s)", cipherName, providerName);
System.out.printf("| %-40s | %8.3f | %8.3f | %8.3f |%n",
testName + " enc", dataSizeMiB, encryptTimeMS, encryptThroughput);
results.add(new BenchmarkResult(providerName, cipherName + " enc", encryptThroughput));
/* Benchmark decryption */
startTime = System.nanoTime();
for (int i = 0; i < TEST_ITERATIONS; i++) {
cipher.init(Cipher.DECRYPT_MODE, key, params);
cipher.doFinal(encryptedData);
}
endTime = System.nanoTime();
decryptTime = (endTime - startTime) / TEST_ITERATIONS;
decryptTimeMS = decryptTime / 1000000.0;
decryptThroughput = (DATA_SIZE / (decryptTime / 1000000000.0)) / (1024.0 * 1024.0);
System.out.printf("| %-40s | %8.3f | %8.3f | %8.3f |%n",
testName + " dec", dataSizeMiB, decryptTimeMS, decryptThroughput);
/* Store decryption result */
results.add(new BenchmarkResult(providerName, cipherName + " dec", decryptThroughput));
}
/* Print RSA results in simpler format */
private static void printRSAResults(int operations, double totalTime, String operation,
String providerName, String mode) {
/* Variables for result calculations */
double avgTimeMs;
double opsPerSec;
/* Calculate metrics */
avgTimeMs = (totalTime * 1000.0) / operations;
opsPerSec = operations / totalTime;
/* Print formatted results */
System.out.printf("%-12s %-8s %8d ops took %.3f sec, avg %.3f ms, %.3f ops/sec%n",
operation,
" ",
operations,
totalTime,
avgTimeMs,
opsPerSec);
/* Store results for delta table */
String fullOperation = String.format("%s (%s)", operation, mode);
results.add(new BenchmarkResult(providerName, fullOperation, opsPerSec));
}
/* Run RSA benchmarks for specified provider and key size */
private static void runRSABenchmark(String providerName, int keySize) throws Exception {
/* Variables for benchmark operations */
KeyPairGenerator keyGen;
Cipher cipher;
byte[] testData;
int keyGenOps;
long startTime;
double elapsedTime;
KeyPair keyPair;
int publicOps;
int privateOps;
byte[] encrypted;
String keyGenOp;
String cipherMode = "RSA/ECB/PKCS1Padding";
/* Initialize key generator and cipher */
keyGen = KeyPairGenerator.getInstance("RSA", providerName);
cipher = Cipher.getInstance(cipherMode, providerName);
testData = generateTestData(SMALL_MESSAGE_SIZE);
/* Key Generation benchmark */
keyGen.initialize(keySize);
keyGenOps = 0;
startTime = System.nanoTime();
elapsedTime = 0;
/* Run key generation benchmark */
do {
keyGen.generateKeyPair();
keyGenOps++;
elapsedTime = (System.nanoTime() - startTime) / 1_000_000_000.0;
} while (elapsedTime < RSA_MIN_TIME_SECONDS);
keyGenOp = String.format("RSA %d key gen", keySize);
printRSAResults(keyGenOps, elapsedTime, keyGenOp, providerName, cipherMode);
/* For 2048-bit keys, test public/private operations */
if (keySize == 2048) {
/* Generate key pair for public/private operations */
keyPair = keyGen.generateKeyPair();
/* Public key operations benchmark */
publicOps = 0;
startTime = System.nanoTime();
do {
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
cipher.doFinal(testData);
publicOps++;
elapsedTime = (System.nanoTime() - startTime) / 1_000_000_000.0;
} while (elapsedTime < RSA_MIN_TIME_SECONDS);
printRSAResults(publicOps, elapsedTime, "RSA 2048 public", providerName, cipherMode);
/* Private key operations benchmark */
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
encrypted = cipher.doFinal(testData);
privateOps = 0;
startTime = System.nanoTime();
do {
cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
cipher.doFinal(encrypted);
privateOps++;
elapsedTime = (System.nanoTime() - startTime) / 1_000_000_000.0;
} while (elapsedTime < RSA_MIN_TIME_SECONDS);
printRSAResults(privateOps, elapsedTime, "RSA 2048 private", providerName, cipherMode);
}
}
public static void main(String[] args) {
try {
/* Check if Bouncy Castle is available */
boolean hasBouncyCastle = false;
Provider bcProvider = null;
try {
Class<?> bcClass = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");
bcProvider = (Provider) bcClass.getDeclaredConstructor().newInstance();
hasBouncyCastle = true;
} catch (Exception e) {
/* Bouncy Castle not available */
}
/* Create provider list based on availability */
java.util.List<Provider> providerList = new java.util.ArrayList<>();
java.util.List<String> providerNameList = new java.util.ArrayList<>();
providerList.add(new WolfCryptProvider());
providerNameList.add("wolfJCE");
providerList.add(new com.sun.crypto.provider.SunJCE());
providerNameList.add("SunJCE");
if (hasBouncyCastle && bcProvider != null) {
providerList.add(bcProvider);
providerNameList.add("BC");
}
Provider[] providers = providerList.toArray(new Provider[0]);
String[] providerNames = providerNameList.toArray(new String[0]);
/* Print provider versions */
for (Provider provider : providers) {
printProviderInfo(provider);
}
System.out.println("-----------------------------------------------------------------------------");
System.out.println(" Symmetric Cipher Benchmark");
System.out.println("-----------------------------------------------------------------------------");
System.out.println("| Operation | Size MiB | ms | MiB/s |");
System.out.println("|------------------------------------------|----------|----------|----------|");
/* Run symmetric benchmarks */
for (int i = 0; i < providers.length; i++) {
Security.insertProviderAt(providers[i], 1);
runEncDecBenchmark("AES", "CBC", "NoPadding", providerNames[i]);
runEncDecBenchmark("AES", "CBC", "PKCS5Padding", providerNames[i]);
runEncDecBenchmark("AES", "GCM", "NoPadding", providerNames[i]);
if (FeatureDetect.Des3Enabled()) {
runEncDecBenchmark("DESede", "CBC", "NoPadding", providerNames[i]);
}
if (i < providers.length - 1) {
System.out.println("|------------------------------------------|----------|----------|----------|");
}
Security.removeProvider(providers[i].getName());
}
System.out.println("-----------------------------------------------------------------------------");
/* Run RSA benchmarks */
System.out.println("\nRSA Benchmark Results");
System.out.println("-----------------------------------------------------------------------------");
for (Provider provider : providers) {
if (!provider.getName().equals("SunJCE")) {
Security.insertProviderAt(provider, 1);
System.out.println("\n" + provider.getName() + ":");
for (int keySize : RSA_KEY_SIZES) {
runRSABenchmark(provider.getName(), keySize);
}
Security.removeProvider(provider.getName());
}
}
System.out.println("-----------------------------------------------------------------------------");
/* Print delta table */
printDeltaTable();
} catch (Exception e) {
System.err.println("Benchmark failed: " + e.getMessage());
e.printStackTrace();
}
} }
}
} }