JCE: implements AES-GCM benchmark and modify test sizes in crypto benchmark

pull/89/head
Jack Tjaden 2024-12-27 12:12:24 -06:00
parent 005e5f2bee
commit 8ddb01f1ee
1 changed files with 90 additions and 74 deletions

View File

@ -1,45 +1,61 @@
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.KeyGenerator; import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Provider; import java.security.Provider;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.Security; import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays; import java.util.Arrays;
import com.wolfssl.provider.jce.WolfCryptProvider; import com.wolfssl.provider.jce.WolfCryptProvider;
public class CryptoBenchmark { public class CryptoBenchmark {
/* Constants for benchmark configuration */ /* Constants for benchmark configuration */
private static final int WARMUP_ITERATIONS = 1000; private static final int WARMUP_ITERATIONS = 5;
private static final int TEST_ITERATIONS = 10000; private static final int TEST_ITERATIONS = 5; /* Number of iterations */
private static final int DATA_SIZE = 16384; /* 16KB of data */ 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 GCM_TAG_LENGTH = 128; /* GCM auth tag length in bits */
private static final int AES_KEY_SIZE = 256; private static final int AES_KEY_SIZE = 256;
private static byte[] generateRandomData(int size) { /* Static key and IV buffers */
byte[] data = new byte[size]; private static final byte[] STATIC_KEY = new byte[] {
new SecureRandom().nextBytes(data); (byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67,
return data; (byte)0x89, (byte)0xab, (byte)0xcd, (byte)0xef,
(byte)0xfe, (byte)0xde, (byte)0xba, (byte)0x98,
(byte)0x76, (byte)0x54, (byte)0x32, (byte)0x10,
(byte)0x89, (byte)0xab, (byte)0xcd, (byte)0xef,
(byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67,
(byte)0xf0, (byte)0xf1, (byte)0xf2, (byte)0xf3,
(byte)0xf4, (byte)0xf5, (byte)0xf6, (byte)0xf7
};
private static final byte[] STATIC_IV = new byte[] {
(byte)0x12, (byte)0x34, (byte)0x56, (byte)0x78,
(byte)0x90, (byte)0xab, (byte)0xcd, (byte)0xef,
(byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01,
(byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01
};
private static byte[] generateTestData(int size) {
return new byte[size]; /* Creates array initialized with zeros */
} }
/* private static void runBenchmark(String algorithm, String mode) throws Exception {
* Benchmarks Cipher class operations using AES-CBC
* Returns array containing encrypt and decrypt times in nanoseconds
*/
private static void benchmarkCipher() throws Exception {
/* Key generation variables */ /* Key generation variables */
KeyGenerator keyGen;
SecretKey key; SecretKey key;
/* IV generation variables */ /* IV/Nonce generation variables */
byte[] ivBytes; byte[] ivBytes;
IvParameterSpec iv; /* Using specific type instead of Object */
AlgorithmParameterSpec params;
/* Test data variables */ /* Test data variables */
byte[] testData; byte[] testData;
byte[] encryptedData; byte[] encryptedData = null;
byte[] encrypted; double dataSizeMiB;
/* Cipher variables */ /* Cipher variables */
Cipher cipher; Cipher cipher;
@ -51,81 +67,76 @@ public class CryptoBenchmark {
long decryptTime; long decryptTime;
double encryptThroughput; double encryptThroughput;
double decryptThroughput; double decryptThroughput;
double encryptTimeMS;
/* Provider info */ double decryptTimeMS;
Provider provider;
/* Generate a random key and IV */ /* Use static pre-made key */
keyGen = KeyGenerator.getInstance("AES"); key = new SecretKeySpec(STATIC_KEY, "AES");
keyGen.init(AES_KEY_SIZE);
key = keyGen.generateKey();
ivBytes = new byte[AES_BLOCK_SIZE]; /* Use static pre-made IV */
new SecureRandom().nextBytes(ivBytes); ivBytes = STATIC_IV;
iv = new IvParameterSpec(ivBytes); if (mode.equals("GCM")) {
params = new GCMParameterSpec(GCM_TAG_LENGTH, ivBytes);
/* Generate random test data */ } else {
testData = generateRandomData(DATA_SIZE); params = new IvParameterSpec(ivBytes);
/* Initialize cipher for warmup */
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
/* Warm up phase */
System.out.println("Warming up...");
for (int i = 0; i < WARMUP_ITERATIONS; i++) {
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
encrypted = cipher.doFinal(testData);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
cipher.doFinal(encrypted);
} }
System.out.println("\nBenchmarking AES-CBC (" + AES_KEY_SIZE + "-bit key) with " + /* Generate test data filled with zeros */
DATA_SIZE + " bytes:"); testData = generateTestData(DATA_SIZE);
System.out.println("Iterations per test: " + TEST_ITERATIONS);
/* Initialize cipher */
cipher = Cipher.getInstance(algorithm);
/* Warm up phase */
for (int i = 0; i < WARMUP_ITERATIONS; i++) {
cipher.init(Cipher.ENCRYPT_MODE, key, params);
encryptedData = cipher.doFinal(testData);
cipher.init(Cipher.DECRYPT_MODE, key, params);
cipher.doFinal(encryptedData);
}
/* Benchmark encryption */ /* Benchmark encryption */
startTime = System.nanoTime(); startTime = System.nanoTime();
for (int i = 0; i < TEST_ITERATIONS; i++) { for (int i = 0; i < TEST_ITERATIONS; i++) {
cipher.init(Cipher.ENCRYPT_MODE, key, iv); cipher.init(Cipher.ENCRYPT_MODE, key, params);
cipher.doFinal(testData); encryptedData = cipher.doFinal(testData);
} }
endTime = System.nanoTime(); endTime = System.nanoTime();
encryptTime = (endTime - startTime) / TEST_ITERATIONS; encryptTime = (endTime - startTime) / TEST_ITERATIONS;
/* Benchmark decryption */ /* Calculate data size in MiB */
cipher.init(Cipher.ENCRYPT_MODE, key, iv); dataSizeMiB = (DATA_SIZE * TEST_ITERATIONS) / (1024.0 * 1024.0);
encryptedData = cipher.doFinal(testData);
/* Calculate time in milliseconds */
encryptTimeMS = encryptTime / 1000000.0;
/* Calculate throughput using seconds for MiB/s */
encryptThroughput = (DATA_SIZE / (encryptTime / 1000000000.0)) / (1024.0 * 1024.0);
/* Print encryption results immediately */
String testName = "AES-256-" + mode;
System.out.printf("%s-enc %4.2f MiB took %1.3f ms, %8.3f MiB/s%n",
testName, dataSizeMiB, encryptTimeMS, encryptThroughput);
/* Benchmark decryption using the encrypted data from encryption benchmark */
startTime = System.nanoTime(); startTime = System.nanoTime();
for (int i = 0; i < TEST_ITERATIONS; i++) { for (int i = 0; i < TEST_ITERATIONS; i++) {
cipher.init(Cipher.DECRYPT_MODE, key, iv); cipher.init(Cipher.DECRYPT_MODE, key, params);
cipher.doFinal(encryptedData); cipher.doFinal(encryptedData);
} }
endTime = System.nanoTime(); endTime = System.nanoTime();
decryptTime = (endTime - startTime) / TEST_ITERATIONS; decryptTime = (endTime - startTime) / TEST_ITERATIONS;
/* Print results */ /* Calculate time in milliseconds */
System.out.println("\nResults (average time per operation):"); decryptTimeMS = decryptTime / 1000000.0;
System.out.println(" Encryption: " + encryptTime + " ns (" +
String.format("%.2f", encryptTime/1000000.0) + " ms)");
System.out.println(" Decryption: " + decryptTime + " ns (" +
String.format("%.2f", decryptTime/1000000.0) + " ms)");
/* Calculate and print throughput */ /* Calculate throughput using seconds for MiB/s */
encryptThroughput = (DATA_SIZE / (encryptTime / 1000000000.0)) / (1024 * 1024); decryptThroughput = (DATA_SIZE / (decryptTime / 1000000000.0)) / (1024.0 * 1024.0);
decryptThroughput = (DATA_SIZE / (decryptTime / 1000000000.0)) / (1024 * 1024);
System.out.println("\nThroughput:");
System.out.println(" Encryption: " + String.format("%.2f", encryptThroughput) + " MB/s");
System.out.println(" Decryption: " + String.format("%.2f", decryptThroughput) + " MB/s");
/* Print provider information */ /* Print decryption results immediately */
provider = Security.getProvider(cipher.getProvider().getName()); System.out.printf("%s-dec %4.2f MiB took %1.3f ms, %8.3f MiB/s%n",
System.out.println("\nProvider Information:"); testName, dataSizeMiB, decryptTimeMS, decryptThroughput);
System.out.println(" Name: " + provider.getName());
System.out.println(" Version: " + provider.getVersion());
System.out.println(" Info: " + provider.getInfo());
} }
public static void main(String[] args) { public static void main(String[] args) {
@ -133,8 +144,13 @@ public class CryptoBenchmark {
/* Register wolfJCE as the default provider */ /* Register wolfJCE as the default provider */
Security.insertProviderAt(new WolfCryptProvider(), 1); Security.insertProviderAt(new WolfCryptProvider(), 1);
/* Run Cipher benchmark */ System.out.println("------------------------------------------------------------------------------");
benchmarkCipher(); System.out.println(" JCE Crypto Benchmark");
System.out.println("------------------------------------------------------------------------------");
/* Run benchmarks for different algorithms */
runBenchmark("AES/CBC/PKCS5Padding", "CBC");
runBenchmark("AES/GCM/NoPadding", "GCM");
} catch (Exception e) { } catch (Exception e) {
System.err.println("Benchmark failed: " + e.getMessage()); System.err.println("Benchmark failed: " + e.getMessage());