- updated and added tests
- replaced junit EnumSource with ArgumentsSource in CryptoUtilJ8ParameterizedTest
(automatically converts to provided argument enum by JUnit Argument Conversion)
- check system ciphers in test and cli info (printInfo)
- dynamic clear code in CryptoParametersJ8
- fixes and cleanup of typed instances CryptoUtilJ8 and CryptoStreamFactoryJ8Template
- added documentation
git-svn-id: https://svn.apache.org/repos/asf/turbine/fulcrum/trunk/yaafi-crypto@1880199 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index bb8e321..7556de7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,8 +20,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>turbine-parent</artifactId>
- <groupId>org.apache.turbine</groupId>
- <version>7</version>
+ <groupId>org.apache.turbine</groupId>
+ <version>7</version>
+ <relativePath />
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -206,6 +207,15 @@
</executions>
</plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <forkCount>1</forkCount>
+ <reuseFork>true</reuseFork>
+ </configuration>
+ </plugin>
</plugins>
</build>
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 35ed3d8..edd24a1 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -25,6 +25,9 @@
<body>
<release version="1.0.8" date="as in SVN">
+ <action dev="gk" type="update">
+ Updated Tests using Junit extension. More flexible comman line utility, defining CLI2 as manifest main class. Fine tuning clear code prefix and added integration-test
+ </action>
<action dev="gk" type="update">
Added two Java 8 implementations based on PBE/AES (PBEWithHmacSHA256AndAES_256) or GCM (AES/GCM/NoPadding) encryption.
</action>
diff --git a/src/filters/filter-integration-test.properties b/src/filters/filter-integration-test.properties
index f49b270..b08a2f5 100644
--- a/src/filters/filter-integration-test.properties
+++ b/src/filters/filter-integration-test.properties
@@ -1,2 +1,2 @@
-#Mon, 20 Jul 2020 13:46:30 +0200
-password_encrypted=1796bc2d3d02f478bb042ed24740e98a2654fa47bd331266e1a7b682c2d37a2d0254dc61dd71badfe1c22b745f039041
+#Thu, 23 Jul 2020 13:53:53 +0200
+password_encrypted=0e88b1ae1cc8bcee9df12575805fbb770d70123259929778998a8285730b1d53453632a50fd9cac77d8a8f1603b622f4
diff --git a/src/java/org/apache/fulcrum/jce/crypto/CryptoStreamFactoryImpl.java b/src/java/org/apache/fulcrum/jce/crypto/CryptoStreamFactoryImpl.java
index 3e27a33..609d0a6 100644
--- a/src/java/org/apache/fulcrum/jce/crypto/CryptoStreamFactoryImpl.java
+++ b/src/java/org/apache/fulcrum/jce/crypto/CryptoStreamFactoryImpl.java
@@ -122,6 +122,27 @@
this.providerName = PROVIDERNAME;
this.algorithm = CryptoParameters.ALGORITHM;
}
+
+
+ /**
+ * Factory method to get a default instance
+ *
+ * @param salt the salt for the PBE algorithm
+ * @param count the iteration for PBEParameterSpec
+ * @return an instance of the CryptoStreamFactory
+ *
+ */
+ public static CryptoStreamFactory getInstance( byte[] salt, int count)
+ {
+ synchronized(CryptoStreamFactoryImpl.class ) {
+ if( CryptoStreamFactoryImpl.instance == null )
+ {
+ CryptoStreamFactoryImpl.instance = new CryptoStreamFactoryImpl(salt, count);
+ }
+
+ return CryptoStreamFactoryImpl.instance;
+ }
+ }
/**
* @see org.apache.fulcrum.jce.crypto.CryptoStreamFactory#getSmartInputStream(java.io.InputStream,char[])
diff --git a/src/java/org/apache/fulcrum/jce/crypto/CryptoUtil.java b/src/java/org/apache/fulcrum/jce/crypto/CryptoUtil.java
index 81f8d3a..7272f76 100644
--- a/src/java/org/apache/fulcrum/jce/crypto/CryptoUtil.java
+++ b/src/java/org/apache/fulcrum/jce/crypto/CryptoUtil.java
@@ -26,6 +26,8 @@
import java.security.GeneralSecurityException;
import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8;
+import org.apache.fulcrum.jce.crypto.extended.CryptoStreamFactoryJ8Template;
+import org.apache.fulcrum.jce.crypto.extended.CryptoUtilJ8;
/**
* Helper class to provde generic functions to work with CryptoStreams.
@@ -43,7 +45,7 @@
private static CryptoUtil instance;
- private CryptoStreamFactory cryptoStreamFactory;
+ protected CryptoStreamFactory cryptoStreamFactory;
/**
* Factory method to get a default instance
@@ -64,6 +66,29 @@
protected CryptoUtil() {
cryptoStreamFactory = CryptoStreamFactoryImpl.getInstance();
}
+
+ /**
+ * Factory method to get a default instance
+ *
+ * @param salt the salt for the PBE algorithm
+ * @param count the iteration for PBEParameterSpec
+ * @return an instance of the CryptoUtil
+ */
+ public synchronized static CryptoUtil getInstance(byte[] salt, int count) {
+ if (CryptoUtil.instance == null) {
+ CryptoUtil.instance = new CryptoUtil(salt, count);
+ }
+
+ return CryptoUtil.instance;
+ }
+
+ /**
+ * @param salt the salt for the PBE algorithm
+ * @param count the iteration for PBEParameterSpec
+ */
+ protected CryptoUtil(byte[] salt, int count) {
+ cryptoStreamFactory = CryptoStreamFactoryImpl.getInstance(salt, count);
+ }
/**
* Copies from a source to a target object using encryption
@@ -100,7 +125,7 @@
/**
- * Encrypts a string into a hex string using {@link CryptoParametersJ8#CLEAR_CODE_J8}
+ * Encrypts a string into a hex string using {@link CryptoParametersJ8#CLEAR_CODE_DEFAULT}
*
* @param plainText the plain text to be encrypted
* @param password the password for encryption
@@ -138,10 +163,12 @@
*/
public String encryptString(CryptoStreamFactory factory, String plainText, char[] password, boolean withClearCode)
throws GeneralSecurityException, IOException {
- ByteArrayOutputStream bais = new ByteArrayOutputStream();
- encrypt(factory, plainText, bais, password);
- return (withClearCode)? CryptoParametersJ8.CLEAR_CODE_J8 + HexConverter.toString(bais.toByteArray()):
- HexConverter.toString(bais.toByteArray());
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ encrypt(factory, plainText, baos, password);
+ String prefix = (withClearCode)? (this instanceof CryptoUtilJ8)?
+ ((CryptoStreamFactoryJ8Template)((CryptoUtilJ8)this).getCryptoStreamFactory()).getType().getClearCode()
+ : CryptoParametersJ8.CLEAR_CODE_DEFAULT: "";
+ return prefix + HexConverter.toString(baos.toByteArray());
}
/**
@@ -161,7 +188,9 @@
* Decrypts an encrypted string into the plain text. The encrypted string must
* be a hex string created by encryptString.
*
- * Decrypts encrypted text after {@link CryptoParametersJ8#CLEAR_CODE_J8}.
+ * Decrypts encrypted text after {@link CryptoParametersJ8#CLEAR_CODE_DEFAULT}.
+ *
+ * Removes ClearCode length of 10 bit, before decrpyting expected as prefix.
*
* @param cipherText the encrypted text to be decrypted
* @param password the password for decryption
@@ -170,7 +199,7 @@
* @throws IOException accessing the souce failed
*/
public String decryptStringWithClearCode(String cipherText, char[] password) throws GeneralSecurityException, IOException {
- return decryptString(getCryptoStreamFactory(), cipherText.substring(CryptoParametersJ8.CLEAR_CODE_J8.length()), password);
+ return decryptString(getCryptoStreamFactory(), cipherText.substring(10), password);
}
/**
@@ -200,7 +229,7 @@
*/
public String decryptString(String cipherText, char[] password, boolean withClearCode) throws GeneralSecurityException, IOException {
return decryptString(getCryptoStreamFactory(), withClearCode?
- cipherText.substring(CryptoParametersJ8.CLEAR_CODE_J8.length()):
+ cipherText.substring(CryptoParametersJ8.CLEAR_CODE_DEFAULT.length()):
cipherText, password);
}
diff --git a/src/java/org/apache/fulcrum/jce/crypto/algo/CryptoStreamGCMImpl.java b/src/java/org/apache/fulcrum/jce/crypto/algo/CryptoStreamGCMImpl.java
index f8bc29d..0fad268 100644
--- a/src/java/org/apache/fulcrum/jce/crypto/algo/CryptoStreamGCMImpl.java
+++ b/src/java/org/apache/fulcrum/jce/crypto/algo/CryptoStreamGCMImpl.java
@@ -69,24 +69,21 @@
*/
public CryptoStreamGCMImpl() throws GeneralSecurityException
{
- this.salt = generateSalt();
- this.providerName = PROVIDERNAME;
- this.algorithm = CryptoParametersJ8.TYPES_IMPL.ALGORITHM_J8_GCM.getAlgorithm();
+ this(generateSalt());
}
/**
* Constructor
*
- * @param salt the salt for the PBE algorithm
- * @param count the iteration for PBEParameterSpec
+ * @param salt the salt for the GCM algorithm
*/
- public CryptoStreamGCMImpl( byte[] salt, int count)
+ public CryptoStreamGCMImpl( byte[] salt)
{
- this.salt = salt.clone();
- this.count = count;
+ setSalt(salt);
this.providerName = PROVIDERNAME;
+ setType(TYPES.GCM);
this.algorithm = CryptoParametersJ8.TYPES_IMPL.ALGORITHM_J8_GCM.getAlgorithm();
}
@@ -102,7 +99,6 @@
protected Key createKey( char[] password, byte[] salt )
throws GeneralSecurityException
{
-
SecretKey key = new SecretKeySpec(((salt == null)? this.getSalt(): salt.clone()), "AES");
return key;
}
diff --git a/src/java/org/apache/fulcrum/jce/crypto/algo/CryptoStreamPBEImpl.java b/src/java/org/apache/fulcrum/jce/crypto/algo/CryptoStreamPBEImpl.java
index 12d1f15..adc1603 100644
--- a/src/java/org/apache/fulcrum/jce/crypto/algo/CryptoStreamPBEImpl.java
+++ b/src/java/org/apache/fulcrum/jce/crypto/algo/CryptoStreamPBEImpl.java
@@ -31,7 +31,6 @@
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
@@ -69,34 +68,48 @@
protected static final int IV_SIZE = 16;
+ protected static final int KEY_SIZE = 256;
+
/**
* default count for pbe spec
*/
- protected int COUNT_J8 = 10_000; // 200_000;
+ protected static final int COUNT_J8 = 10_000; // 200_000;
/**
* Constructor
+ * count is set to {@link #COUNT_J8}.
+ *
* @throws GeneralSecurityException if no algo could be found.
*/
public CryptoStreamPBEImpl() throws GeneralSecurityException
{
- this.salt = generateSalt();
- this.count = COUNT_J8;
- this.providerName = PROVIDERNAME;
- this.algorithm = CryptoParametersJ8.TYPES_IMPL.ALGORITHM_J8_PBE.getAlgorithm();
+ this(generateSalt(), COUNT_J8);
}
/**
* Constructor
*
* @param salt the salt for the PBE algorithm
+ */
+ public CryptoStreamPBEImpl( byte[] salt)
+ {
+ this(salt, COUNT_J8);
+
+ }
+
+
+ /**
+ * Constructor
+ *
+ * @param salt the salt for the PBE algorithm
* @param count the iteration for PBEParameterSpec
*/
public CryptoStreamPBEImpl( byte[] salt, int count)
{
- this.salt = salt.clone();
+ setSalt(salt);
this.count = count;
this.providerName = PROVIDERNAME;
+ setType(TYPES.PBE);
this.algorithm = CryptoParametersJ8.TYPES_IMPL.ALGORITHM_J8_PBE.getAlgorithm();
}
diff --git a/src/java/org/apache/fulcrum/jce/crypto/cli/CLI2.java b/src/java/org/apache/fulcrum/jce/crypto/cli/CLI2.java
index 4c7989c..e6ba487 100644
--- a/src/java/org/apache/fulcrum/jce/crypto/cli/CLI2.java
+++ b/src/java/org/apache/fulcrum/jce/crypto/cli/CLI2.java
@@ -27,6 +27,7 @@
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.Arrays;
+import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -35,331 +36,336 @@
import org.apache.fulcrum.jce.crypto.HexConverter;
import org.apache.fulcrum.jce.crypto.StreamUtil;
import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8;
+import org.apache.fulcrum.jce.crypto.extended.CryptoStreamFactoryJ8Template;
import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8.TYPES;
import org.apache.fulcrum.jce.crypto.extended.CryptoUtilJ8;
/**
+ * <b>Manifest main class</b>.
+ *
* Command line tool for encrypting/decrypting a file or string
*
- * file [enc|dec] passwd [file]*
- * string [enc|dec] passwd plaintext
+ * file [enc|dec] passwd [file]* string [enc|dec] passwd plaintext
*
* Example :
*
- * <pre>java -classpath target/classes org.apache.fulcrum.jce.crypto.cli.CLI2 string enc changeit mysecretgeheim</pre>
+ * <pre>
+ * java -classpath target/classes org.apache.fulcrum.jce.crypto.cli.CLI2 string enc changeit mysecretgeheim
+ * </pre>
+ *
+ * <pre>
+ * java -jar target/fulcrum-yaafi-crypto-1.0.8.jar string enc changeit mysecretgeheim
+ * </pre>
+ *
* ...
*
- * <pre>java -cp target/classes org.apache.fulcrum.jce.crypto.cli.Main string dec changeit J8_AES256 </pre>
+ * <pre>
+ * java java -jar target/fulcrum-yaafi-crypto-1.0.8.jar string dec changeit anothersecret
+ * </pre>
+ *
+ * @author gk@apache.org
*
- * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
*/
+public class CLI2 {
+
+
+ static boolean debug = false;
+ /**
+ * Allows usage on the command line.
+ *
+ * @param args the command line parameters
+ */
+ public static void main(String[] args) {
+ try {
+ if (args.length == 0) {
+ printHelp();
+ return;
+ }
+ String operationMode = args[0];
-public class CLI2
-{
- /**
- * Allows usage on the command line.
- *
- * @param args the command line parameters
- */
- public static void main( String[] args )
- {
- try
- {
- if (args.length ==0 ){
- printHelp();
- return;
- }
- String operationMode = args[0];
-
- String msg = "No operationMode" ;
- if (operationMode == null || operationMode.equals(""))
- {
- throw new IllegalArgumentException(msg);
- }
-
- if( operationMode.equals("info") )
- {
- printInfo();
- return;
- }
- else if (operationMode.equals("help") )
- {
- printHelp();
- return;
- }
-
- if( args.length < 3 )
- {
- printHelp();
- throw new IllegalArgumentException("Invalid command line");
- }
+ String msg = "No operationMode";
+ if (operationMode == null || operationMode.equals("")) {
+ throw new IllegalArgumentException(msg);
+ }
+ if (operationMode.equals("info")) {
+ printInfo();
+ return;
+ } else if (operationMode.equals("help")) {
+ printHelp();
+ return;
+ }
- if( operationMode.equals("file") )
- {
- processFiles(args);
- }
- else if( operationMode.equals("string") )
- {
- processString(args);
- }
- }
- catch (Exception e)
- {
- System.out.println("Error : " + e.getMessage());
- e.printStackTrace();
- }
- }
+ if (args.length < 3) {
+ printHelp();
+ throw new IllegalArgumentException("Invalid command line");
+ }
- private static void printInfo()
- {
- CryptoUtilJ8 cryptoUtilJ8 = CryptoUtilJ8.getInstance();
- System.out.println("\tCrypto factory class: " + cryptoUtilJ8.getCryptoStreamFactory().getClass());
- System.out.println("\tDefault Algorithm used: " + cryptoUtilJ8.getCryptoStreamFactory().getAlgorithm());
- String algoShortList= Arrays.stream(CryptoParametersJ8.TYPES.values()).map(t-> t.toString()).collect(Collectors.joining(","));
- System.out.println("\tAlgorithms (shortcut) available: " + algoShortList);
- String algoList= Arrays.stream(CryptoParametersJ8.TYPES_IMPL.values()).map(t-> t.toString()).collect(Collectors.joining(", "));
- System.out.println("\tAlgorithms available: " + algoList);
- System.out.println("\tMore Info: https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html");
- }
+ if (operationMode.equals("file")) {
+ processFiles(args);
+ } else if (operationMode.equals("string")) {
+ processString(args);
+ }
+ } catch (Exception e) {
+ System.out.println("Error : " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
- /**
- * Prints usage information.
- */
- public static void printHelp()
- {
- System.out.println("\r\n\t*** Command line tool for encrypting/decrypting strings/files ***\r\n\t*** algorithm based on "+ CryptoParametersJ8.TYPES_IMPL.ALGORITHM_J8_PBE+ "***\r\n");
- System.out.println("\tjava -cp target\\classes; "+ CLI2.class.getName()+ " <operation mode> <coding mode> <password> <path|string> [target]\r\n");
- System.out.println("\t\toperation mode: file|string|info");
- System.out.println("\t\tcoding mode: enc|dec|enc:GCM. Default algorithm is " + TYPES.PBE);
- System.out.println("\t\t<password: string or empty:''");
- System.out.println("\t\tcode|coderef: path|string");
- System.out.println("\t\ttarget: optional\r\n");
- System.out.println( "\t*** Usage: ***\r\n");
- System.out.println("\t\t"+ CLI2.class.getSimpleName()+ " file [enc|dec] passwd source [target]");
- System.out.println("\t\t"+ CLI2.class.getSimpleName() + " string [enc|dec] passwd source");
- System.out.println("\t\t"+ CLI2.class.getSimpleName() + " info");
- }
+ private static void printInfo() {
+ CryptoUtilJ8 cryptoUtilJ8 = CryptoUtilJ8.getInstance();
+ System.out.println("");
+ System.out.println("\t|Crypto factory class: \t" + cryptoUtilJ8.getCryptoStreamFactory().getClass());
+ System.out.println("\t|_Default Algorithm used: \t" + cryptoUtilJ8.getCryptoStreamFactory().getAlgorithm());
+ List<String> algoShortList = Arrays.stream(CryptoParametersJ8.TYPES.values()).map(t -> t.toString())
+ .collect(Collectors.toList());
+ System.out.println("\t|Algorithms (shortcut) available: \t" + algoShortList);
+ String type = "AlgorithmParameters";
+ List result = CryptoParametersJ8.getSupportedAlgos(algoShortList, type, true);
+ System.out.println(
+ String.format("\t|_Matched supported %2$s:\t%1$s",
+ ((result.size() > 0) ?
+ result:
+ CryptoParametersJ8.getSupportedAlgos(algoShortList, type, false)), type));
+
+ List<String> algoList = Arrays.stream(CryptoParametersJ8.TYPES_IMPL.values()).map(t -> t.toString())
+ .collect(Collectors.toList());
+ System.out.println("\t|Algorithms available: \t" + algoList);
+ type = "Cipher";
+ result = CryptoParametersJ8.getSupportedAlgos(algoList, type, true);
+ System.out.println(
+ String.format("\t|_Matched Supported %2$ss:\t%1$s",
+ ((result.size() > 0) ?
+ result:
+ CryptoParametersJ8.getSupportedAlgos(algoList, type, false)), type));
+ System.out.println("");
+ System.out.println(
+ "\t|_ More Info: https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html\r\n");
+ }
+
- /**
- * Decrypt/encrypt a list of files
- * @param args the command line
- * @throws Exception the operation failed
- */
- public static void processFiles(String[] args)
- throws Exception
- {
- String cipherMode = args[1];
- char[] password = args[2].toCharArray();
- File sourceFile = new File(args[3]);
- File targetFile = null;
+ /**
+ * Prints usage information.
+ */
+ public static void printHelp() {
+ System.out.println(
+ "\r\n\t*** Command line tool for encrypting/decrypting strings/files ***\r\n\t*** algorithm based on "
+ + CryptoParametersJ8.TYPES_IMPL.ALGORITHM_J8_PBE + "***\r\n");
+ System.out.println("\tjava -cp target\\classes; " + CLI2.class.getName()
+ + " <operation mode> <coding mode> <password> <path|string> [target]\r\n");
+ System.out.println(
+ "\tjava -jar target/fulcrum-yaafi-crypto-1.0.8-SNAPSHOT.jar <operation mode> <coding mode> <password> <path|string> [target]\r\n");
+ System.out.println("\t\t-------------------");
+ System.out.println("\t\toperation mode: file|string|info");
+ System.out.println("\t\tcoding mode: enc|dec|enc:GCM. Default algorithm is " + TYPES.PBE);
+ System.out.println("\t\t<password: string or empty:''");
+ System.out.println("\t\tcode|coderef: path|string");
+ System.out.println("\t\ttarget: optional\r\n");
+ System.out.println("\t\t-------------------");
+ System.out.println("\t*** Usage: ***\r\n");
+ System.out.println("\t\t" + CLI2.class.getSimpleName() + " file [enc|dec] passwd source [target]");
+ System.out.println("\t\t" + CLI2.class.getSimpleName() + " string [enc|dec] passwd source");
+ System.out.println("\t\t" + CLI2.class.getSimpleName() + " info");
+ }
- if (args.length == 4)
- {
- targetFile = sourceFile;
- }
- else
- {
- targetFile = new File(args[4]);
- File parentFile = targetFile.getParentFile();
+ /**
+ * Decrypt/encrypt a list of files
+ *
+ * @param args the command line
+ * @throws Exception the operation failed
+ */
+ public static void processFiles(String[] args) throws Exception {
+ String cipherMode = args[1];
+ char[] password = args[2].toCharArray();
+ File sourceFile = new File(args[3]);
+ File targetFile = null;
- if (parentFile != null && (!parentFile.exists() || !parentFile.isDirectory()))
- {
- boolean success = parentFile.mkdirs();
- if ( !success )
- {
- System.err.println("Error, could not create directory to write parent file");
- }
- }
- }
+ if (args.length == 4) {
+ targetFile = sourceFile;
+ } else {
+ targetFile = new File(args[4]);
+ File parentFile = targetFile.getParentFile();
- processFile(cipherMode,password,sourceFile,targetFile);
- }
+ if (parentFile != null && (!parentFile.exists() || !parentFile.isDirectory())) {
+ boolean success = parentFile.mkdirs();
+ if (!success) {
+ System.err.println("Error, could not create directory to write parent file");
+ }
+ }
+ }
- /**
- * Decrypt/encrypt a single file
- * @param cipherMode the mode
- * @param password the password
- * @param sourceFile the file to process
- * @param targetFile the target file
- * @throws Exception the operation failed
- */
- public static void processFile(String cipherMode, char[] password, File sourceFile, File targetFile)
- throws Exception
- {
-
- try (FileInputStream fis = new FileInputStream(sourceFile))
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- CryptoUtilJ8 cryptoUtilJ8 = createCryptoUtil(cipherMode);
-
- if( cipherMode.startsWith("dec") )
- {
- System.out.println("Decrypting " + sourceFile.getAbsolutePath() );
-
- //String value = new String(Files.readAllBytes(Paths.get(sourceFile.toURI())));
- StringBuffer stringBuffer = new StringBuffer();
- int i;
- while ((i=fis.read()) != -1)
- {
- stringBuffer.append((char) i);
- }
-
- String value = stringBuffer.toString();
- if (isHexadecimal(value))
- {
- byte[] buffer = HexConverter.toBytes(value);
- cryptoUtilJ8.decrypt( buffer, baos, password );
- }
- else
- {
- try ( FileInputStream fis2 = new FileInputStream(sourceFile) )
- {
- cryptoUtilJ8.decrypt( fis2, baos, password );
- }
- }
-
- ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
- FileOutputStream fos = new FileOutputStream(targetFile);
- StreamUtil.copy(bais,fos);
- bais.close();
- fos.close();
- }
- else if( cipherMode.startsWith("enc") )
- {
- System.out.println("Encrypting " + sourceFile.getAbsolutePath() );
- cryptoUtilJ8.encrypt( fis, baos, password );
- fis.close();
-
- ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
- FileOutputStream fos = new FileOutputStream(targetFile);
- StreamUtil.copy(bais,fos);
- bais.close();
- fos.close();
- }
- else
- {
- String msg = "Don't know what to do with : " + cipherMode;
- throw new IllegalArgumentException(msg);
- }
- }
- }
+ processFile(cipherMode, password, sourceFile, targetFile);
+ }
- private static CryptoUtilJ8 createCryptoUtil(String cipherMode) throws Exception
- {
- CryptoUtilJ8 cryptoUtilJ8 = null;
- if (cipherMode.endsWith(TYPES.PBE.toString()) || cipherMode.substring("enc".length()).equals("") )
- {
- cryptoUtilJ8 = CryptoUtilJ8.getInstance();
- }
- else
- {
- Optional<TYPES> algoShortcut = Arrays.stream(CryptoParametersJ8.TYPES.values()).filter(a-> cipherMode.endsWith(a.toString())).findFirst(); //.collect(Collectors.toList());
- if (algoShortcut.isPresent())
- {
- cryptoUtilJ8 = CryptoUtilJ8.getInstance(algoShortcut.get());
- }
- }
-
- if (cryptoUtilJ8 == null)
- {
- throw new Exception("Could not find any algorithms. check provided alog shortcuts with CLI2 info!");
- }
-
- return cryptoUtilJ8;
- }
+ /**
+ * Decrypt/encrypt a single file
+ *
+ * @param cipherMode the mode
+ * @param password the password
+ * @param sourceFile the file to process
+ * @param targetFile the target file
+ * @throws Exception the operation failed
+ */
+ public static void processFile(String cipherMode, char[] password, File sourceFile, File targetFile)
+ throws Exception {
- /**
- * Decrypt and encrypt a string.
- *
- * @param args the command line
- * @throws Exception the operation failed
- */
- public static void processString(String[] args)
- throws Exception
- {
- final String cipherMode;
- final char[] password;
- final String value;
- File targetFile = null;
- if (args.length > 3) {
- cipherMode = args[1];
- password = args[2].toCharArray();
- value = args[3];
- } else {
- value = null;
- cipherMode = null;
- password = null;
- }
- if (args.length == 5)
- {
- targetFile = new File(args[4]);
- File parentFile = targetFile.getParentFile();
+ try (FileInputStream fis = new FileInputStream(sourceFile)) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ CryptoUtilJ8 cryptoUtilJ8 = createCryptoUtil(cipherMode);
- if (parentFile != null && (!parentFile.exists() || !parentFile.isDirectory()))
- {
- boolean success = parentFile.mkdirs();
- if ( !success )
- {
- System.err.println("Error, could not create directory to write parent file");
- }
-
- }
- }
-
- if (value != null && !value.equals(""))
- {
+ if (cipherMode.startsWith("dec")) {
+ System.out.println("Decrypting " + sourceFile.getAbsolutePath());
- String result = processString(cipherMode, password, value);
-
- if (targetFile != null) {
-
- try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(targetFile), Charset.forName("UTF-8").newEncoder() ) )
- {
- osw.write(result);
- }
- } else {
- System.out.println( result );
- }
- }
- }
-
- /**
- * Decrypt and encrypt a string.
- *
- * @param cipherMode \"dec|enc\" + @link{TYPES}
- * @param password as char array
- * @param value String to be en/decrypted
- * @throws Exception the operation failed
- *
- * @return the result - either the encrypted or decrypted string depending on cipherMode
- */
- public static String processString(String cipherMode, char[] password, String value)
- throws Exception
- {
- if (value != null && !value.equals(""))
- {
- CryptoUtilJ8 cryptoUtilJ8 = createCryptoUtil(cipherMode);
-
- String result = null;
- if ( cipherMode.startsWith("dec") )
- {
- result = cryptoUtilJ8.decryptString(value,password);
- }
- else if ( cipherMode.startsWith("enc"))
- {
- result = cryptoUtilJ8.encryptString(value,password);
- }
- return result;
- } else {
- return null;
- }
- }
-
- private static final Pattern HEXADECIMAL_PATTERN = Pattern.compile("\\p{XDigit}+");
+ // String value = new String(Files.readAllBytes(Paths.get(sourceFile.toURI())));
+ StringBuffer stringBuffer = new StringBuffer();
+ int i;
+ while ((i = fis.read()) != -1) {
+ stringBuffer.append((char) i);
+ }
- public static boolean isHexadecimal(String input) {
- final Matcher matcher = HEXADECIMAL_PATTERN.matcher(input);
- return matcher.matches();
- }
+ String value = stringBuffer.toString();
+ if (isHexadecimal(value)) {
+ byte[] buffer = HexConverter.toBytes(value);
+ cryptoUtilJ8.decrypt(buffer, baos, password);
+ } else {
+ try (FileInputStream fis2 = new FileInputStream(sourceFile)) {
+ cryptoUtilJ8.decrypt(fis2, baos, password);
+ }
+ }
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ FileOutputStream fos = new FileOutputStream(targetFile);
+ StreamUtil.copy(bais, fos);
+ bais.close();
+ fos.close();
+ } else if (cipherMode.startsWith("enc")) {
+ System.out.println("Encrypting " + sourceFile.getAbsolutePath());
+ cryptoUtilJ8.encrypt(fis, baos, password);
+ fis.close();
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ FileOutputStream fos = new FileOutputStream(targetFile);
+ StreamUtil.copy(bais, fos);
+ bais.close();
+ fos.close();
+ } else {
+ String msg = "Don't know what to do with : " + cipherMode;
+ throw new IllegalArgumentException(msg);
+ }
+ }
+ }
+
+ private static CryptoUtilJ8 createCryptoUtil(String cipherMode) throws Exception {
+ CryptoUtilJ8 cryptoUtilJ8 = null;
+ // now extension like enc:GCM
+ if (cipherMode.endsWith(TYPES.PBE.toString()) || cipherMode.substring("enc".length()).equals("")) {
+ cryptoUtilJ8 = CryptoUtilJ8.getInstance();
+ } else {
+ List<String> supportedTypes = CryptoParametersJ8.init();
+ System.err.println("checking supported types:"+ supportedTypes);
+ List<String> matchedType = supportedTypes.stream().filter(x-> cipherMode.endsWith(x) ).collect(Collectors.toList());
+ System.err.println("matched type:"+ matchedType);
+ Optional<TYPES> algoShortcut = Arrays.stream(CryptoParametersJ8.TYPES.values())
+ .filter(a -> matchedType.get(0).equals(a.toString())).findFirst();
+ if (algoShortcut.isPresent()) {
+ System.err.println("initializing type:"+ algoShortcut);
+ cryptoUtilJ8 = CryptoUtilJ8.getInstance(algoShortcut.get());
+ }
+ }
+
+ if (cryptoUtilJ8 == null) {
+ throw new Exception("Could not find any algorithms. check provided algo shortcuts with CLI2 info!");
+ }
+
+ if (debug) {
+ CryptoStreamFactoryJ8Template crt = ((CryptoStreamFactoryJ8Template)cryptoUtilJ8.getCryptoStreamFactory());
+ System.err.println(String.format("using crypto factory instance %s for algo %s and type %s with salt length: %s and count %s",
+ crt.getClass().getSimpleName(), crt.getType(),
+ crt.getAlgorithm(), crt.getSalt().length, crt.getCount()));
+ }
+ return cryptoUtilJ8;
+ }
+
+ /**
+ * Decrypt and encrypt a string.
+ *
+ * @param args the command line
+ * @throws Exception the operation failed
+ */
+ public static void processString(String[] args) throws Exception {
+ final String cipherMode;
+ final char[] password;
+ final String value;
+ File targetFile = null;
+ if (args.length > 3) {
+ cipherMode = args[1];
+ password = args[2].toCharArray();
+ value = args[3];
+ } else {
+ value = null;
+ cipherMode = null;
+ password = null;
+ }
+ if (args.length == 5) {
+ targetFile = new File(args[4]);
+ File parentFile = targetFile.getParentFile();
+
+ if (parentFile != null && (!parentFile.exists() || !parentFile.isDirectory())) {
+ boolean success = parentFile.mkdirs();
+ if (!success) {
+ System.err.println("Error, could not create directory to write parent file");
+ }
+
+ }
+ }
+
+ if (value != null && !value.equals("")) {
+
+ String result = processString(cipherMode, password, value);
+
+ if (targetFile != null) {
+
+ try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(targetFile),
+ Charset.forName("UTF-8").newEncoder())) {
+ osw.write(result);
+ }
+ } else {
+ System.out.println(result);
+ }
+ }
+ }
+
+ /**
+ * Decrypt and encrypt a string.
+ *
+ * @param cipherMode \"dec|enc\" + @link{TYPES}
+ * @param password as char array
+ * @param value String to be en/decrypted
+ * @throws Exception the operation failed
+ *
+ * @return the result - either the encrypted or decrypted string depending on
+ * cipherMode
+ */
+ public static String processString(String cipherMode, char[] password, String value) throws Exception {
+ if (value != null && !value.equals("")) {
+ CryptoUtilJ8 cryptoUtilJ8 = createCryptoUtil(cipherMode);
+
+ String result = null;
+ if (cipherMode.startsWith("dec")) {
+ result = cryptoUtilJ8.decryptString(value, password);
+ } else if (cipherMode.startsWith("enc")) {
+ result = cryptoUtilJ8.encryptString(value, password);
+ }
+ return result;
+ } else {
+ return null;
+ }
+ }
+
+ private static final Pattern HEXADECIMAL_PATTERN = Pattern.compile("\\p{XDigit}+");
+
+ public static boolean isHexadecimal(String input) {
+ final Matcher matcher = HEXADECIMAL_PATTERN.matcher(input);
+ return matcher.matches();
+ }
}
\ No newline at end of file
diff --git a/src/java/org/apache/fulcrum/jce/crypto/extended/CryptoParametersJ8.java b/src/java/org/apache/fulcrum/jce/crypto/extended/CryptoParametersJ8.java
index a02eb6a..152219a 100644
--- a/src/java/org/apache/fulcrum/jce/crypto/extended/CryptoParametersJ8.java
+++ b/src/java/org/apache/fulcrum/jce/crypto/extended/CryptoParametersJ8.java
@@ -1,5 +1,13 @@
package org.apache.fulcrum.jce.crypto.extended;
+import java.security.Provider;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -26,7 +34,7 @@
*/
public interface CryptoParametersJ8 {
-
+
/**
*
* Implementing classes are either using
@@ -42,14 +50,13 @@
* </ul>
*
*
- * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html#SunJCEProvider">The Oracle Security SunJCE Provider</a>
+ * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html#SunJCEProvider">The Oracle Security SunJCE Provider</a>
*
* Algo/mode/padding for cipher transformation:
*
- * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher">Java 8: The Oracle Security Standard Names Cipher Algorithms</a>
+ * Java 8: <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher">The Oracle Security Standard Names Cipher Algorithms</a>
*
- * @see <a href="https://docs.oracle.com/en/java/javase/14/docs/specs/security/standard-names.html#security-algorithm-implementation-requirements">Java 14: Security Algorithm Implementation Requirements</a>
- *
+ * Java 14: <a href="https://docs.oracle.com/en/java/javase/14/docs/specs/security/standard-names.html#security-algorithm-implementation-requirements">Security Algorithm Implementation Requirements</a>
*
*/
public enum TYPES_IMPL {
@@ -57,7 +64,7 @@
// key size 256
ALGORITHM_J8_PBE("PBEWithHmacSHA256AndAES_256"),
// key size 128
- ALGORITHM_J8_GCM("AES/GCM/NoPadding");
+ ALGORITHM_J8_GCM("AES_128/GCM/NoPadding");
private final String algorithm;
@@ -73,16 +80,113 @@
public String getAlgorithm() {
return algorithm;
}
- }
-
- public enum TYPES {
- PBE, GCM
+
+ /**
+ * clear code depending on algorithm AES size return <pre>J8AESAES_<size>;</pre>.
+ * {@link CryptoParametersJ8#CLEAR_CODE_DEFAULT}
+ *
+ * @return clear code J8AES_<size>; with three digit size.
+ */
+ public String getClearCode() {
+
+ return String.format("J8%1$s;",
+ algorithm.subSequence(algorithm.indexOf("AES_"),algorithm.indexOf("AES_")+7));
+ }
}
/**
- * Prefix to decrypted hex hash to get a clue, what to use and what it is.
*
- * This should be always 10 bytes
+ * short names, exact names @see {@link TYPES_IMPL}.
+ *
*/
- String CLEAR_CODE_J8 = "J8_AES256;";
+ public enum TYPES {
+
+ /**
+ * PBE algorithm is kind of meta algorithm, uses AES, see above.
+ */
+ PBE,
+ /**
+ * AES algorithm, but GCM is is actually the algorithm mode, but nevertheless used as a short name.
+ */
+ GCM;
+
+ /**
+ * Clear code should be always 10 bytes.
+ *
+ * {@link CryptoParametersJ8#CLEAR_CODE_DEFAULT}
+ *
+ * @return clear code
+ *
+ */
+ public String getClearCode() {
+ return this.equals(TYPES.PBE)?
+ TYPES_IMPL.ALGORITHM_J8_PBE.getClearCode():
+ TYPES_IMPL.ALGORITHM_J8_GCM.getClearCode();
+ }
+ }
+
+ /**
+ * Prefix to decrypted hex hash to get a clue, what to use and what it is; should be always 10 bytes.
+ */
+ public String CLEAR_CODE_DEFAULT = "J8_AES064;";
+
+ public TYPES DEFAULT_TYPE = TYPES.PBE;
+
+
+ /**
+ * Checks Java provider with <b>type</b> has exact type or contains any of the strings in algoList.
+ * <pre>Types</pre> may be Cipher, AlgorithmParameters, KeyGenerator, Alg, Mac, SecretKeyFactory.
+ *
+ * @param algoList the types to be checked
+ * @param type the type is ignored if not exact, instead uses the two types: "AlgorithmParameters", "Cipher".
+ * @param exact if exact does a exact match
+ * @return the matched results as a list
+ */
+ public static List<String> getSupportedAlgos(List<String> algoList, String type, boolean exact) {
+ List<String> result = new ArrayList<String>();
+ Provider p[] = Security.getProviders();
+ List<Provider> providerList = Arrays.asList(p);
+
+ String[] PROVIDER_TYPES = { "AlgorithmParameters", "Cipher" };
+ for (Provider provider : providerList) {
+ // System.out.println(provider);
+ result.addAll(Collections.list(provider.keys()).stream().map(t -> t.toString())
+ .filter(x->
+ (exact)?
+ (x.startsWith(type) && algoList.contains(x.replaceAll(type + ".", ""))):
+ (x.matches("(" +String.join("|", PROVIDER_TYPES) + ").*$") &&
+ algoList.stream().anyMatch(y -> y.contains(x.replaceAll(type + ".", "")))
+ )
+ )
+ .map( x ->
+ (exact)?
+ x.replaceAll(type + ".", ""):
+ x.replaceAll("(" +String.join("|", PROVIDER_TYPES) + ")" + ".", "")
+ )
+ .collect(Collectors.toList()));
+ }
+ return result;
+ }
+
+ /**
+ * initializes supported parameters by filtering {@link TYPES} against <i>AlgorithmParameters</i> in system supported cipher suites:
+ * first by an exact match with type <i>AlgorithmParameters</i>, then by inexact matching.
+ *
+ * {@link #getSupportedAlgos(List, String, boolean)}
+ * @return list of supported algo short codes, if nothing is found the {@link #DEFAULT_TYPE} is set.
+ */
+ static List<String> init() {
+ List<String> result = new ArrayList<String>();
+ List<String> defaultSupportedTypes = Arrays.asList( TYPES.values() ).stream().map(x-> x.toString()).collect(Collectors.toList());
+ String providerType = "AlgorithmParameters";
+ result = getSupportedAlgos(defaultSupportedTypes, providerType, true);
+ if (result.isEmpty()) {
+ // minimal default, try it
+ result = getSupportedAlgos(defaultSupportedTypes, providerType, false);
+ result = !result.isEmpty()?
+ result: Arrays.asList( DEFAULT_TYPE).stream().map(x-> x.toString()).collect(Collectors.toList());
+ }
+ return result;
+ }
+
}
diff --git a/src/java/org/apache/fulcrum/jce/crypto/extended/CryptoStreamFactoryJ8Template.java b/src/java/org/apache/fulcrum/jce/crypto/extended/CryptoStreamFactoryJ8Template.java
index dbd5fb3..7de7f52 100644
--- a/src/java/org/apache/fulcrum/jce/crypto/extended/CryptoStreamFactoryJ8Template.java
+++ b/src/java/org/apache/fulcrum/jce/crypto/extended/CryptoStreamFactoryJ8Template.java
@@ -23,7 +23,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
@@ -50,7 +49,7 @@
/** the salt for the algorithm */
protected byte[] salt;
- /** the count paramter for the algorithm */
+ /** the count parameter for the algorithm, not used for GCM */
protected int count;
/** the name of the JCE provider */
@@ -59,6 +58,16 @@
/** the algorithm to use */
protected String algorithm;
+ private TYPES type;
+
+ public TYPES getType() {
+ return type;
+ }
+
+ public void setType(TYPES type) {
+ this.type = type;
+ }
+
/**
* The JCE provider name known to work. If the value
* is set to null an appropriate provider will be
@@ -67,16 +76,42 @@
protected static final String PROVIDERNAME = null;
protected static final int SALT_SIZE = 16; //might increase cipher length
- protected static final int KEY_SIZE = 256;
/** the default instances */
- protected static Map<TYPES,CryptoStreamFactoryJ8Template> instances = new ConcurrentHashMap<>();
+ protected static final Map<TYPES,CryptoStreamFactoryJ8Template> instances = new ConcurrentHashMap<>();
//protected AlgorithmParameters algorithmParameters;// used only for debugging
public CryptoStreamFactoryJ8Template() {
}
+
+ /**
+ * Factory method to get a default instance
+ *
+ * creating instance of type {@link CryptoParametersJ8#DEFAULT_TYPE}.
+ *
+ * @return an instance of the CryptoStreamFactory
+ */
+ public static CryptoStreamFactoryJ8 getInstance()
+ {
+ synchronized (CryptoStreamFactoryJ8Template.class) {
+ if( !instances.containsKey(CryptoParametersJ8.DEFAULT_TYPE) )
+ {
+ try {
+ instances.put(CryptoParametersJ8.DEFAULT_TYPE,
+ (CryptoParametersJ8.DEFAULT_TYPE.equals(TYPES.PBE))? new CryptoStreamPBEImpl():
+ new CryptoStreamGCMImpl()
+ );
+ } catch (GeneralSecurityException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
+ return instances.get(CryptoParametersJ8.DEFAULT_TYPE);
+ }
+ }
/**
* Factory method to get a default instance
@@ -103,22 +138,33 @@
return instances.get(type);
}
}
-
-
+
/**
- * Constructor
- *
- * @param salt the salt for the PBE algorithm
- * @param count the iteration for PBEParameterSpec
- * @param type {@link TYPES} what type the algorithm will be
+ * Factory method to get a default instance
+ *
+ * @param type the @see {@link TYPES} of the instance.
+ * @param salt provided salt
+ * @param count provided count, used only for {@link TYPES#PBE}.
+ * @return an instance of the CryptoStreamFactory
*/
- public CryptoStreamFactoryJ8Template( byte[] salt, int count, TYPES type)
+ public static CryptoStreamFactoryJ8 getInstance(TYPES type, byte[] salt, int count)
{
- this.salt = salt.clone();
- this.count = count;
- this.providerName = PROVIDERNAME;
- this.algorithm = type.equals(TYPES.PBE)? CryptoParametersJ8.TYPES_IMPL.ALGORITHM_J8_PBE.getAlgorithm():
- CryptoParametersJ8.TYPES_IMPL.ALGORITHM_J8_GCM.getAlgorithm();;
+ synchronized (CryptoStreamFactoryJ8Template.class) {
+ if( !instances.containsKey(type) )
+ {
+ try {
+ instances.put(type,
+ (type.equals(TYPES.PBE))? new CryptoStreamPBEImpl(salt, count):
+ new CryptoStreamGCMImpl(salt)
+ );
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
+ return instances.get(type);
+ }
}
@@ -146,6 +192,9 @@
return eis;
}
+ /**
+ * @see org.apache.fulcrum.jce.crypto.extended.CryptoStreamFactoryJ8#getOutputStream(InputStream, OutputStream, char[])
+ */
public OutputStream getOutputStream(InputStream is, OutputStream os, char[] password)
throws GeneralSecurityException, IOException {
byte[] encrypted = this.createCipher( is, Cipher.ENCRYPT_MODE, password.clone() );
@@ -162,16 +211,16 @@
CryptoStreamFactoryJ8Template.instances.clear();
}
- /**
- * Set the default instances from an external application.
- * @param instances the new default instances map
- * @throws Exception if instances are null
- */
- public static void setInstances(Map<TYPES,CryptoStreamFactoryJ8Template> instances ) throws Exception
- {
- if (instances == null) throw new Exception("setting instances to null not allowed!");
- CryptoStreamFactoryJ8Template.instances = instances;
- }
+// /**
+// * Set the default instances from an external application.
+// * @param instances the new default instances map
+// * @throws Exception if instances are null
+// */
+// public static void setInstances(Map<TYPES,CryptoStreamFactoryJ8Template> instances ) throws Exception
+// {
+// if (instances == null) throw new Exception("setting instances to null not allowed!");
+// CryptoStreamFactoryJ8Template.instances = instances;
+// }
/** not used / implemented methods **/
@@ -239,12 +288,12 @@
*
* changed to {@link SecureRandom#getInstanceStrong()} and let the system decide, what PRNG to use for salt random.
*
- * salt size by default @link {@value #SALT_SIZE}.
+ * salt size is by default @link {@value #SALT_SIZE}.
*
* @return the generated salt as byte array
* @throws GeneralSecurityException if no algo could be found.
*/
- protected byte[] generateSalt() throws GeneralSecurityException {
+ protected static byte[] generateSalt() throws GeneralSecurityException {
SecureRandom random;
try {
random = SecureRandom.getInstanceStrong();
@@ -260,7 +309,7 @@
return salt.clone();
}
- public void setSalt(byte[] salt) {
+ protected void setSalt(byte[] salt) {
this.salt = salt.clone();
}
diff --git a/src/java/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8.java b/src/java/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8.java
index a4bbc2e..51d1805 100644
--- a/src/java/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8.java
+++ b/src/java/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8.java
@@ -32,42 +32,19 @@
import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8.TYPES;
/**
- * Helper class to provide generic functions to work with CryptoStreams.
- *
- * The code uses parts from Markus Hahn's Blowfish library found at
- * http://blowfishj.sourceforge.net/
+ * Helper class to provide typed functions to work with CryptoStreams.
*
* @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl </a>
- * @author <a href="mailto:maakus@earthlink.net">Markus Hahn</a>
* @author <a href="mailto:gk@apache.org">Georg Kallidis</a>
*/
public final class CryptoUtilJ8 extends CryptoUtil {
- /** the typed default instances */
- private static Map<TYPES, CryptoUtilJ8> cryptoUtilJ8s = new ConcurrentHashMap<>();
-
- // default see instance
- public TYPES type;
-
- public TYPES getType() {
- return type;
- }
-
- /**
- * Factory method to get a default instance
- *
- * @param type one of the enum {@link TYPES}.
- * @return an instance of the CryptoStreamFactory
- */
- public static CryptoUtilJ8 getInstance(TYPES type) {
- synchronized (CryptoUtilJ8.class) {
- if (!cryptoUtilJ8s.containsKey(type)) {
- cryptoUtilJ8s.put(type, new CryptoUtilJ8(type));
- }
- return cryptoUtilJ8s.get(type);
- }
- }
-
+ /** the typed default instances */
+ private static final Map<TYPES, CryptoUtilJ8> instances = new ConcurrentHashMap<>();
+
+ /** the default instances with custom settings **/
+ private static final Map<TYPES, CryptoUtilJ8> instancesWithExplicitParams = new ConcurrentHashMap<>();
+
/**
* Factory method to get a default instance
*
@@ -77,26 +54,69 @@
*/
public static CryptoUtilJ8 getInstance() {
synchronized (CryptoUtilJ8.class) {
- TYPES defaultType = TYPES.PBE;
- if (cryptoUtilJ8s.isEmpty() && !cryptoUtilJ8s.containsKey(defaultType)) {
- cryptoUtilJ8s.put(defaultType, new CryptoUtilJ8(defaultType));
+ TYPES defaultType = CryptoParametersJ8.DEFAULT_TYPE;
+ if (instances.isEmpty() && !instances.containsKey(defaultType)) {
+ instances.put(defaultType, new CryptoUtilJ8());
}
- return cryptoUtilJ8s.get(defaultType);
+ return instances.get(defaultType);
}
}
-
- private CryptoUtilJ8(TYPES type) {
- super();
- this.type = type;
+
+ /**
+ * Factory method to get a default instance
+ *
+ * @param type one of the enum {@link TYPES}.
+ * @return an instance of the CryptoStreamFactory
+ */
+ public static CryptoUtilJ8 getInstance(TYPES type) {
+ synchronized (CryptoUtilJ8.class) {
+ if (!instances.containsKey(type)) {
+ instances.put(type, new CryptoUtilJ8(type));
+ }
+ return instances.get(type);
+ }
}
-
+
+ /**
+ * Factory method to get a default instance
+ *
+ * @param type one of the enum {@link TYPES}.
+ * @param salt the salt
+ * @param count the iteration count
+ * @return an instance of the CryptoStreamFactory
+ */
+ public static CryptoUtilJ8 getInstance(TYPES type, byte[] salt, int count) {
+ synchronized (CryptoUtilJ8.class) {
+ if (!instancesWithExplicitParams.containsKey(type)) {
+ instancesWithExplicitParams.put(type, new CryptoUtilJ8(type, salt, count));
+ }
+ return instancesWithExplicitParams.get(type);
+ }
+ }
+
private CryptoUtilJ8() {
- super();
+ cryptoStreamFactory = CryptoStreamFactoryJ8Template.getInstance();
}
+
+ private CryptoUtilJ8(TYPES type) {
+ cryptoStreamFactory = CryptoStreamFactoryJ8Template.getInstance(type);
+ }
+
+ /**
+ *
+ * @param type one of the enum {@link TYPES}.
+ * @param salt v
+ * @param count the iteration count
+ */
+ protected CryptoUtilJ8(TYPES type, byte[] salt, int count) {
+ cryptoStreamFactory = CryptoStreamFactoryJ8Template.getInstance(type, salt, count);
+ }
/**
* Copies from a source to a target object using encryption and a caller
* supplied CryptoStreamFactory.
+ *
+ * {@link CryptoStreamFactoryJ8Template#getOutputStream(InputStream, OutputStream, char[])}
*
* @param factory the factory to create the crypto streams
* @param source the source object
@@ -110,8 +130,7 @@
throws GeneralSecurityException, IOException {
InputStream is = StreamUtil.createInputStream(source);
OutputStream os = StreamUtil.createOutputStream(target);
- OutputStream eos = ((CryptoStreamFactoryJ8) factory).getOutputStream(is, os, password);
- // StreamUtil.copy( is, eos );
+ ((CryptoStreamFactoryJ8) factory).getOutputStream(is, os, password);
}
/**
@@ -134,11 +153,12 @@
StreamUtil.copy(dis, os);
}
- /**
- *
- * @return the CryptoStreamFactory to be used
- */
- public CryptoStreamFactory getCryptoStreamFactory() {
- return CryptoStreamFactoryJ8Template.getInstance(type);
+ public static Map<TYPES, CryptoUtilJ8> getInstances() {
+ return instances;
}
+
+ public static Map<TYPES, CryptoUtilJ8> getInstancesWithExplicitParams() {
+ return instancesWithExplicitParams;
+ }
+
}
diff --git a/src/test/log4j2.xml b/src/test/log4j2.xml
index 1846038..3533c0e 100644
--- a/src/test/log4j2.xml
+++ b/src/test/log4j2.xml
@@ -1,58 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
--->
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
+ license agreements. See the NOTICE file distributed with this work for additional
+ information regarding copyright ownership. The ASF licenses this file to
+ you under the Apache License, Version 2.0 (the "License"); you may not use
+ this file except in compliance with the License. You may obtain a copy of
+ the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License. -->
<Configuration status="info" verbose="false">
- <Appenders>
- <Console name="console" target="SYSTEM_OUT">
- <PatternLayout pattern="%d [%t] %-5p %c - %m%n"/>
- </Console>
- <File name="logfile" fileName="target/fulcrum-test.log">
- <PatternLayout pattern="%d [%t] %-5p %c - %m%n"/>
- </File>
- <File name="avalon" fileName="target/avalon-test.log">
- <PatternLayout pattern="%d [%t] %-5p %c - %m%n"/>
- </File>
- </Appenders>
- <Loggers>
- <Logger name="org.apache.fulcrum.jce.crypto" level="debug" additivity="false">
- <AppenderRef ref="console"/>
- <AppenderRef ref="logfile"/>
- </Logger>
- <Logger name="org.apache.fulcrum.jce" level="debug" additivity="false">
- <AppenderRef ref="console"/>
- <AppenderRef ref="logfile"/>
- </Logger>
- <Logger name="org.apache.fulcrum" level="info" additivity="false">
- <AppenderRef ref="console"/>
- <AppenderRef ref="logfile"/>
- </Logger>
- <Logger name="org.apache.fulcrum.yaafi" level="info" additivity="false">
- <AppenderRef ref="avalon"/>
- </Logger>
- <Logger name="avalon" level="warn" additivity="false">
- <AppenderRef ref="avalon"/>
- </Logger>
- <Logger name="org.apache.logging.log4j" level="warn" additivity="false">
- <AppenderRef ref="logfile"/>
- </Logger>
- <Root level="error">
- <AppenderRef ref="console"/>
- </Root>
- </Loggers>
+ <Appenders>
+ <Console name="console" target="SYSTEM_OUT">
+ <PatternLayout pattern="%d [%t] %-5p %c - %m%n" />
+ </Console>
+ <File name="logfile" fileName="target/fulcrum-test.log">
+ <PatternLayout pattern="%d [%t] %-5p %c - %m%n" />
+ </File>
+ <File name="avalon" fileName="target/avalon-test.log">
+ <PatternLayout pattern="%d [%t] %-5p %c - %m%n" />
+ </File>
+ </Appenders>
+ <Loggers>
+ <Logger name="org.apache.fulcrum.jce.crypto" level="debug"
+ additivity="false">
+ <AppenderRef ref="console" />
+ <AppenderRef ref="logfile" />
+ </Logger>
+ <Logger name="org.apache.fulcrum.jce" level="debug"
+ additivity="false">
+ <AppenderRef ref="console" />
+ <AppenderRef ref="logfile" />
+ </Logger>
+ <Logger name="org.apache.fulcrum" level="info"
+ additivity="false">
+ <AppenderRef ref="console" />
+ <AppenderRef ref="logfile" />
+ </Logger>
+ <Logger name="org.apache.fulcrum.yaafi" level="info"
+ additivity="false">
+ <AppenderRef ref="avalon" />
+ </Logger>
+ <Logger name="avalon" level="warn" additivity="false">
+ <AppenderRef ref="avalon" />
+ </Logger>
+ <Logger name="org.apache.logging.log4j" level="warn"
+ additivity="false">
+ <AppenderRef ref="logfile" />
+ </Logger>
+ <Root level="error">
+ <AppenderRef ref="console" />
+ </Root>
+ </Loggers>
</Configuration>
\ No newline at end of file
diff --git a/src/test/org/apache/fulcrum/jce/crypto/CryptoUtilExplicitParamsTest.java b/src/test/org/apache/fulcrum/jce/crypto/CryptoUtilExplicitParamsTest.java
new file mode 100644
index 0000000..12001c1
--- /dev/null
+++ b/src/test/org/apache/fulcrum/jce/crypto/CryptoUtilExplicitParamsTest.java
@@ -0,0 +1,447 @@
+package org.apache.fulcrum.jce.crypto;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Test suite for crypto functionality
+ *
+ * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
+ */
+
+public class CryptoUtilExplicitParamsTest {
+ /** the password to be used */
+ private String password;
+
+ /** the test data directory */
+ private File testDataDirectory;
+
+ /** the temp data director */
+ private File tempDataDirectory;
+
+ private static Logger log = LogManager.getLogger(CryptoUtilExplicitParamsTest.class);
+
+ private static byte[] SALT = Salt();
+
+ private static int COUNT = 25;
+
+ public static byte[] Salt()
+ {
+ SecureRandom random;
+ try {
+ random = SecureRandom.getInstanceStrong();
+ byte[] salt = new byte[ 8 ];
+ random.nextBytes(salt);
+ return salt;
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * Constructor
+ */
+ public CryptoUtilExplicitParamsTest() {
+ this.password = "mysecret";
+ this.testDataDirectory = new File("./src/test/data");
+ this.tempDataDirectory = new File("./target/temp");
+ this.tempDataDirectory.mkdirs();
+ }
+
+ /**
+ *
+ * @throws Exception Generic exception
+ */
+ @BeforeAll
+ protected static void setUp() throws Exception {
+ }
+
+ /**
+ * @return Returns the password.
+ */
+ protected char[] getPassword() {
+ return password.toCharArray();
+ }
+
+ /**
+ * @return Returns the tempDataDirectory.
+ */
+ protected File getTempDataDirectory() {
+ return tempDataDirectory;
+ }
+
+ /**
+ * @return Returns the testDataDirectory.
+ */
+ protected File getTestDataDirectory() {
+ return testDataDirectory;
+ }
+
+ /** Encrypt a text file
+ */
+ @Test
+ public void testTextEncryption() {
+ File sourceFile = new File(this.getTestDataDirectory(), "plain.txt");
+ File targetFile = new File(this.getTempDataDirectory(), "plain.enc.txt");
+ try {
+ CryptoUtil.getInstance(SALT,COUNT).encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException e) {
+ fail(e);
+ } catch (IOException e) {
+ fail(e);
+ }
+ }
+
+ /** Decrypt a text file
+ */
+ @Test
+ public void testTextDecryption() {
+ testTextEncryption();
+ File sourceFile = new File(this.getTempDataDirectory(), "plain.enc.txt");
+ File targetFile = new File(this.getTempDataDirectory(), "plain.dec.txt");
+ try {
+ CryptoUtil.getInstance(SALT,COUNT).decrypt(sourceFile, targetFile.getAbsolutePath(), this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+ }
+
+ /** Encrypt an empty text file
+ */
+ @Test
+ public void testEmptyTextEncryption() {
+ File sourceFile = new File(this.getTestDataDirectory(), "empty.txt");
+ File targetFile = new File(this.getTempDataDirectory(), "empty.enc.txt");
+ try {
+ CryptoUtil.getInstance(SALT,COUNT).encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+ }
+
+ /** Decrypt a text file
+ */
+ @Test
+ public void testEmptyTextDecryption() {
+ testEmptyTextEncryption();
+ File sourceFile = new File(this.getTempDataDirectory(), "empty.enc.txt");
+ File targetFile = new File(this.getTempDataDirectory(), "empty.dec.txt");
+ try {
+ CryptoUtil.getInstance(SALT,COUNT).decrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+ }
+
+ /** Encrypt a PDF file
+ */
+ @Test
+ public void testPdfEncryption() {
+ File sourceFile = new File(this.getTestDataDirectory(), "plain.pdf");
+ File targetFile = new File(this.getTempDataDirectory(), "plain.enc.pdf");
+ try {
+ CryptoUtil.getInstance(SALT,COUNT).encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+ }
+
+ /** Decrypt a PDF file
+ */
+ @Test
+ public void testPdfDecryption() {
+ testPdfEncryption();
+ File sourceFile = new File(this.getTempDataDirectory(), "plain.enc.pdf");
+ File targetFile = new File(this.getTempDataDirectory(), "plain.dec.pdf");
+ try {
+ CryptoUtil.getInstance(SALT,COUNT).decrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+ }
+
+ /** Encrypt a ZIP file
+ */
+ @Test
+ public void testZipEncryption() {
+ File sourceFile = new File(this.getTestDataDirectory(), "plain.zip");
+ File targetFile = new File(this.getTempDataDirectory(), "plain.enc.zip");
+ try {
+ CryptoUtil.getInstance(SALT,COUNT).encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+ }
+
+ /** Decrypt a ZIP file
+ */
+ @Test
+ public void testZipDecryption() {
+ testZipEncryption();
+ File sourceFile = new File(this.getTempDataDirectory(), "plain.enc.zip");
+ File targetFile = new File(this.getTempDataDirectory(), "plain.dec.zip");
+ try {
+ CryptoUtil.getInstance(SALT,COUNT).decrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+ }
+
+ /** Encrypt a UTF-16 XML file
+ */
+ @Test
+ public void testXmlUTF16Encryption() {
+ File sourceFile = new File(this.getTestDataDirectory(), "plain-utf16.xml");
+ File targetFile = new File(this.getTempDataDirectory(), "plain-utf16.enc.xml");
+ try {
+ CryptoUtil.getInstance(SALT,COUNT).encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+ }
+
+ /**
+ * Decrypt a UTF-16 XML file
+ */
+ @Test
+ public void testXMLUTF16Decryption() {
+ testXmlUTF16Encryption();
+ File sourceFile = new File(this.getTempDataDirectory(), "plain-utf16.enc.xml");
+ File targetFile = new File(this.getTempDataDirectory(), "plain-utf16.dec.xml");
+ try {
+ CryptoUtil.getInstance(SALT,COUNT).decrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+ }
+
+ /**
+ * Encrypt a UTF-8 XML file
+ */
+ @Test
+ public void testXmlUTF8Encryption() {
+ File sourceFile = new File(this.getTestDataDirectory(), "plain-utf8.xml");
+ File targetFile = new File(this.getTempDataDirectory(), "plain-utf8.enc.xml");
+ try {
+ CryptoUtil.getInstance(SALT,COUNT).encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+ }
+
+ /**
+ * Decrypt a UTF-8 XML file
+ */
+ @Test
+ public void testXMLUTF8Decryption() {
+ testXmlUTF8Encryption();
+ File sourceFile = new File(this.getTempDataDirectory(), "plain-utf8.enc.xml");
+ File targetFile = new File(this.getTempDataDirectory(), "plain-utf8.dec.xml");
+ try {
+ CryptoUtil.getInstance(SALT,COUNT).decrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+ }
+
+ /**
+ * Encrypt a ISO-8859-1 XML file
+ */
+ @Test
+ public void testXmlISO88591Encryption() {
+ File sourceFile = new File(this.getTestDataDirectory(), "plain-iso-8859-1.xml");
+ File targetFile = new File(this.getTempDataDirectory(), "plain-iso-8859-1.enc.xml");
+ try {
+ CryptoUtil.getInstance(SALT,COUNT).encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+ }
+
+ /**
+ * Decrypt a ISO-8859-1 XML file
+ */
+ @Test
+ public void testXmlISO88591Decryption() {
+ testXmlISO88591Encryption();
+ File sourceFile = new File(this.getTempDataDirectory(), "plain-iso-8859-1.enc.xml");
+ File targetFile = new File(this.getTempDataDirectory(), "plain-iso-8859-1.dec.xml");
+ try {
+ CryptoUtil.getInstance(SALT,COUNT).decrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+ }
+
+ /** Test encryption and decryption of Strings
+ */
+ @Test
+ public void testStringEncryption() {
+ char[] testVector = new char[513];
+
+ for (int i = 0; i < testVector.length; i++) {
+ testVector[i] = (char) i;
+ }
+
+ String source = new String(testVector);
+ try {
+ String cipherText = CryptoUtil.getInstance(SALT,COUNT).encryptString(source, this.getPassword());
+ String plainText = CryptoUtil.getInstance(SALT,COUNT).decryptString(cipherText, this.getPassword());
+ assertEquals(source, plainText);
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+
+ }
+
+ @Test
+ public void testStringEncryptionWithType() {
+ CryptoUtil cu = CryptoUtil.getInstance(SALT,COUNT);
+ char[] testVector = new char[513];
+
+ for (int i = 0; i < testVector.length; i++) {
+ testVector[i] = (char) i;
+ }
+
+ String source = new String(testVector);
+ String cipherText = null;
+ String plainText = null;
+ try {
+ log.info("Test without clearTextHeader");
+ cipherText = cu.encryptString(source, this.getPassword());
+ log.trace(cipherText);
+ plainText = cu.decryptString(cipherText, this.getPassword());
+ assertEquals(source, plainText, source + " is not equal with " + plainText);
+
+ log.info(String.format("Test with clearTextHeader %s in encrypted string.",
+ CryptoParametersJ8.CLEAR_CODE_DEFAULT));
+ String cipherText2 = cu.encryptStringWithClearCode(source, this.getPassword());
+ log.trace(cipherText2);
+ // old style
+ assertTrue(cipherText2.startsWith(CryptoParametersJ8.CLEAR_CODE_DEFAULT),
+ String.format("%s does not start with '%s'", cipherText2, CryptoParametersJ8.CLEAR_CODE_DEFAULT));
+ String plainText2 = cu.decryptStringWithClearCode(cipherText2, this.getPassword());
+ assertEquals(source, plainText2, String.format("%s is not equal with %s", source, plainText));
+
+ } catch (GeneralSecurityException | IOException e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ /** Test encryption and decryption of Strings
+ */
+ @Test
+ public void testStringHandling() {
+ String source = "Nobody knows the toubles I have seen ...";
+ try {
+ String cipherText = CryptoUtil.getInstance(SALT,COUNT).encryptString(source, this.getPassword());
+ String plainText = CryptoUtil.getInstance(SALT,COUNT).decryptString(cipherText, this.getPassword());
+ assertEquals(source, plainText);
+ } catch (GeneralSecurityException | IOException e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ /** Test encryption and decryption of binary data
+ * @throws Exception Generic exception
+ */
+ @Test
+ public void testBinaryHandling() throws Exception {
+ byte[] source = new byte[256];
+ byte[] result = null;
+
+ for (int i = 0; i < source.length; i++) {
+ source[i] = (byte) i;
+ }
+
+ ByteArrayOutputStream cipherText = new ByteArrayOutputStream();
+ ByteArrayOutputStream plainText = new ByteArrayOutputStream();
+
+ CryptoUtil.getInstance(SALT,COUNT).encrypt(source, cipherText, this.getPassword());
+ CryptoUtil.getInstance(SALT,COUNT).decrypt(cipherText, plainText, this.getPassword());
+
+ result = plainText.toByteArray();
+
+ for (int i = 0; i < source.length; i++) {
+ if (source[i] != result[i]) {
+ fail("Binary data are different at position " + i);
+ }
+ }
+ }
+
+ /** Test creating a password
+ * @throws Exception Generic exception
+ */
+ @Test
+ public void testPasswordFactory() throws Exception {
+ char[] result = null;
+ result = PasswordFactory.getInstance().create();
+ System.out.println(new String(result));
+ result = PasswordFactory.getInstance().create(this.getPassword());
+ log.info(new String(result));
+ assertNotNull(result);
+ }
+
+ /** Test the hex converter
+ * @throws Exception Generic exception
+ */
+ @Test
+ public void testHexConverter() throws Exception {
+ String source = "DceuATAABWSaVTSIK";
+ String hexString = HexConverter.toString(source.getBytes());
+ String result = new String(HexConverter.toBytes(hexString));
+ assertEquals(source, result);
+ }
+
+ /** Test encryption and decryption of Strings
+ * @throws Exception Generic exception
+ */
+ @Test
+ public void testPasswordEncryption() throws Exception {
+ char[] password = "57cb-4a23-d838-45222".toCharArray();
+ String source = "e02c-3b76-ff1e-5d9a1";
+ String cipherText = CryptoUtil.getInstance(SALT,COUNT).encryptString(source, password);
+ log.info(cipherText);// len 48
+ assertEquals(48, cipherText.length());
+ String plainText = CryptoUtil.getInstance(SALT,COUNT).decryptString(cipherText, password);
+ assertEquals(source, plainText);
+ }
+
+}
diff --git a/src/test/org/apache/fulcrum/jce/crypto/CryptoUtilTest.java b/src/test/org/apache/fulcrum/jce/crypto/CryptoUtilTest.java
index caf0283..8b10615 100644
--- a/src/test/org/apache/fulcrum/jce/crypto/CryptoUtilTest.java
+++ b/src/test/org/apache/fulcrum/jce/crypto/CryptoUtilTest.java
@@ -1,5 +1,10 @@
package org.apache.fulcrum.jce.crypto;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -21,12 +26,14 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
-import org.apache.fulcrum.jce.crypto.extended.CryptoUtilJ8ParameterizedTest;
+import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-
-import junit.framework.TestCase;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
/**
* Test suite for crypto functionality
@@ -34,7 +41,7 @@
* @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
*/
-public class CryptoUtilTest extends TestCase {
+public class CryptoUtilTest {
/** the password to be used */
private String password;
@@ -48,12 +55,8 @@
/**
* Constructor
- *
- * @param name the name of the test case
*/
- public CryptoUtilTest(String name) {
- super(name);
-
+ public CryptoUtilTest() {
this.password = "mysecret";
this.testDataDirectory = new File("./src/test/data");
this.tempDataDirectory = new File("./target/temp");
@@ -61,15 +64,16 @@
}
/**
- * @see junit.framework.TestCase#setUp() byte[] salt, int count, String
- * algorithm, String providerName )
*
* @throws Exception Generic exception
*/
- protected void setUp() throws Exception {
+ @BeforeAll
+ protected static void setUp() throws Exception {
CryptoStreamFactoryImpl factory = new CryptoStreamFactoryImpl(CryptoParameters.Salt(), CryptoParameters.COUNT);
CryptoStreamFactoryImpl.setInstance(factory);
+
+
}
/**
@@ -94,159 +98,205 @@
}
/** Encrypt a text file
- * @throws Exception Generic exception
*/
- public void testTextEncryption() throws Exception {
+ @Test
+ public void testTextEncryption() {
File sourceFile = new File(this.getTestDataDirectory(), "plain.txt");
File targetFile = new File(this.getTempDataDirectory(), "plain.enc.txt");
- CryptoUtil.getInstance().encrypt(sourceFile, targetFile, this.getPassword());
+ try {
+ CryptoUtil.getInstance().encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException e) {
+ fail(e);
+ } catch (IOException e) {
+ fail(e);
+ }
}
/** Decrypt a text file
- * @throws Exception Generic exception
*/
- public void testTextDecryption() throws Exception {
+ @Test
+ public void testTextDecryption() {
testTextEncryption();
File sourceFile = new File(this.getTempDataDirectory(), "plain.enc.txt");
File targetFile = new File(this.getTempDataDirectory(), "plain.dec.txt");
- CryptoUtil.getInstance().decrypt(sourceFile, targetFile.getAbsolutePath(), this.getPassword());
+ try {
+ CryptoUtil.getInstance().decrypt(sourceFile, targetFile.getAbsolutePath(), this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
}
/** Encrypt an empty text file
- *
- * @throws Exception Generic exception
*/
- public void testEmptyTextEncryption() throws Exception {
+ @Test
+ public void testEmptyTextEncryption() {
File sourceFile = new File(this.getTestDataDirectory(), "empty.txt");
File targetFile = new File(this.getTempDataDirectory(), "empty.enc.txt");
- CryptoUtil.getInstance().encrypt(sourceFile, targetFile, this.getPassword());
+ try {
+ CryptoUtil.getInstance().encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
}
/** Decrypt a text file
- * @throws Exception Generic exception
*/
- public void testEmptyTextDecryption() throws Exception {
+ @Test
+ public void testEmptyTextDecryption() {
testEmptyTextEncryption();
File sourceFile = new File(this.getTempDataDirectory(), "empty.enc.txt");
File targetFile = new File(this.getTempDataDirectory(), "empty.dec.txt");
- CryptoUtil.getInstance().decrypt(sourceFile, targetFile, this.getPassword());
+ try {
+ CryptoUtil.getInstance().decrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
}
/** Encrypt a PDF file
- *
- * @throws Exception Generic exception
*/
- public void testPdfEncryption() throws Exception {
+ @Test
+ public void testPdfEncryption() {
File sourceFile = new File(this.getTestDataDirectory(), "plain.pdf");
File targetFile = new File(this.getTempDataDirectory(), "plain.enc.pdf");
- CryptoUtil.getInstance().encrypt(sourceFile, targetFile, this.getPassword());
+ try {
+ CryptoUtil.getInstance().encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
}
/** Decrypt a PDF file
- *
- * @throws Exception Generic exception
*/
- public void testPdfDecryption() throws Exception {
+ @Test
+ public void testPdfDecryption() {
testPdfEncryption();
File sourceFile = new File(this.getTempDataDirectory(), "plain.enc.pdf");
File targetFile = new File(this.getTempDataDirectory(), "plain.dec.pdf");
- CryptoUtil.getInstance().decrypt(sourceFile, targetFile, this.getPassword());
+ try {
+ CryptoUtil.getInstance().decrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
}
/** Encrypt a ZIP file
- *
- * @throws Exception Generic exception
*/
- public void testZipEncryption() throws Exception {
+ @Test
+ public void testZipEncryption() {
File sourceFile = new File(this.getTestDataDirectory(), "plain.zip");
File targetFile = new File(this.getTempDataDirectory(), "plain.enc.zip");
- CryptoUtil.getInstance().encrypt(sourceFile, targetFile, this.getPassword());
+ try {
+ CryptoUtil.getInstance().encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
}
/** Decrypt a ZIP file
- *
- * @throws Exception Generic exception
*/
- public void testZipDecryption() throws Exception {
+ @Test
+ public void testZipDecryption() {
testZipEncryption();
File sourceFile = new File(this.getTempDataDirectory(), "plain.enc.zip");
File targetFile = new File(this.getTempDataDirectory(), "plain.dec.zip");
- CryptoUtil.getInstance().decrypt(sourceFile, targetFile, this.getPassword());
+ try {
+ CryptoUtil.getInstance().decrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
}
/** Encrypt a UTF-16 XML file
- *
- * @throws Exception Generic exception
*/
- public void testXmlUTF16Encryption() throws Exception {
+ @Test
+ public void testXmlUTF16Encryption() {
File sourceFile = new File(this.getTestDataDirectory(), "plain-utf16.xml");
File targetFile = new File(this.getTempDataDirectory(), "plain-utf16.enc.xml");
- CryptoUtil.getInstance().encrypt(sourceFile, targetFile, this.getPassword());
+ try {
+ CryptoUtil.getInstance().encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
}
/**
* Decrypt a UTF-16 XML file
- *
- * @throws Exception Generic exception
*/
- public void testXMLUTF16Decryption() throws Exception {
+ @Test
+ public void testXMLUTF16Decryption() {
testXmlUTF16Encryption();
File sourceFile = new File(this.getTempDataDirectory(), "plain-utf16.enc.xml");
File targetFile = new File(this.getTempDataDirectory(), "plain-utf16.dec.xml");
- CryptoUtil.getInstance().decrypt(sourceFile, targetFile, this.getPassword());
+ try {
+ CryptoUtil.getInstance().decrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
}
/**
* Encrypt a UTF-8 XML file
- *
- * @throws Exception Generic exception
*/
- public void testXmlUTF8Encryption() throws Exception {
+ @Test
+ public void testXmlUTF8Encryption() {
File sourceFile = new File(this.getTestDataDirectory(), "plain-utf8.xml");
File targetFile = new File(this.getTempDataDirectory(), "plain-utf8.enc.xml");
- CryptoUtil.getInstance().encrypt(sourceFile, targetFile, this.getPassword());
+ try {
+ CryptoUtil.getInstance().encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
}
/**
* Decrypt a UTF-8 XML file
- *
- * @throws Exception Generic exception
*/
- public void testXMLUTF8Decryption() throws Exception {
+ @Test
+ public void testXMLUTF8Decryption() {
testXmlUTF8Encryption();
File sourceFile = new File(this.getTempDataDirectory(), "plain-utf8.enc.xml");
File targetFile = new File(this.getTempDataDirectory(), "plain-utf8.dec.xml");
- CryptoUtil.getInstance().decrypt(sourceFile, targetFile, this.getPassword());
+ try {
+ CryptoUtil.getInstance().decrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
}
/**
* Encrypt a ISO-8859-1 XML file
- *
- * @throws Exception Generic exception
*/
- public void testXmlISO88591Encryption() throws Exception {
+ @Test
+ public void testXmlISO88591Encryption() {
File sourceFile = new File(this.getTestDataDirectory(), "plain-iso-8859-1.xml");
File targetFile = new File(this.getTempDataDirectory(), "plain-iso-8859-1.enc.xml");
- CryptoUtil.getInstance().encrypt(sourceFile, targetFile, this.getPassword());
+ try {
+ CryptoUtil.getInstance().encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
}
/**
* Decrypt a ISO-8859-1 XML file
- *
- * @throws Exception Generic exception
*/
- public void testXmlISO88591Decryption() throws Exception {
+ @Test
+ public void testXmlISO88591Decryption() {
testXmlISO88591Encryption();
File sourceFile = new File(this.getTempDataDirectory(), "plain-iso-8859-1.enc.xml");
File targetFile = new File(this.getTempDataDirectory(), "plain-iso-8859-1.dec.xml");
- CryptoUtil.getInstance().decrypt(sourceFile, targetFile, this.getPassword());
+ try {
+ CryptoUtil.getInstance().decrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
}
/** Test encryption and decryption of Strings
- *
- * @throws Exception Generic exception
*/
- public void testStringEncryption() throws Exception {
+ @Test
+ public void testStringEncryption() {
char[] testVector = new char[513];
for (int i = 0; i < testVector.length; i++) {
@@ -254,24 +304,70 @@
}
String source = new String(testVector);
- String cipherText = CryptoUtil.getInstance().encryptString(source, this.getPassword());
- String plainText = CryptoUtil.getInstance().decryptString(cipherText, this.getPassword());
- assertEquals(source, plainText);
+ try {
+ String cipherText = CryptoUtil.getInstance().encryptString(source, this.getPassword());
+ String plainText = CryptoUtil.getInstance().decryptString(cipherText, this.getPassword());
+ assertEquals(source, plainText);
+ } catch (GeneralSecurityException | IOException e) {
+ fail(e);
+ }
+
+ }
+
+ @Test
+ public void testStringEncryptionWithType() {
+ CryptoUtil cu = CryptoUtil.getInstance();
+ char[] testVector = new char[513];
+
+ for (int i = 0; i < testVector.length; i++) {
+ testVector[i] = (char) i;
+ }
+
+ String source = new String(testVector);
+ String cipherText = null;
+ String plainText = null;
+ try {
+ log.info("Test without clearTextHeader");
+ cipherText = cu.encryptString(source, this.getPassword());
+ log.trace(cipherText);
+ plainText = cu.decryptString(cipherText, this.getPassword());
+ assertEquals(source, plainText, source + " is not equal with " + plainText);
+
+ log.info(String.format("Test with clearTextHeader %s in encrypted string.",
+ CryptoParametersJ8.CLEAR_CODE_DEFAULT));
+ String cipherText2 = cu.encryptStringWithClearCode(source, this.getPassword());
+ log.trace(cipherText2);
+ // old style
+ assertTrue(cipherText2.startsWith(CryptoParametersJ8.CLEAR_CODE_DEFAULT),
+ String.format("%s does not start with '%s'", cipherText2, CryptoParametersJ8.CLEAR_CODE_DEFAULT));
+ String plainText2 = cu.decryptStringWithClearCode(cipherText2, this.getPassword());
+ assertEquals(source, plainText2, String.format("%s is not equal with %s", source, plainText));
+
+ } catch (GeneralSecurityException | IOException e) {
+ e.printStackTrace();
+ fail();
+ }
}
/** Test encryption and decryption of Strings
- * @throws Exception Generic exception
*/
- public void testStringHandling() throws Exception {
+ @Test
+ public void testStringHandling() {
String source = "Nobody knows the toubles I have seen ...";
- String cipherText = CryptoUtil.getInstance().encryptString(source, this.getPassword());
- String plainText = CryptoUtil.getInstance().decryptString(cipherText, this.getPassword());
+ try {
+ String cipherText = CryptoUtil.getInstance().encryptString(source, this.getPassword());
+ String plainText = CryptoUtil.getInstance().decryptString(cipherText, this.getPassword());
assertEquals(source, plainText);
+ } catch (GeneralSecurityException | IOException e) {
+ e.printStackTrace();
+ fail();
+ }
}
/** Test encryption and decryption of binary data
* @throws Exception Generic exception
*/
+ @Test
public void testBinaryHandling() throws Exception {
byte[] source = new byte[256];
byte[] result = null;
@@ -298,6 +394,7 @@
/** Test creating a password
* @throws Exception Generic exception
*/
+ @Test
public void testPasswordFactory() throws Exception {
char[] result = null;
result = PasswordFactory.getInstance().create();
@@ -305,12 +402,12 @@
result = PasswordFactory.getInstance().create(this.getPassword());
log.info(new String(result));
assertNotNull(result);
- return;
}
/** Test the hex converter
* @throws Exception Generic exception
*/
+ @Test
public void testHexConverter() throws Exception {
String source = "DceuATAABWSaVTSIK";
String hexString = HexConverter.toString(source.getBytes());
@@ -321,6 +418,7 @@
/** Test encryption and decryption of Strings
* @throws Exception Generic exception
*/
+ @Test
public void testPasswordEncryption() throws Exception {
char[] password = "57cb-4a23-d838-45222".toCharArray();
String source = "e02c-3b76-ff1e-5d9a1";
diff --git a/src/test/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8ExplicitParamsTest.java b/src/test/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8ExplicitParamsTest.java
new file mode 100644
index 0000000..6a0b84a
--- /dev/null
+++ b/src/test/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8ExplicitParamsTest.java
@@ -0,0 +1,371 @@
+package org.apache.fulcrum.jce.crypto.extended;
+
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.fulcrum.jce.crypto.PasswordFactory;
+import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8.TYPES;
+import org.apache.fulcrum.jce.junit5.extension.SupportedTypeArguments;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+/**
+ * Test suite for crypto functionality
+ *
+ * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
+ */
+public class CryptoUtilJ8ExplicitParamsTest {
+ /** the password to be used */
+ private String password;
+
+ /** the test data directory */
+ private File testDataDirectory;
+
+ /** the temp data director */
+ private File tempDataDirectory;
+
+
+ private static byte[] SALT = generateSalt();
+
+ private static int COUNT = 12345;
+
+ private static List<CryptoUtilJ8> cryptoUtilJ8s = new ArrayList<>();
+
+ private static Logger log = LogManager.getLogger(CryptoUtilJ8ExplicitParamsTest.class);
+
+
+ protected static byte[] generateSalt() {
+ SecureRandom random;
+ try {
+ random = SecureRandom.getInstanceStrong();
+ byte[] salt = new byte[ 16 ];
+ random.nextBytes(salt);
+ return salt;
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * Constructor
+ */
+ public CryptoUtilJ8ExplicitParamsTest() {
+
+ this.password = "mysecret";
+ this.testDataDirectory = new File("./src/test/data");
+ this.tempDataDirectory = new File("./target/temp");
+ this.tempDataDirectory.mkdirs();
+ }
+
+
+ @BeforeAll
+ public static void setUp() throws Exception {
+ cryptoUtilJ8s.clear();
+ SupportedTypeArguments.init();
+ for (TYPES type : CryptoParametersJ8.TYPES.values()) {
+ if (SupportedTypeArguments.SUPPORTED_TYPES.contains(type.toString())) {
+ cryptoUtilJ8s.add(CryptoUtilJ8.getInstance(type, SALT, COUNT));
+ }
+ }
+ for (CryptoUtilJ8 cryptoUtilJ8 : cryptoUtilJ8s) {
+ log.debug("registered {}", cryptoUtilJ8.getClass().getSimpleName() );
+ CryptoStreamFactoryJ8Template crt = ((CryptoStreamFactoryJ8Template)cryptoUtilJ8.getCryptoStreamFactory());
+ log.debug(String.format("created default crypto factory instance %s for algo %s with salt length: %s",
+ crt.getClass().getSimpleName(),
+ crt.getAlgorithm(), crt.getSalt().length));
+ }
+ }
+
+ @AfterAll
+ public static void destroy() {
+ cryptoUtilJ8s.clear();
+ }
+
+
+ /**
+ * @return Returns the password.
+ */
+ protected char[] getPassword() {
+ return password.toCharArray();
+ }
+
+ /**
+ * @return Returns the tempDataDirectory.
+ */
+ protected File getTempDataDirectory() {
+ return tempDataDirectory;
+ }
+
+ /**
+ * @return Returns the testDataDirectory.
+ */
+ protected File getTestDataDirectory() {
+ return testDataDirectory;
+ }
+
+ /** Encrypt a text file
+ *
+ */
+ @Test
+ public void testTextEncryption() {
+
+ File sourceFile = new File(this.getTestDataDirectory(), "plain.txt");
+ File targetFile = new File(this.getTempDataDirectory(), "plain.j8.enc.txt");
+
+ cryptoUtilJ8s.forEach(cuj8 -> {
+ try {
+ cuj8.encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException e) {
+ e.printStackTrace();
+ fail();
+ } catch (IOException e) {
+ e.printStackTrace();
+ fail();
+ }
+ } );
+ }
+
+ /** Decrypt a text file
+ */
+ @Test
+ public void testTextDecryption() {
+ cryptoUtilJ8s.forEach(cuj8 -> {
+ log.info("start en-/decrypting with {}",cuj8);
+ try {
+ File sourceFile = new File(this.getTestDataDirectory(), "plain.txt");
+ File targetFile = new File(this.getTempDataDirectory(), "plain.j8.enc.txt");
+ cuj8.encrypt(sourceFile, targetFile, this.getPassword());
+
+ File sourceFile2 = new File(this.getTempDataDirectory(), "plain.j8.enc.txt");;
+ File targetFile2 = new File(this.getTempDataDirectory(), "plain.j8.dec.txt");
+ cuj8.decrypt(sourceFile2, targetFile2.getAbsolutePath(), this.getPassword());
+ assertEquals(
+ new String(Files.readAllBytes( Paths.get(sourceFile.toURI())) ),
+ new String(Files.readAllBytes( Paths.get(targetFile2.toURI())) )
+ );
+ } catch (GeneralSecurityException | IOException e) {
+ e.printStackTrace();
+ fail();
+ }
+ });
+ }
+
+ /** Encrypt a PDF file
+ *
+ */
+ @Test
+ public void testPdfEncryption() {
+ File sourceFile = new File(this.getTestDataDirectory(), "plain.pdf");
+ File targetFile = new File(this.getTempDataDirectory(), "plain.j8.enc.pdf");
+ cryptoUtilJ8s.forEach(cuj8 -> {
+ try {
+ cuj8.encrypt(sourceFile, targetFile, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ e.printStackTrace();
+ fail();
+ }
+ });
+ }
+
+ /** Decrypt a PDF file
+ *
+ */
+ @Test
+ public void testPdfDecryption() {
+ //testPdfEncryption();
+ cryptoUtilJ8s.forEach(cuj8 -> {
+ try {
+ File sourceFile = new File(this.getTestDataDirectory(), "plain.pdf");
+ File targetFile = new File(this.getTempDataDirectory(), "plain.j8.enc.pdf");
+ cuj8.encrypt(sourceFile, targetFile, this.getPassword());
+
+ File sourceFile2 = new File(this.getTempDataDirectory(), "plain.j8.enc.pdf");
+ File targetFile2 = new File(this.getTempDataDirectory(), "plain.j8.dec.pdf");
+ cuj8.decrypt(sourceFile2, targetFile2, this.getPassword());
+
+ assertEquals(
+ new String(Files.readAllBytes( Paths.get(sourceFile.toURI())) ),
+ new String(Files.readAllBytes( Paths.get(targetFile2.toURI())) )
+ );
+ } catch (GeneralSecurityException | IOException e) {
+ e.printStackTrace();
+ fail();
+ }
+ });
+
+ }
+
+ /** Test encryption and decryption of Strings
+ *
+ */
+ @Test
+ public void testStringEncryption() {
+ char[] testVector = new char[513];
+
+ for (int i = 0; i < testVector.length; i++) {
+ testVector[i] = (char) i;
+ }
+
+ String source = new String(testVector);
+ cryptoUtilJ8s.forEach(cuj8 -> {
+ String cipherText;
+ String plainText;
+ try {
+ cipherText = cuj8.encryptString(source, this.getPassword());
+ plainText = cuj8.decryptString(cipherText, this.getPassword());
+ assertEquals(source, plainText, source +" is not equal with " + plainText);
+ } catch (GeneralSecurityException | IOException e) {
+ e.printStackTrace();
+ fail();
+ }
+
+ });
+
+
+ }
+
+ /** Test encryption and decryption of Strings
+ */
+ @Test
+ public void testStringHandling() {
+ String source = "Nobody knows the toubles I have seen ...";
+ cryptoUtilJ8s.forEach(cuj8 -> {
+ String cipherText;
+ try {
+ cipherText = cuj8.encryptString(source, this.getPassword());
+ String plainText = cuj8.decryptString(cipherText, this.getPassword());
+ assertEquals(source, plainText);
+ } catch (GeneralSecurityException | IOException e) {
+ e.printStackTrace();
+ fail();
+ }
+
+ });
+
+ }
+
+ /**
+ * Test creating a password
+ * @throws Exception Generic exception
+ */
+ @Test
+ public void testPasswordFactory() throws Exception {
+ char[] result = null;
+ result = PasswordFactory.getInstance("SHA-256").create();
+ log.debug("random pw: {}", new String(result));
+ result = PasswordFactory.getInstance("SHA-256",10_000).create(this.getPassword());
+ log.debug("password pw with seed: {}", new String(result));
+ assertNotNull(result);
+ return;
+ }
+
+ /** Test encryption and decryption of binary data
+ * @throws Exception Generic exception
+ */
+ @Test
+ public void testBinaryHandling() throws Exception {
+
+ cryptoUtilJ8s.forEach(cuj8 -> {
+ byte[] source = new byte[256];
+ byte[] result = null;
+
+ for (int i = 0; i < source.length; i++) {
+ source[i] = (byte) i;
+ }
+
+ ByteArrayOutputStream cipherText = new ByteArrayOutputStream();
+ ByteArrayOutputStream plainText = new ByteArrayOutputStream();
+ try {
+ cuj8.encrypt(source, cipherText, this.getPassword());
+ cuj8.decrypt(cipherText, plainText, this.getPassword());
+ } catch (GeneralSecurityException | IOException e) {
+ e.printStackTrace();
+ fail();
+ }
+ result = plainText.toByteArray();
+
+ for (int i = 0; i < source.length; i++) {
+ if (source[i] != result[i]) {
+ fail("Binary data are different at position " + i);
+ }
+ }
+ });
+
+
+
+ }
+
+ /**
+ * Test encryption and decryption of Strings
+ */
+ @Test
+ public void testStringWithPasswordEncryption() {
+ char[] password = "57cb-4a23-d838-45222".toCharArray();
+ String source = "e02c-3b76-ff1e-5d9a1";
+
+ cryptoUtilJ8s.forEach(cuj8 -> {
+ String cipherText = null;
+ try {
+ cipherText = cuj8.encryptString(source, password);
+ log.debug(cipherText);// about 128
+
+ log.debug("registered {}: {}", cuj8.getClass().getSimpleName());
+ CryptoStreamFactoryJ8Template crt = ((CryptoStreamFactoryJ8Template)cuj8.getCryptoStreamFactory());
+ log.debug(String.format("created default crypto factory instance %s for algo %s with salt (optional): %s",
+ crt.getClass().getSimpleName(),
+ crt.getAlgorithm(), crt.getSalt()));
+
+ log.debug("length for {} is: {}", crt.getType(), cipherText.length());// about 128
+ if (crt.getType() == TYPES.PBE) {
+ assertEquals(128, cipherText.length()); // 128bytes + 10 bytes for cleartext
+ }
+ CryptoStreamFactoryJ8Template.resetInstances();
+ String plainText = cuj8.decryptString(cipherText, password);
+ assertEquals(source, plainText);
+ } catch (GeneralSecurityException | IOException e) {
+ e.printStackTrace();
+ fail();
+ }
+
+ });
+
+ }
+
+}
diff --git a/src/test/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8ParameterizedTest.java b/src/test/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8ParameterizedTest.java
index ed3f275..0f278e7 100644
--- a/src/test/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8ParameterizedTest.java
+++ b/src/test/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8ParameterizedTest.java
@@ -16,18 +16,25 @@
import org.apache.fulcrum.jce.crypto.PasswordFactory;
import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8.TYPES;
+import org.apache.fulcrum.jce.junit5.extension.SupportedTypeArguments;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
+import org.junit.jupiter.params.provider.ArgumentsSource;
/**
* Test suite for crypto functionality
+ *
+ * Could still not access arguments of parameterized tests in lifecycle callback methods
+ *
+ * - https://github.com/junit-team/junit5/issues/944
+ * - https://github.com/junit-team/junit5/issues/1139#issuecomment-341683075
*
- * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
- */
+ * e.g. with ExtendWith(SupportedTypeArguments.class)
+ * */
public class CryptoUtilJ8ParameterizedTest {
/** the password to be used */
private String password;
@@ -46,19 +53,12 @@
* Constructor
*/
public CryptoUtilJ8ParameterizedTest() {
-
this.password = "mysecret";
this.testDataDirectory = new File("./src/test/data");
this.tempDataDirectory = new File("./target/temp");
this.tempDataDirectory.mkdirs();
}
-// @ParameterizedTest
-// @EnumSource( TYPES.class )
-// public void setUp(TYPES type) throws Exception {
-// cryptoUtilJ8 = CryptoUtilJ8.getInstance(type); // (TYPES.PBE);
-// }
-
/**
* @return Returns the password.
*/
@@ -80,9 +80,16 @@
return testDataDirectory;
}
- @AfterEach
+ @BeforeEach
public void setup() {
cryptoUtilJ8s.clear();
+ SupportedTypeArguments.init();
+ }
+
+
+ @AfterEach
+ public void clean() {
+ cryptoUtilJ8s.clear();
}
/**
@@ -94,7 +101,7 @@
*
*/
@ParameterizedTest
- @EnumSource(TYPES.class)
+ @ArgumentsSource(SupportedTypeArguments.class)
public void testTextEncryption(TYPES type) {
cryptoUtilJ8s.add(CryptoUtilJ8.getInstance(type));
@@ -103,7 +110,11 @@
cryptoUtilJ8s.forEach(cuj8 -> {
try {
- log.info("checking " + cuj8.getType());
+ log.debug("registered {}: {}", cuj8.getClass().getSimpleName());
+ CryptoStreamFactoryJ8Template crt = ((CryptoStreamFactoryJ8Template)cuj8.getCryptoStreamFactory());
+ log.debug(String.format("created default crypto factory instance %s for algo %s with salt (optional): %s",
+ crt.getClass().getSimpleName(),
+ crt.getAlgorithm(), crt.getSalt()));
cuj8.encrypt(sourceFile, targetFile, this.getPassword());
} catch (GeneralSecurityException e) {
e.printStackTrace();
@@ -122,11 +133,15 @@
*
*/
@ParameterizedTest
- @EnumSource(TYPES.class)
+ @ArgumentsSource(SupportedTypeArguments.class)
public void testTextDecryption(TYPES type) {
cryptoUtilJ8s.add(CryptoUtilJ8.getInstance(type));
cryptoUtilJ8s.forEach(cuj8 -> {
- log.info("checking " + cuj8.getType());
+ log.debug("registered {}: {}", cuj8.getClass().getSimpleName());
+ CryptoStreamFactoryJ8Template crt = ((CryptoStreamFactoryJ8Template)cuj8.getCryptoStreamFactory());
+ log.debug(String.format("created default crypto factory instance %s for algo %s with salt length: %s",
+ crt.getClass().getSimpleName(),
+ crt.getAlgorithm(), crt.getSalt().length));
try {
File sourceFile = new File(this.getTestDataDirectory(), "plain.txt");
File targetFile = new File(this.getTempDataDirectory(), "plain.j8.enc.txt");
@@ -153,7 +168,7 @@
*
*/
@ParameterizedTest
- @EnumSource(TYPES.class)
+ @ArgumentsSource(SupportedTypeArguments.class)
public void testPdfEncryption(TYPES type) {
cryptoUtilJ8s.add(CryptoUtilJ8.getInstance(type));
File sourceFile = new File(this.getTestDataDirectory(), "plain.pdf");
@@ -175,7 +190,7 @@
*
*/
@ParameterizedTest
- @EnumSource(TYPES.class)
+ @ArgumentsSource(SupportedTypeArguments.class)
public void testPdfDecryption(TYPES type) {
cryptoUtilJ8s.add(CryptoUtilJ8.getInstance(type));
// testPdfEncryption();
@@ -206,9 +221,15 @@
*
*/
@ParameterizedTest
- @EnumSource(TYPES.class)
+ @ArgumentsSource(SupportedTypeArguments.class)
public void testStringEncryption(TYPES type) {
CryptoUtilJ8 cuj8 = CryptoUtilJ8.getInstance(type);
+
+ log.debug("registered {} and called for {}", cuj8.getClass().getSimpleName(), type);
+ CryptoStreamFactoryJ8Template crt = ((CryptoStreamFactoryJ8Template)cuj8.getCryptoStreamFactory());
+ log.debug(String.format("created default crypto factory instance %s for algo %s with salt length: %s",
+ crt.getClass().getSimpleName(),
+ crt.getAlgorithm(), crt.getSalt().length));
char[] testVector = new char[513];
for (int i = 0; i < testVector.length; i++) {
@@ -219,18 +240,20 @@
String cipherText = null;
String plainText = null;
try {
- log.info("Test without clearTextHeader");
+ log.info("Test without clearTextHeader in type {}", type);
cipherText = cuj8.encryptString(source, this.getPassword());
- // log.debug(cipherText);
+ log.trace(cipherText);
plainText = cuj8.decryptString(cipherText, this.getPassword());
assertEquals(source, plainText, source + " is not equal with " + plainText);
+
+ String clearCode = type.equals(TYPES.PBE)? CryptoParametersJ8.TYPES.PBE.getClearCode():
+ CryptoParametersJ8.TYPES.GCM.getClearCode() ;
- log.info(String.format("Test with clearTextHeader %s in encrypted string.",
- CryptoParametersJ8.CLEAR_CODE_J8));
+ log.info(String.format("Test with clearTextHeader %s in encrypted string.",clearCode) );
String cipherText2 = cuj8.encryptStringWithClearCode(source, this.getPassword());
- // log.debug(cipherText2);
- assertTrue(cipherText2.startsWith(CryptoParametersJ8.CLEAR_CODE_J8),
- String.format("%s does not start with '%s'", cipherText2, CryptoParametersJ8.CLEAR_CODE_J8));
+ log.trace(cipherText2);
+ assertTrue(cipherText2.startsWith(clearCode),
+ String.format("%s does not start with '%s'", cipherText2, clearCode));
String plainText2 = cuj8.decryptStringWithClearCode(cipherText2, this.getPassword());
assertEquals(source, plainText2, String.format("%s is not equal with %s", source, plainText));
@@ -247,7 +270,7 @@
*
*/
@ParameterizedTest
- @EnumSource(TYPES.class)
+ @ArgumentsSource(SupportedTypeArguments.class)
public void testStringHandling(TYPES type) {
cryptoUtilJ8s.add(CryptoUtilJ8.getInstance(type));
String source = "Nobody knows the toubles I have seen ...";
@@ -292,7 +315,7 @@
* @param type the type to be tested based on {@link TYPES}
*/
@ParameterizedTest
- @EnumSource(TYPES.class)
+ @ArgumentsSource(SupportedTypeArguments.class)
public void testBinaryHandling(TYPES type) throws Exception {
cryptoUtilJ8s.add(CryptoUtilJ8.getInstance(type));
cryptoUtilJ8s.forEach(cuj8 -> {
@@ -332,23 +355,28 @@
*
*/
@ParameterizedTest
- @EnumSource(TYPES.class)
+ @ArgumentsSource(SupportedTypeArguments.class)
public void testStringWithPasswordEncryption(TYPES type) {
char[] password = "57cb-4a23-d838-45222".toCharArray();
String source = "e02c-3b76-ff1e-5d9a1";
CryptoUtilJ8 cuj8 = CryptoUtilJ8.getInstance(type);
- log.debug("checking type " + cuj8.getType());
+ log.debug("registered {}: {}", cuj8.getClass().getSimpleName());
+ CryptoStreamFactoryJ8Template crt = ((CryptoStreamFactoryJ8Template)cuj8.getCryptoStreamFactory());
+ log.debug(String.format("created default crypto factory instance %s for algo %s with salt (optional): %s",
+ crt.getClass().getSimpleName(),
+ crt.getAlgorithm(), crt.getSalt()));
String cipherText = null;
try {
cipherText = cuj8.encryptString(source, password);
log.info(cipherText);// about 128
- log.info(String.format("length for %s is %d", cuj8.getType(), cipherText.length()));// about 128
- if (cuj8.type == TYPES.PBE) {
- assertEquals(128, cipherText.length()); // 128bytes + 10 bytes for cleartext
- }
- if (cuj8.type == TYPES.GCM) {
- assertEquals(128, cipherText.length());
- }
+ log.info(String.format("length for %s is %d", cuj8, cipherText.length()));// about 128
+ assertEquals(128, cipherText.length());
+// if (cuj8.type == TYPES.PBE) {
+// assertEquals(128, cipherText.length()); // 128bytes + 10 bytes for cleartext
+// }
+// if (cuj8.type == TYPES.GCM) {
+// assertEquals(128, cipherText.length());
+// }
String plainText = cuj8.decryptString(cipherText, password);
assertEquals(source, plainText);
} catch (GeneralSecurityException | IOException e) {
diff --git a/src/test/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8Test.java b/src/test/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8Test.java
index 3c7570b..2b7ef55 100644
--- a/src/test/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8Test.java
+++ b/src/test/org/apache/fulcrum/jce/crypto/extended/CryptoUtilJ8Test.java
@@ -11,6 +11,8 @@
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
@@ -18,6 +20,7 @@
import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8;
import org.apache.fulcrum.jce.crypto.extended.CryptoStreamFactoryJ8Template;
import org.apache.fulcrum.jce.crypto.extended.CryptoUtilJ8;
+import org.apache.fulcrum.jce.junit5.extension.SupportedTypeArguments;
import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8.TYPES;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -25,6 +28,24 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
/**
* Test suite for crypto functionality
@@ -60,17 +81,21 @@
@BeforeAll
public static void setUp() throws Exception {
cryptoUtilJ8s.clear();
+ SupportedTypeArguments.init();
for (TYPES type : CryptoParametersJ8.TYPES.values()) {
- cryptoUtilJ8s.add(CryptoUtilJ8.getInstance(type));
+ if (SupportedTypeArguments.SUPPORTED_TYPES.contains(type.toString())) {
+ cryptoUtilJ8s.add(CryptoUtilJ8.getInstance(type));
+ }
}
for (CryptoUtilJ8 cryptoUtilJ8 : cryptoUtilJ8s) {
- log.debug("registered {}: {}", cryptoUtilJ8.getClass().getSimpleName(), cryptoUtilJ8.getType() );
+ log.debug("registered {}: {}", cryptoUtilJ8.getClass().getSimpleName());
CryptoStreamFactoryJ8Template crt = ((CryptoStreamFactoryJ8Template)cryptoUtilJ8.getCryptoStreamFactory());
- log.debug(String.format("created default crypto factory instance %s for algo %s", crt.getClass().getSimpleName(),
- crt.getAlgorithm()));
+ log.debug(String.format("created default crypto factory instance %s for algo %s with salt length: %s",
+ crt.getClass().getSimpleName(),
+ crt.getAlgorithm(), crt.getSalt().length));
}
-
}
+
@AfterAll
public static void destroy() {
cryptoUtilJ8s.clear();
@@ -124,8 +149,13 @@
*/
@Test
public void testTextDecryption() {
- cryptoUtilJ8s.forEach(cuj8 -> {
- try {
+ cryptoUtilJ8s.forEach(cuj8 -> {
+ log.debug("registered {}: {}", cuj8.getClass().getSimpleName());
+ CryptoStreamFactoryJ8Template crt = ((CryptoStreamFactoryJ8Template)cuj8.getCryptoStreamFactory());
+ log.debug(String.format("created default crypto factory instance %s for algo %s with salt length: %s",
+ crt.getClass().getSimpleName(),
+ crt.getAlgorithm(), crt.getSalt().length));
+ try {
File sourceFile = new File(this.getTestDataDirectory(), "plain.txt");
File targetFile = new File(this.getTempDataDirectory(), "plain.j8.enc.txt");
cuj8.encrypt(sourceFile, targetFile, this.getPassword());
@@ -302,9 +332,14 @@
try {
cipherText = cuj8.encryptString(source, password);
log.debug(cipherText);// about 128
+
+ CryptoStreamFactoryJ8Template crt = ((CryptoStreamFactoryJ8Template)cuj8.getCryptoStreamFactory());
+ log.debug(String.format("created default crypto factory instance %s for algo %s and type %s with salt (optional): %s",
+ crt.getClass().getSimpleName(), crt.getType(),
+ crt.getAlgorithm(), crt.getSalt()));
- log.debug("length for {} is: {}", cuj8.getType(), cipherText.length());// about 128
- if (cuj8.type == TYPES.PBE) {
+ log.debug("length for {} is: {}", crt.getType(), cipherText.length());// about 128
+ if (crt.getType() == TYPES.PBE) {
assertEquals(128, cipherText.length()); // 128bytes + 10 bytes for cleartext
}
CryptoStreamFactoryJ8Template.resetInstances();
diff --git a/src/test/org/apache/fulcrum/jce/crypto/extended/Main8Test.java b/src/test/org/apache/fulcrum/jce/crypto/extended/Main8Test.java
index 6453529..ecd6228 100644
--- a/src/test/org/apache/fulcrum/jce/crypto/extended/Main8Test.java
+++ b/src/test/org/apache/fulcrum/jce/crypto/extended/Main8Test.java
@@ -1,23 +1,25 @@
package org.apache.fulcrum.jce.crypto.extended;
import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;
-import org.apache.commons.io.Charsets;
import org.apache.commons.io.FileUtils;
import org.apache.fulcrum.jce.crypto.cli.CLI2;
import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8.TYPES;
+import org.apache.fulcrum.jce.junit5.extension.SupportedTypeArguments;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
-
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
/*
@@ -39,177 +41,198 @@
* under the License.
*/
-
/**
* Test suite for crypto functionality
*
* @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
*/
-public class Main8Test
-{
- /** the password to be used */
- private String password;
-
- /**
- * Constructor
- */
- public Main8Test() {
+public class Main8Test {
+ /** the password to be used */
+ private String password;
- this.password = "foobar";
- ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
- builder.setStatusLevel(Level.DEBUG);
- }
-
+ /**
+ * Constructor
+ */
+ public Main8Test() {
- /**
- * @return Returns the password.
- */
- protected char[] getPassword()
- {
- return password.toCharArray();
- }
-
-
- /** Encrypt a string on the command line */
- @Test
- public void testStringEncryption()
- {
- String[] encryptionArgs = { "string", "enc", this.password, "mysecretpassword"};
- CLI2.main(encryptionArgs);
- String[] decryptionArgs = { "string", "dec", this.password, "ce3bf02da8a57c94b4f42c084230d1bedcd856c49a3fd23ec59835ca46a3d37ee02d470394691353478c905e7b342316d1fcc3e1b98837bf0595ef50853922df"};
- CLI2.main(decryptionArgs);
- }
- @Test
- public void testAnotherStringEncryption()
- {
- String[] encryptionArgs = { "string", "enc", this.password, "secret"};
- CLI2.main(encryptionArgs);
- String[] decryptionArgs = { "string", "dec", this.password, "8626904c9e64fddfa64add56472c4796429b0adb7c8039424adef7434be6bc255ce092011e8c560965814e806dd68117"};
- CLI2.main(decryptionArgs);
- }
- @Test
- /** Encrypt a text file on the command line */
- public void testFileEncryption1()
- {
- String[] encryptionArgs = { "file", "enc", this.password, "./src/test/data/plain.txt", "./target/main8/plain.enc.txt" };
- String[] decryptionArgs = { "file", "dec", this.password, "./target/main8/plain.enc.txt", "./target/main8/plain.dec.txt" };
- CLI2.main(encryptionArgs);
- CLI2.main(decryptionArgs);
- try {
- assertTrue(
- FileUtils.contentEquals(new File("./src/test/data/plain.txt"), new File("./target/main8/plain.dec.txt"))
- );
- } catch (IOException e) {
- fail();
+ this.password = "foobar";
+ ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
+ builder.setStatusLevel(Level.DEBUG);
+ }
+
+ @BeforeAll
+ public static void setup() {
+ SupportedTypeArguments.init();
+ }
+
+ /**
+ * @return Returns the password.
+ */
+ protected char[] getPassword() {
+ return password.toCharArray();
+ }
+
+ /** Encrypt a string on the command line */
+ @Test
+ public void testStringEncryption() {
+ String[] encryptionArgs = { "string", "enc", this.password, "mysecretpassword" };
+ CLI2.main(encryptionArgs);
+ String[] decryptionArgs = { "string", "dec", this.password,
+ "ce3bf02da8a57c94b4f42c084230d1bedcd856c49a3fd23ec59835ca46a3d37ee02d470394691353478c905e7b342316d1fcc3e1b98837bf0595ef50853922df" };
+ CLI2.main(decryptionArgs);
+ }
+
+ @Test
+ public void testAnotherStringEncryption() {
+ String[] encryptionArgs = { "string", "enc", this.password, "secret" };
+ CLI2.main(encryptionArgs);
+ String[] decryptionArgs = { "string", "dec", this.password,
+ "8626904c9e64fddfa64add56472c4796429b0adb7c8039424adef7434be6bc255ce092011e8c560965814e806dd68117" };
+ CLI2.main(decryptionArgs);
+ }
+
+ @Test
+ /** Encrypt a text file on the command line */
+ public void testFileEncryption1() {
+ String[] encryptionArgs = { "file", "enc", this.password, "./src/test/data/plain.txt",
+ "./target/main8/plain.enc.txt" };
+ String[] decryptionArgs = { "file", "dec", this.password, "./target/main8/plain.enc.txt",
+ "./target/main8/plain.dec.txt" };
+ CLI2.main(encryptionArgs);
+ CLI2.main(decryptionArgs);
+ try {
+ assertTrue(FileUtils.contentEquals(new File("./src/test/data/plain.txt"),
+ new File("./target/main8/plain.dec.txt")));
+ } catch (IOException e) {
+ fail();
+ }
+ }
+
+ @Test
+ /** Encrypt a text file in-place on the command line */
+ public void testFileEncryption2() {
+ String[] encryptionArgs = { "file", "enc", this.password, "./src/test/data/plain.txt",
+ "./target/main8/plain.txt" };
+ // caution decrypting into source file!
+ String[] decryptionArgs = { "file", "dec", this.password, "./target/main8/plain.txt" };
+ CLI2.main(encryptionArgs);
+ CLI2.main(decryptionArgs);
+ }
+
+ @Test
+ public void testYetAnotherStringEncryption() {
+ try {
+ // assumptions
+ String topSecret = "mysecretpassword";
+ assertTrue(FileUtils.readFileToString(new File("./src/test/data/plain-simple.txt"), StandardCharsets.UTF_8)
+ .equals(topSecret));
+
+ if (SupportedTypeArguments.SUPPORTED_TYPES.contains(TYPES.GCM.toString())) {
+
+ // test
+ // encode from string = hexdecimal file
+ String[] encryptionArgs = { "string", "enc" + TYPES.GCM, this.password, topSecret,
+ "./target/main8/another-plain16chars.enc.txt" };
+ CLI2.main(encryptionArgs);
+ // shows hex dec in stderr + file
+
+ String[] decryptionArgs = { "string", "dec" + TYPES.GCM, this.password,
+ "c9fa3e7d3c49d379ee8ff2dff6e6effbafee264794a03d0ffd895caac2b3c9b4558087f5b12e72a92475f1ed638b7911389234b443d4ebcf351c86cb",
+ "./target/main8/another-plain16chars.dec.txt" };
+ CLI2.main(decryptionArgs);
+ // shows clear password in stdout + file
+
+ assertTrue(FileUtils.readFileToString(new File("./target/main8/another-plain16chars.dec.txt"),
+ StandardCharsets.UTF_8).equals(topSecret));
+
+ String[] decryptionArgs2 = { "string", "dec" + TYPES.GCM, this.password,
+ "605efd3009a7242a9c9cab23aa712d6d116e8686732194d3306416cda2a416df1e63aeffcdc1910af1e1100b382b24fc628d9c413ebf7e1b2885c0ec" };
+ CLI2.main(decryptionArgs2);
+ // shows clear password in stdout (offline decoded)
+
+ // file mode commands do show nothing on stdout, except Decrypting / Encrypting
+
+ // should not fail, if converted from hex
+ String[] decryptionArgs3 = { "file", "dec" + TYPES.GCM, this.password,
+ "./target/main8/another-plain16chars.enc.txt", "./target/main8/another-plain16chars2.dec.txt" };
+ CLI2.main(decryptionArgs3);
+ assertTrue(FileUtils.readFileToString(new File("./target/main8/another-plain16chars2.dec.txt"),
+ StandardCharsets.UTF_8).equals(topSecret));
+
+ String[] encryptionArgs4 = { "file", "enc" + TYPES.GCM, this.password,
+ "./src/test/data/plain-simple.txt", "./target/main8/plain-simple.enc.txt" };
+ CLI2.main(encryptionArgs4);
+
+ String[] decryptionArgs4 = { "file", "dec" + TYPES.GCM, this.password,
+ "./target/main8/plain-simple.enc.txt", "./target/main8/plain-simple.dec.txt" };
+ CLI2.main(decryptionArgs4);
+
+ try {
+ assertTrue(FileUtils.contentEquals(new File("./src/test/data/plain-simple.txt"),
+ new File("./target/main8/plain-simple.dec.txt")));
+ } catch (IOException e) {
+ fail();
+ }
+
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void testIntegratedStringEncryption() {
+ try {
+ // assumptions
+ String topSecret = "myX!_secretp@ssword?~,2";
+
+ Map<String, Object> conf = new HashMap<>();
+ conf.put("enc", TYPES.GCM);
+
+ // encode as string to stderr and file in hexdecimal format
+ String[] encryptionArgs = { "string", "enc" + conf.get("enc"), this.password, topSecret,
+ "./target/main8/integrated-plain16chars.enc.txt" };
+ CLI2.main(encryptionArgs);
+ // shows encoded hexdec in stdout + file
+
+ String encodedEncrypted = FileUtils.readFileToString(
+ new File("./target/main8/integrated-plain16chars.enc.txt"), StandardCharsets.UTF_8);
+
+ conf.put("pw", encodedEncrypted);
+
+ // this should be done without output to console
+ String result = CLI2.processString("dec" + conf.get("enc"), this.password.toCharArray(),
+ (String) conf.get("pw"));
+
+ assertTrue(result.equals(topSecret));
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void testDefaultStringEncryption() {
+ char[] testVector = new char[513];
+
+ for (int i = 0; i < testVector.length; i++) {
+ testVector[i] = (char) i;
}
- }
- @Test
- /** Encrypt a text file in-place on the command line */
- public void testFileEncryption2()
- {
- String[] encryptionArgs = { "file", "enc", this.password, "./src/test/data/plain.txt", "./target/main8/plain.txt" };
- // caution decrypting into source file!
- String[] decryptionArgs = { "file", "dec", this.password, "./target/main8/plain.txt" };
- CLI2.main(encryptionArgs);
- CLI2.main(decryptionArgs);
- }
-
- @Test
- public void testYetAnotherStringEncryption()
- {
+ String source = new String(testVector);
+
+ CryptoUtilJ8.getInstances().clear();
+ CryptoUtilJ8 cuj8 = CryptoUtilJ8.getInstance();
+ String cipherText;
+ String plainText;
try {
- // assumptions
- String topSecret= "mysecretpassword";
- assertTrue(FileUtils.readFileToString(
- new File("./src/test/data/plain-simple.txt"), StandardCharsets.UTF_8).
- equals(topSecret));
- // test
- // encode from string = hexdecimal file
- String[] encryptionArgs = { "string", "enc"+TYPES.GCM, this.password, topSecret,
- "./target/main8/another-plain16chars.enc.txt"};
- CLI2.main(encryptionArgs);
- // shows hex dec in stderr + file
-
- String[] decryptionArgs = { "string", "dec"+TYPES.GCM, this.password,
- "c9fa3e7d3c49d379ee8ff2dff6e6effbafee264794a03d0ffd895caac2b3c9b4558087f5b12e72a92475f1ed638b7911389234b443d4ebcf351c86cb",
- "./target/main8/another-plain16chars.dec.txt"};
- CLI2.main(decryptionArgs);
- // shows clear password in stdout + file
-
- assertTrue(
- FileUtils.readFileToString(
- new File("./target/main8/another-plain16chars.dec.txt"), StandardCharsets.UTF_8).
- equals(topSecret));
-
- String[] decryptionArgs2 = { "string", "dec"+TYPES.GCM, this.password,
- "605efd3009a7242a9c9cab23aa712d6d116e8686732194d3306416cda2a416df1e63aeffcdc1910af1e1100b382b24fc628d9c413ebf7e1b2885c0ec"};
- CLI2.main(decryptionArgs2);
- // shows clear password in stdout (offline decoded)
-
- // file mode commands do show nothing on stdout, except Decrypting / Encrypting
-
- // should not fail, if converted from hex
- String[] decryptionArgs3 = { "file", "dec"+TYPES.GCM, this.password, "./target/main8/another-plain16chars.enc.txt", "./target/main8/another-plain16chars2.dec.txt"};
- CLI2.main(decryptionArgs3);
- assertTrue(
- FileUtils.readFileToString(
- new File("./target/main8/another-plain16chars2.dec.txt"), StandardCharsets.UTF_8).
- equals(topSecret));
-
- String[] encryptionArgs4 = { "file", "enc"+TYPES.GCM, this.password,
- "./src/test/data/plain-simple.txt", "./target/main8/plain-simple.enc.txt" };
- CLI2.main(encryptionArgs4);
-
- String[] decryptionArgs4 = { "file", "dec"+TYPES.GCM, this.password,
- "./target/main8/plain-simple.enc.txt", "./target/main8/plain-simple.dec.txt"};
- CLI2.main(decryptionArgs4);
-
- try {
- assertTrue(
- FileUtils.contentEquals(
- new File("./src/test/data/plain-simple.txt"),
- new File("./target/main8/plain-simple.dec.txt"))
- );
- } catch (IOException e) {
- fail();
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- fail();
- }
- }
-
- @Test
- public void testIntegratedStringEncryption()
- {
- try {
- // assumptions
- String topSecret= "myX!_secretp@ssword?~,2";
-
- Map<String,Object> conf = new HashMap<>();
- conf.put("enc",TYPES.GCM);
-
- // encode as string to stderr and file in hexdecimal format
- String[] encryptionArgs = {
- "string", "enc"+ conf.get("enc"), this.password,
- topSecret,
- "./target/main8/integrated-plain16chars.enc.txt"};
- CLI2.main(encryptionArgs);
- // shows encoded hexdec in stdout + file
-
- String encodedEncrypted = FileUtils.readFileToString(new File("./target/main8/integrated-plain16chars.enc.txt"), StandardCharsets.UTF_8);
-
- conf.put("pw", encodedEncrypted);
-
- // this should be done without output to console
- String result = CLI2.processString( "dec"+ conf.get("enc"), this.password.toCharArray(), (String) conf.get("pw"));
-
- assertTrue(
- result.equals(topSecret));
-
- } catch (Exception e) {
+ cipherText = cuj8.encryptString(source, this.getPassword());
+ plainText = cuj8.decryptString(cipherText, this.getPassword());
+ assertEquals(source, plainText, source +" is not equal with " + plainText);
+ } catch (GeneralSecurityException | IOException e) {
e.printStackTrace();
fail();
}
diff --git a/src/test/org/apache/fulcrum/jce/junit5/extension/SupportedTypeArguments.java b/src/test/org/apache/fulcrum/jce/junit5/extension/SupportedTypeArguments.java
new file mode 100644
index 0000000..c475523
--- /dev/null
+++ b/src/test/org/apache/fulcrum/jce/junit5/extension/SupportedTypeArguments.java
@@ -0,0 +1,71 @@
+package org.apache.fulcrum.jce.junit5.extension;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8;
+import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8.TYPES;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Using {@link CryptoParametersJ8#init()} and ArgumentsProvider to filter parameters.
+ *
+ * Could still not access arguments of parameterized tests in lifecycle callback methods
+ *
+ * - https://github.com/junit-team/junit5/issues/944
+ * - https://github.com/junit-team/junit5/issues/1139#issuecomment-341683075
+ *
+ * @author gkallidis
+ *
+ */
+public class SupportedTypeArguments implements ArgumentsProvider {
+
+ public static Logger log = LogManager.getLogger();
+
+ public static List<String> SUPPORTED_TYPES = null;
+
+ public static void init() {
+ if (SUPPORTED_TYPES == null) {
+ SUPPORTED_TYPES = CryptoParametersJ8.init();
+ }
+ log.warn("SUPPORTED_TYPES: {}",SupportedTypeArguments.SUPPORTED_TYPES);
+ }
+
+ @Override
+ public Stream<? extends Arguments> provideArguments(ExtensionContext arg0) throws Exception {
+ if (SUPPORTED_TYPES == null) {
+ init();
+ }
+ return SUPPORTED_TYPES.stream().map(Arguments::of);
+ }
+
+ public static List<String> getSUPPORTED_TYPES() {
+ return SUPPORTED_TYPES;
+ }
+
+}
diff --git a/xdocs/index.xml b/xdocs/index.xml
index 66a9b0d..8e21359 100644
--- a/xdocs/index.xml
+++ b/xdocs/index.xml
@@ -120,7 +120,7 @@
</tr>
</table>
</subsection>
- <subsection name="Availabe Algorithms">
+ <subsection name="Availabe Cipher Algorithms (Algorithm Modes)">
<table>
<tr>
<th>Provider Version</th>
@@ -134,10 +134,14 @@
<td>SunJCE 1.42</td>
<td>PBEWithMD5AndDES</td>
</tr>
- <tr>
+ <tr>
<td>SunJCE (Java 8)</td>
<td>PBEWithHmacSHA256AndAES_256</td>
</tr>
+ <tr>
+ <td>SunJCE (Java 8)</td>
+ <td>AES_128/GCM/NoPadding</td>
+ </tr>
</table>
</subsection>
</section>