From 6da8cae15329164ade3a34cc58e3f152fc266ce6 Mon Sep 17 00:00:00 2001 From: Boy Baukema Date: Thu, 21 Jun 2018 23:05:14 +0200 Subject: [PATCH 1/3] Fixed package names for crypto_applications.password_management. --- crypto_applications/password_management/Authentication.java | 2 +- .../password_management/PasswordManagementUtils.java | 2 +- crypto_applications/password_management/PasswordStorage.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crypto_applications/password_management/Authentication.java b/crypto_applications/password_management/Authentication.java index cf2dd95..99f1095 100644 --- a/crypto_applications/password_management/Authentication.java +++ b/crypto_applications/password_management/Authentication.java @@ -1,4 +1,4 @@ -package crypto_usecases.password_management ; +package crypto_applications.password_management ; import java.util.Base64 ; import java.security.GeneralSecurityException; diff --git a/crypto_applications/password_management/PasswordManagementUtils.java b/crypto_applications/password_management/PasswordManagementUtils.java index cace429..e700c1b 100644 --- a/crypto_applications/password_management/PasswordManagementUtils.java +++ b/crypto_applications/password_management/PasswordManagementUtils.java @@ -1,4 +1,4 @@ -package crypto_usecases.password_management; +package crypto_applications.password_management; import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; diff --git a/crypto_applications/password_management/PasswordStorage.java b/crypto_applications/password_management/PasswordStorage.java index c7ac36e..b29a108 100644 --- a/crypto_applications/password_management/PasswordStorage.java +++ b/crypto_applications/password_management/PasswordStorage.java @@ -1,4 +1,4 @@ -package crypto_usecases.password_management ; +package crypto_applications.password_management ; import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; From 345a3c42377b3831c51ba15cffb21693b3f585c4 Mon Sep 17 00:00:00 2001 From: Boy Baukema Date: Thu, 21 Jun 2018 23:06:21 +0200 Subject: [PATCH 2/3] Added example of AES encryption based on PBE --- .../password_management/DataEncryption.java | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 crypto_applications/password_management/DataEncryption.java diff --git a/crypto_applications/password_management/DataEncryption.java b/crypto_applications/password_management/DataEncryption.java new file mode 100644 index 0000000..e22baee --- /dev/null +++ b/crypto_applications/password_management/DataEncryption.java @@ -0,0 +1,103 @@ +package crypto_applications.password_management; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.SecureRandom; +import java.security.spec.KeySpec; +import java.util.regex.Pattern; + +public class DataEncryption { + public static void main(String[] args) { + if (args.length < 3) { + System.err.println("Missing arguments. Usage: java DataEncryption encrypt password salt < file"); + System.exit(1); + } + String output = ""; + char[] password = args[1].toCharArray(); + String salt = args[2]; + try { + String input = readStdIn(); + + if (args[0].equals("encrypt")) { + output = encrypt(input, password, salt); + } else if (args[0].equals("decrypt")) { + output = decrypt(input, password, salt); + } else { + System.err.println("Invalid operation, first argument must be 'encrypt' or 'decrypt'"); + System.exit(1); + } + } catch (GeneralSecurityException e) { + e.printStackTrace(System.err); + System.exit(1); + } + + System.out.println(output); + } + + private static String encrypt(String data, char[] password, String salt) throws GeneralSecurityException { + PasswordManagementUtils utils = new PasswordManagementUtils(); + + KeySpec spec = new PBEKeySpec(password); + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithHmacSHA512AndAES_128"); + SecretKey tmp = factory.generateSecret(spec); + SecretKeySpec secret = new SecretKeySpec(tmp.getEncoded(), "PBEWithHmacSHA512AndAES_128"); + + byte iv[] = new byte[16]; + + SecureRandom secRandom = new SecureRandom() ; + secRandom.nextBytes(iv); // self-seeded randomizer to generate IV + + IvParameterSpec randomIvSpec = new IvParameterSpec(iv) ; + + PBEParameterSpec pbeSpec = new PBEParameterSpec(salt.getBytes(), 4096, randomIvSpec); + Cipher c = Cipher.getInstance("PBEWITHHMACSHA512ANDAES_128"); + c.init(Cipher.ENCRYPT_MODE, secret, pbeSpec); + byte[] encrypted = c.doFinal(data.getBytes()); + + return utils.returnStringRep(encrypted) + "$" + utils.returnStringRep(iv); + } + + private static String decrypt(String data, char[] password, String salt) throws GeneralSecurityException { + PasswordManagementUtils utils = new PasswordManagementUtils(); + + String[] dataParts = data.split(Pattern.quote("$")); + if (dataParts.length != 2) { + throw new GeneralSecurityException("Data does not contain IV?"); + } + byte[] encrypted = utils.returnByteArray(dataParts[0].trim()); + byte[] iv = utils.returnByteArray(dataParts[1].trim()); + + KeySpec spec = new PBEKeySpec(password); + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithHmacSHA512AndAES_128"); + SecretKey tmp = factory.generateSecret(spec); + SecretKeySpec secret = new SecretKeySpec(tmp.getEncoded(), "PBEWithHmacSHA512AndAES_128"); + + IvParameterSpec ivSpec = new IvParameterSpec(iv); + PBEParameterSpec pbeSpec = new PBEParameterSpec(salt.getBytes(), 4096, ivSpec); + Cipher c = Cipher.getInstance("PBEWITHHMACSHA512ANDAES_128"); + c.init(Cipher.DECRYPT_MODE, secret, pbeSpec); + + return new String(c.doFinal(encrypted)); + } + + private static String readStdIn() throws GeneralSecurityException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[32 * 1024]; + + try { + int bytesRead; + while ((bytesRead = System.in.read(buffer)) > 0) { + baos.write(buffer, 0, bytesRead); + } + return baos.toString(); + } catch (IOException e) { throw new GeneralSecurityException("Unable to read stdin"); } + } +} From 772df03019808c8c99423c91339c4970f320545f Mon Sep 17 00:00:00 2001 From: Boy Baukema Date: Thu, 21 Jun 2018 23:33:04 +0200 Subject: [PATCH 3/3] Extract constants to class constants and increase iteration count for PBE. --- .../password_management/DataEncryption.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/crypto_applications/password_management/DataEncryption.java b/crypto_applications/password_management/DataEncryption.java index e22baee..833f863 100644 --- a/crypto_applications/password_management/DataEncryption.java +++ b/crypto_applications/password_management/DataEncryption.java @@ -15,6 +15,11 @@ import java.util.regex.Pattern; public class DataEncryption { + + public static final String ALGORITHM = "PBEWITHHMACSHA512ANDAES_128"; + public static final String IV_SEPARATOR = "$"; + public static final int ITERATION_COUNT = 200000; + public static void main(String[] args) { if (args.length < 3) { System.err.println("Missing arguments. Usage: java DataEncryption encrypt password salt < file"); @@ -46,9 +51,9 @@ private static String encrypt(String data, char[] password, String salt) throws PasswordManagementUtils utils = new PasswordManagementUtils(); KeySpec spec = new PBEKeySpec(password); - SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithHmacSHA512AndAES_128"); + SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM); SecretKey tmp = factory.generateSecret(spec); - SecretKeySpec secret = new SecretKeySpec(tmp.getEncoded(), "PBEWithHmacSHA512AndAES_128"); + SecretKeySpec secret = new SecretKeySpec(tmp.getEncoded(), ALGORITHM); byte iv[] = new byte[16]; @@ -57,18 +62,18 @@ private static String encrypt(String data, char[] password, String salt) throws IvParameterSpec randomIvSpec = new IvParameterSpec(iv) ; - PBEParameterSpec pbeSpec = new PBEParameterSpec(salt.getBytes(), 4096, randomIvSpec); - Cipher c = Cipher.getInstance("PBEWITHHMACSHA512ANDAES_128"); + PBEParameterSpec pbeSpec = new PBEParameterSpec(salt.getBytes(), ITERATION_COUNT, randomIvSpec); + Cipher c = Cipher.getInstance(ALGORITHM); c.init(Cipher.ENCRYPT_MODE, secret, pbeSpec); byte[] encrypted = c.doFinal(data.getBytes()); - return utils.returnStringRep(encrypted) + "$" + utils.returnStringRep(iv); + return utils.returnStringRep(encrypted) + IV_SEPARATOR + utils.returnStringRep(iv); } private static String decrypt(String data, char[] password, String salt) throws GeneralSecurityException { PasswordManagementUtils utils = new PasswordManagementUtils(); - String[] dataParts = data.split(Pattern.quote("$")); + String[] dataParts = data.split(Pattern.quote(IV_SEPARATOR)); if (dataParts.length != 2) { throw new GeneralSecurityException("Data does not contain IV?"); } @@ -76,13 +81,13 @@ private static String decrypt(String data, char[] password, String salt) throws byte[] iv = utils.returnByteArray(dataParts[1].trim()); KeySpec spec = new PBEKeySpec(password); - SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithHmacSHA512AndAES_128"); + SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM); SecretKey tmp = factory.generateSecret(spec); - SecretKeySpec secret = new SecretKeySpec(tmp.getEncoded(), "PBEWithHmacSHA512AndAES_128"); + SecretKeySpec secret = new SecretKeySpec(tmp.getEncoded(), ALGORITHM); IvParameterSpec ivSpec = new IvParameterSpec(iv); - PBEParameterSpec pbeSpec = new PBEParameterSpec(salt.getBytes(), 4096, ivSpec); - Cipher c = Cipher.getInstance("PBEWITHHMACSHA512ANDAES_128"); + PBEParameterSpec pbeSpec = new PBEParameterSpec(salt.getBytes(), ITERATION_COUNT, ivSpec); + Cipher c = Cipher.getInstance(ALGORITHM); c.init(Cipher.DECRYPT_MODE, secret, pbeSpec); return new String(c.doFinal(encrypted));