Skip to content

Instantly share code, notes, and snippets.

@juusechec
Created February 15, 2018 02:37
Show Gist options
  • Save juusechec/701ea268dfad1d24c4e7b05f24631851 to your computer and use it in GitHub Desktop.
Save juusechec/701ea268dfad1d24c4e7b05f24631851 to your computer and use it in GitHub Desktop.
Class to encrypt and decrypt values in AES algorithm with rando IV saved in convenient BASE64 format.
package co.edu.udistrital.glud.services;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.Cipher;
import java.util.Base64;
import java.util.Random;
import java.util.Scanner;
/**
* Based on https://gist.github.com/bricef/2436364#file-aes-java
* @author juusechec
* This class encrypt and decrypt paramns
* You can execute making "Run AS" -> "Java Application" over the File
*
* Example:
*
* import co.edu.udistrital.glud.services.EncryptService;
*
* ...
* String secret = "I'm a secret";
* String encryptedSecret = EncryptService.ecryptSecret(secret);
* System.out.println("encryptedSecret: " + encryptedSecret);
* String recoveredSecret = EncryptService.decryptSecret(encryptedSecret);
* System.out.println("recoveredSecret: " + recoveredSecret);
* ...
*/
public class EncryptService {
static int blockSize = 16;
static byte[] IV = new byte[16]; // needed 16 bytes
static String encryptionKey = "0123456789abcdef0123456789abcdef"; // 16, 24, 32 bytes optionally
static String splitter = "$";
public static void main(String[] args) {
// link: https://stackoverflow.com/questions/5287538/how-can-i-get-the-user-input-in-java
Scanner scan = new Scanner(System.in);
System.out.println("You want con encrypt (e) or decrypt(d) (enter to submit): ");
String option = scan.nextLine();
if (option.toLowerCase().startsWith("d")) { // decrypt
System.out.println("Enter a string to decrypt (enter to jump): ");
String encryptedSecret = scan.nextLine();
String recoveredSecret = decryptSecret(encryptedSecret);
System.out.println("recoveredSecret (between quotation marks): '" + recoveredSecret + "'");
scan.close();
return;
}
System.out.println("Enter a string to encrypt (enter to jump): ");
String plaintext = scan.nextLine();
//String s = scan.next(); // only first word (separated with space \s)
//int n = scan.nextInt(); // Scans the next token of the input as an int.
scan.close(); //once finished
if (!plaintext.equals("")) {
System.out.println("\n=== Starting step by step ===\n");
int longitud = plaintext.length();
int veces = (int) Math.ceil((double) longitud / blockSize); // double for precision Beginig
int faltan = (blockSize * veces) - longitud;
String faltante = new String(new char[faltan]);
String newplaintext = plaintext + faltante;
try {
System.out.println("plain: " + newplaintext);
System.out.println("plain length: " + newplaintext.length());
IV = randomIV();
System.out.println("randomIV: " + new String(IV));
byte[] cipher = encrypt(newplaintext, encryptionKey);
System.out.println("encrypt: " + new String(cipher));
byte[] encodedBytes = Base64.getEncoder().encode(cipher);
System.out.println("encodedEncryptBase64Bytes: " + new String(encodedBytes));
byte[] encodedIVBytes = Base64.getEncoder().encode(IV);
System.out.println("encodedIVBase64Bytes: " + new String(encodedIVBytes));
System.out.println("\n=== Recovering ===\n");
byte[] decodedBytes = Base64.getDecoder().decode(encodedBytes);
System.out.println("decodedEncryptBase64Bytes: " + new String(decodedBytes));
byte[] decodedIVBytes = Base64.getDecoder().decode(encodedIVBytes);
System.out.println("decodedIVBase64Bytes: " + new String(decodedIVBytes));
IV = decodedIVBytes;
String decrypted = decrypt(decodedBytes, encryptionKey);
decrypted = decrypted.replace("\0", ""); // replacing null chars with no chars
System.out.println("decrypt: " + decrypted);
System.out.println("decrypt length: " + decrypted.length());
System.out.println("\n=== Final Result ===\n");
String encryptedSecret = ecryptSecret(plaintext);
System.out.println("secureSecret: " + encryptedSecret);
} catch (Exception e) {
e.printStackTrace();
}
return;
}
// example with 16 bytes string
try {
System.out.println("\n=== Example ===\n");
plaintext = "test text 123\0\0\0"; // obligatory 16 length!
System.out.println("plain: " + plaintext);
IV = "AAAAAAAAAAAAAAAA".getBytes("UTF-8"); // example IV
byte[] cipher = encrypt(plaintext, encryptionKey);
System.out.print("cipher: ");
for (int i = 0; i < cipher.length; i++)
System.out.print(new Integer(cipher[i]) + " ");
//System.out.print((char)(cipher[i]));
System.out.println("");
String decrypted = decrypt(cipher, encryptionKey);
System.out.println("decrypt: " + decrypted);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String decryptSecret(String encryptedSecret) {
// text = "$id_algorithm$salt$hashed"
// text = "$1$saltbase64$encryptedbase64text"
// https://www.cyberciti.biz/faq/understanding-etcshadow-file/
try {
String[] parts = encryptedSecret.split("\\" + splitter, 4);
String id = parts[1];
String salt = parts[2];
String hashed = parts[3];
if (id.equals("1")) { // RSA
byte[] decodedIVBytes = Base64.getDecoder().decode(salt);
byte[] decodedEncryptBytes = Base64.getDecoder().decode(hashed);
IV = decodedIVBytes;
String decrypted = decrypt(decodedEncryptBytes, encryptionKey);
decrypted = decrypted.replace("\0", "");
return decrypted;
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public static String ecryptSecret(String plainSecret) {
try {
if (plainSecret.equals("")) {
return "";
}
int lengthSecret = plainSecret.length();
int timesInSizeKey = (int) Math.ceil((double) lengthSecret / blockSize); // double for precision
int remainingNullChars = (blockSize * timesInSizeKey) - lengthSecret;
String remainingString = new String(new char[remainingNullChars]);
plainSecret = plainSecret + remainingString;
IV = randomIV();
byte[] cipher = encrypt(plainSecret, encryptionKey);
byte[] encodedEncryptBytes = Base64.getEncoder().encode(cipher);
byte[] encodedIVBytes = Base64.getEncoder().encode(IV);
// text = "$id_algorithm$salt$hashed"
// text = "$1$saltbase64$encryptedbase64text"
// https://www.cyberciti.biz/faq/understanding-etcshadow-file/
return splitter + "1" + splitter + new String(encodedIVBytes) + splitter + new String(encodedEncryptBytes);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV));
return cipher.doFinal(plainText.getBytes("UTF-8"));
}
public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(IV));
return new String(cipher.doFinal(cipherText), "UTF-8");
}
public static byte[] randomIV() {
byte[] b = new byte[16]; // 16 length
new Random().nextBytes(b);
return b;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment