Skip to main content
Code Review

Return to Question

replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Source Link

This question is related to String Encryption String Encryption which is a previous post made by me regarding this question. I was advised to make another question for another round of reviews so here it goes. I try to follow nearly all of the recommendations given by the community and this is the end result.

This question is related to String Encryption which is a previous post made by me regarding this question. I was advised to make another question for another round of reviews so here it goes. I try to follow nearly all of the recommendations given by the community and this is the end result.

This question is related to String Encryption which is a previous post made by me regarding this question. I was advised to make another question for another round of reviews so here it goes. I try to follow nearly all of the recommendations given by the community and this is the end result.

Rollback to Revision 5
Source Link
user34073
user34073
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
 * <h1>String Encrypter</h1>
 *
 * This programs allows you encrypt a Stringstring and store as a byte array.
 * the program provides a simple encryption set of methods which make use of
 * scrambling/adding/replacing/swapping/ the core structure of the Stringstring.
 * The encrypted message is the store as byte array object which can be sent through sockets
 * or stored locally. In order to be able to view the content of the Stringstring the object
 * must be passed through the decrypt method of this program which will format and reconstruc the
 * Stringstring to it's original state.
 *
 * If the message is infiltrated while stored as an encrypted byte array whether if it is traveling
 * through a socket or store locally on a system. the thief wont be able to see
 * the content of the message without the key used by this class
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
public class StringEncrypter {
 private final static Charset format = Charset.forName("UTF-8");
 private final static char[] added plain = {'L','3','5','G','0','Ä','1','0',
 {'A','D''B','9''C','Å''D','N''E','C''F','0''G','Y''H',
 'W''I','S''J','8''K','Ö''L','4''M','V''N','4''O','1''P',
 'Q','7''R','K''S','6''T','O''U','3''V','6''W','X',
 '8''Y','3''Z','2''Ö','9''Ä','Å','0','5''1','7'};
 /*'2',
 * Meps which hold the encryption base and key data'3','4','5','6','7','8','9',' structures.',
 */
 private static final Map<Character', Character> plain_Map = new HashMap<Character', Character>();
 private static final Map<Character'?', Character> key_Map = new HashMap<Character'.', Character>()'!'};
 private final static finalchar[] Map<String,key String> plain_Byte_Map = new HashMap<String {'D',' String>()','F','G','H','Ä','U','J',
 'A','L','Z','Å','N',',','P','Q',
 'W','S','T','Ö','.','V','R','X',
 'Y','M','!','B','O','4','6','1',
 '8','3','2','9','0','5','7','E',
 'C','?','I','K'};
 private final static finalchar[] Map<Stringadded =
 {'L','3','5','G','0','Ä','1','0',
 String> key_Byte_Map = new HashMap<String 'A','D','9','Å','N','C','0','Y',
 String>() 'W','S','8','Ö','4','V','4','1',
 'Q','7','K','6','O','3','6','X',
 '8','3','2','9','0','5','7'};
 private final static String[] byte_Plain =
 {"1","2","3","4","5","6","7","8","9","0"};
 private final static String[] byte_Key =
 {"8","0","5","4","9","6","1","3","7","2"};
 private final static Map<Character, Character> plain_Map;
 static
 {
 plain_Map = new HashMap<Character, Character>();
 for(int i = 0; i<plain.length; i++){
 plain_Map.put(plain[i],key[i]);
 }
 }
 private final static Map<Character, Character> key_Map;
 static
 {
 key_Map = new HashMap<Character, Character>();
 for(int i = 0; i<plain.length; i++){
 key_Map.put(key[i],plain[i]);
 }
 }
 private static Map<String, String> plain_Byte_Map;
 static
 {
 plain_Byte_Map = new HashMap<String, String>();
 for(int i = 0; i<byte_Plain.length; i++){
 plain_Byte_Map.put(byte_Plain[i],byte_Key[i]);
 }
 }
 private final static Map<String, String> key_Byte_Map;
 static
 {
 key_Byte_Map = new HashMap<String, String>();
 for(int i = 0; i<byte_Plain.length; i++){
 key_Byte_Map.put(byte_Key[i],byte_Plain[i]);
 }
 }
 /**
 * This values determined the swap indexes at which the swapping methods
 * will operate. More swapp indexes may be added for increase security.
 */
 private final static int swap_index_1 = 2;
 private final static int swap_index_2 = 6;
 private final static int swap_index_3 = 4;
 private final static int swap_index_4 = 3;

 /*
 * The higher the number the more random characters will be added to the encryption.
 * The number set here will affect the performace of the application. The higher the
 * number the lower the performance will be but the more populated with random characters
 * he encryption will be.
 * HIgher = more secure but slower.
 * Lower = less secure but faster.
 * recommended: 6
 */
 private final static int max_additions = 5;6;

 /*
 * The index in which the actually code character will be inserted.added too
 * the index must be a number between 0 and the max_additions value-1.
 */
 private final static int insertion_index = 2;
 /**
 * Method used for encrypting a Stringstring. The String passed through
 * this method will be encrypted and returned as byte array.
 * The Stringstring will go through a series of encryption and obsfuscation
 * methodsmethod in order to assure that the contents of the string are kept
 * private static and secure.
 *
 * @param message String message which you wish to encrypt.
 * @return Returns the string given string as an encrypted byte array.
 */
 public static byte[] encrypt(String message){
 return encrypt(message,null,null,null);
 }
 /**
 * Method used for encrypting a string. The String passed through
 * this method will be encrypted and returned as byte array.
 * The string will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the string are kept
 * private and secure.
 * This method allows the input of a custom passwordkey set to be associatedused
 * by this program in replacement of the originals. The key must contain all letters of the
 * swedish dictionary as well as a space character represented as
  * a character with a space in between and the standard comma sign.
 * generated * <h1>Knowing the key. Theused passwordby willthis beprogram neededis fornot decryptionenough ofin Stringsorder
 * whichto weredecode encryptedthe usingcontent of the submittedstrings password.encrypted by this program!</h1>
 * <p>
 * @param message String message which you wish to encrypt.
 * @param passwordnew_Key :The passwordkey to be associatedpassed withas thea encryptionnew replacement key. The passwordkey set must be at least 6 * be 44 characters long and cannot contain duplicates. If the key is
 * not 44 characters long it will simply be ignore and not used. The passwordkey
 * must becontain atthe leaststandard 6comma, charactersperiod, longquestion mark, exclamation mark
 * as well as the space chararcter ' '.
 * @return Returns the Stringstring given Stringstring as an encrypted byte array.
 */
 public static byte[] encrypt(String message,Password passwordchar[]new_Key){
 return encrypt(message,password,null,new_Key,null);
 }
 /**
 * Method used for encrypting a Stringstring. The String passed through
 * this method will be encrypted and returned as byte array.
 * The Stringstring will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the Stringstring are kept
 * private and secure.
 * This method allows the input of a custom character set and a passwordkey set to be used
 * whichby arethis toprogram bein associatedreplacement withof the generated keyoriginals. bothThe thecharacter passwordsets andpassed through
 * thethis submittedconstructor cannot contain any duplicates.
 * <p>
 * <h1>The character set willand the key set must be needed for decryption * of Stringsequal whichlenghts wereand encryptedneither usingthe character set nor the key may have repeating elements.
 * submittedEvery passwordelement andfound in the character set. must be present in the key set and most preferably
 * at a different index<h1>
 * <p>
 * <h1>Knowing either the chararcter set or the key used by this program doest not garantee
 * the ability to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param message String message which you wish to encrypt.
 * @param passwordnew_CharSet :The passwordnew character set to be associatedpassed withas thea encryptionnew chararcter set. The passwordcharacter
 must be at least 6* charactersset longcannot contain duplicates.
 * @param new_CharSetnew_Key :The characterkey setto usedbe bypassed theas encrypteda Stringnew replacement key. The characterkey set must contain
 * set cannotall containthe anycharacters duplicatespresent andin mustthe becharacter atset leastand 40cannot characterscontain long.duplicates
 * @return Returns the Stringstring given Stringstring as an encrypted byte array.
 */
 public static byte[] encrypt(String message, Password password, char[] new_CharSet, char[]new_Key){
 return encrypt(message,password,new_CharSet,new_Key,null);
 }
 /**
 * Method used for encrypting a Stringstring. The String passed through
 * this method will be encrypted and returned as byte array.
 * The Stringstring will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the Stringstring are kept
 * private and secure.
 * This method allows the input of a custom character set, akey passwordset and theByte securitykey levelto be used
 * whichby isthis toprogram bein associatedreplacement withof the generated keyoriginals. The password,character thesets securitypassed levelthrough
 and * this constructor cannot contain any duplicates.
 * the<p>
 submitted * <h1>The character set willand the key set must be needed for decryption * of Stringsequal whichlenghts wereand encryptedneither usingthe character set nor the key may have repeating elements.
 * submittedEvery password,element found in the character set must be present in the key set and securitymost level.preferably
 * at a different index<h1>
 * <p>
 * <h1>Knowing either the chararcter set or the key used by this program doest not garantee
 * the ability to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * The byte key must contain 10 unique digits with numbers
 * from 0 to 9 in any desired order.
 *
 * <h1>Knowing the byte key used by this program is not enough in order
 * to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param message String message which you wish to encrypt.
 * @param passwordnew_CharSet :The password to be associated with the encryption. The password must be at least 6 characters long.
new character set to be *passed @paramas new_CharSeta :Thenew characterchararcter set used by the encrypted String. The character
 * set cannot contain any duplicates and must be at least 40 characters long.
 * @param securitynew_Key :The level of security which iskey to be assignpassed toas thea encryptednew messagereplacement key. The higherkey theset securitymust levelcontain
 * all the highercharacters present in the levelcharacter ofset encryptionand butcannot alsocontain theduplicates
 slower the encryption process will* be.@param new_byte_Key :The lowerkey theto securitybe levelpassed as a new replacement key.
 * theThe lowerkey theset encryptionmus butbe the10 fastercharacters thelong encryptionand willcannot becontain duplicates.
 * @return Returns the Stringstring given Stringstring as an encrypted byte array.
 */
 public static byte[] encrypt(String message, Password password, char[] new_CharSet, SecurityLevelchar[]new_Key, securityString[] new_byte_Key){
 if(prepareEncryptionsetCharset_setKey_setByteKey(new_CharSet, passwordnew_Key, security)new_byte_Key){;
 String cypher = addRandom(message).toString();
 byte[] encryption = cypher.getBytes(format);
 byte[] swapped_Bytes = revertBytes(EncryptionUtils.toByteObject(encryption));
 return swapBytes(swapped_Bytes);

 }else{
 return null;
 }
 }
 /**
 * Method used for decrypting a string in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content
 *
 * @param encryption :byte array containing the encrypted string.
 * @return :Returns a decypted string.
 */
 public static String decrypt(byte[] encryption){
 return decrypt(encryption,null,null,null);
 }
 /**
 * Method used for decrypting a string in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 * This method allows the input of a custom key set to be used
 * by this program in replacement of the passwordoriginals. associatedThe key must contain all letters of the
 * swedish dictionary as well as a space character represented as
  * a character with a space in between and the standard comma sign.
 *
 * <h1>Knowing the encryptedkey fileused whichby this program is needednot enough in order to be able * to viewdecode the file.content of the strings encrypted by this program!</h1>
 * <p>
 * @param encryption :byte array containing the encrypted Stringstring.
 * @param passwordnew_Key :The password associatedkey to thebe filepassed as a new replacement key. NeededThe inkey orderset must
 * tobe view44 characters long and cannot contain duplicates. If the file!key is
 * not 44 characters long it will simply be ignore and not used. The passwordkey
  * must matchcontain the passwordstandard usedcomma, toperiod, encryptquestion mark, exclamation mark
 * as well as the filespace chararcter ' '.
 * @return :Returns a decypted Stringstring.
 */
 public static String decrypt(byte[] encryption, Passwordchar[] passwordnew_Key){
 return decrypt(encryption,password,null,new_Key,null);
 }
 /**
 * Method used for decrypting a Stringstring in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 *
 * This method allows the input of thea custom character set and thea password
key set to be used
 * associated with the encrypted* file.by Boththis theprogram characterin setreplacement andof the password
originals. The character sets passed *through
 are needed in order to* viewthis theconstructor originalcannot Stringcontain contentany duplicates.
 * <p>
 * @param encryption<h1>The :bytecharacter arrayset containingand the encryptedkey String.set must be
 * @paramof passwordequal :Thelenghts passwordand associatedneither tothe character set nor the filekey may have repeating elements. Needed * Every element found in orderthe character set must be present in the key set and most preferably
 * toat viewa thedifferent file!index<h1>
 The password must match * <p>
  * <h1>Knowing either the passwordchararcter set or the key used by this program doest not garantee
 * the ability to encryptdecode the filecontent of the strings encrypted by this program!</h1>
 * <p>
 * @param encryption :byte array containing the encrypted string.
 * @param new_CharSet :The new character set associatedto withbe thepassed encryptedas filea new chararcter set. The character
 * neededset incannot ordercontain duplicates.
 * @param new_Key :The key to viewbe passed as a new replacement key. The key set must contain
 * all the file!characters Mustpresent matchin the character set used toand encryptcannot thecontain Stringduplicates
 * @return Returns a decypted Stringstring.
 */
 public static String decrypt(byte[] encryption, Password password, char[] new_CharSet, char[]new_Key){
 return decrypt(encryption,password,new_CharSet,new_Key,null);
 }
 /**
 * Method used for decrypting a Stringstring in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 *
 * This method allows the input of thea custom character set, thekey passwordset and theByte securitykey levelto be used
 * associated withby thethis encryptedprogram file.in Allreplacement of the inputs are needed inoriginals. orderThe tocharacter viewsets thepassed originalthrough
 * contentthis ofconstructor thecannot filecontain any duplicates.
 * <p>
 * @param encryption<h1>The :bytecharacter arrayset containingand the encryptedkey String.set must be
 * @paramof passwordequal :Thelenghts passwordand associatedneither tothe character set nor the filekey may have repeating elements. Needed * Every element found in orderthe character set must be present in the key set and most preferably
 * at a different index<h1>
 * <p>
 * <h1>Knowing either the chararcter set or the key used by this program doest not garantee
 * the ability to viewdecode the filecontent of the strings encrypted by this program!</h1>
 * <p>
  * The passwordbyte key must matchcontain 10 unique digits with numbers
 * from 0 to 9 in any desired order.
 *
  * <h1>Knowing the passwordbyte key used by this program is not enough in order
  * to encryptdecode the Stringcontent of the strings encrypted by this program!</h1>
 * <p>
 * @param encryption :byte array containing the encrypted string.
 * @param new_CharSet :The new character set associatedto withbe thepassed encryptedas file.Musta matchnew thechararcter set. The character
 * set used to encryptcannot thecontain Stringduplicates.
 * @param securitynew_Key :The securitykey levelto whichbe ispassed associatedas witha thenew encryptedreplacement Stringkey.Muse matchThe key set must contain
 * all the securitycharacters levelpresent usedin the character set and cannot contain duplicates
  * @param new_byte_Key :The key to encryptbe thepassed Stringas a new replacement key.
 * The key set mus be 10 characters long and cannot contain duplicates.
 * @return Returns a decypted Stringstring.
 */
 public static String decrypt(byte[] encryption, Password password, char[] new_CharSet, SecurityLevelchar[]new_Key, securityString[] new_byte_Key){
 if(prepareEncryptionsetCharset_setKey_setByteKey(new_CharSet, passwordnew_Key, security)new_byte_Key){;
 byte[] unswapped_Bytes = revertBytesBack(EncryptionUtils.toByteObject(unSwapBytes(encryption)));
 List<String> list = EncryptionUtils.fromStringToList(new String(unswapped_Bytes, format),", ");
 EncryptedMessage unScrambled = removeRandom(list);
 String decyphered = revertSubstitution(unScrambled);
 return decyphered;
 }
 else{
 return "";
 }
 }
 /*
 * Method incharged of processing the encryption and decryption request made
 * by the user. This method will perform checks on the validity of the password and the character
 * set if any. If both the password and the character set are valid the method will then generate a key
 * and allow the encryption to proceed further.
 */
 private static boolean prepareEncryption(char[] new_CharSet, Password password, SecurityLevel security){
 boolean duplicates = false;
 String[] byte_Plain =
 {"1","2","3","4","5","6","7","8","9","0"};
 char[] plain_char_set =
 {'A','B','C','D','E','F','G','H',
 'I','J','K','L','M','N','O','P',
 'Q','R','S','T','U','V','W','X',
 'Y','Z','Ö','Ä','Å','0','1','2',
 '3','4','5','6','7','8','9',' ',
 ',','?','.','!'};

 private static ifvoid (password.isPasswordOksetCharset_setKey_setByteKey() &&char[] new_CharSet != null) {
 , duplicateschar[]new_Key, =String[] EncryptionUtils.containsDuplicates(new_CharSetnew_byte_Key) ;{
 if(new_Key!duplicates=null && new_CharSet.length>=40) {
 KeyGenerator keyGen =!=null new&& KeyGenerator(passwordnew_Key.getPassword(),new_CharSet, byte_Plain);
 length == setSecurityLevel(passwordnew_CharSet.getPassword(), securitylength);{
 key_Map.clear();
 plain_Map.clear();
 key_Byte_Map.clear();
 plain_Byte_Map.clear();
 for(int i = 0; i < new_CharSeti<new_CharSet.length; i++){
 plain_Map.put(keyGen.getBase_key()[i], keyGen.getNew_Key()[i]);
 key_Map.put(keyGen.getNew_Key()[i], keyGen.getBase_key()[i]);
 }
 for (int i = 0; i < byte_Plain.length; i++) {
 plain_Byte_Map.put(keyGen.getBase_Byte()[i]new_Key[i], keyGen.getNew_Byte()[i]new_CharSet[i]);
 key_Byte_Mapplain_Map.put(keyGen.getNew_Byte()[i]new_CharSet[i], keyGen.getBase_Byte()[i]);
 }
 return true;
 }
 else if(duplicates && new_CharSet.length>=40){
 new InvalidCharacterSetException("The submitted character set contains duplicates!");
 return false;
 }
  else if(!duplicates && new_CharSet.length<40){
 new InvalidCharacterSetException("The submitted character set does not meet the character amount specification!");
 return false;
 }
 else{
 new InvalidCharacterSetException("The submitted character set contains less than then minimum allow amount of characters!"new_Key[i]);
 return false;
 }
 }
 else if (password.isPasswordOk()new_Key!=null && new_CharSet == null) {
  KeyGenerator keyGen =new_CharSet==null new&& KeyGenerator(passwordnew_Key.getPassword(),plain_char_set, byte_Plain);
 setSecurityLevel(passwordlength==plain.getPassword(), securitylength);{
 key_Map.clear();
 plain_Map.clear();
 key_Byte_Map.clear();
 plain_Byte_Map.clear();
 for(int i = 0; i < plain_char_seti<key.length; i++){
 plain_Map.put(keyGen.getBase_key()[i], keyGen.getNew_Key()[i]);
  key_Map.put(keyGen.getNew_Key()[i]new_Key[i], keyGen.getBase_key()[i]plain[i]);
 }
 }
 for (int i = 0; iif(new_byte_Key!=null <&& byte_Plainnew_byte_Key.length; i++length==byte_Plain.length){
 key_Byte_Map.clear();
 plain_Byte_Map.put(keyGen.getBase_Byte for()[i],int keyGeni = 0; i<byte_Plain.getNew_Byte()[i]length; i++);{
 key_Byte_Map.put(keyGen.getNew_Byte()[i]new_byte_Key[i], keyGen.getBase_Byte()[i]byte_Plain[i]);
 }
 return true;
 } else {
 new InvalidPasswordException("The submitted password is not valid");
 return false;
 }
 }
 /*
 * Method used to swapp the elements of the input array.
 * The elements will be swapped using 4 nested loops with
 * different swap indexes. The elements are swapped around
 * millions of times
 */
 private static char[] swapCharacters(char[] chars){
 for(int i1 = 0; i1<chars.length-swap_index_1; i1++){
 char temp = chars[i1];
 chars[i1] = chars[i1+swap_index_1];
 chars[i1+swap_index_1] = temp;
 for(int i2 = 0; i2<chars.length-swap_index_2; i2++){
 char temp2 = chars[i2];
 chars[i2] = chars[i2+swap_index_2];
 chars[i2+swap_index_2] = temp2;
 for(int i3 = 0; i3<chars.length-swap_index_3; i3++){
 char temp3 = chars[i3];
 chars[i3] = chars[i3+swap_index_3];
 chars[i3+swap_index_3] = temp3;
 for(int i4 = swap_index_4; i4<chars.length; i4++){
 char temp4 = chars[i4];
 chars[i4] = chars[i4-swap_index_4];
 chars[i4-swap_index_4] = temp4;
 }
 }
 }
 }
 return chars;
 }
 /*
 * Method used to swapp the elements which were previously swapped
 * by the swapCharacters method back to their original index. The swap
 */
 private static char[] revertCharacterSwap(char[] chars) {
 for (int i1 = chars.length - (swap_index_1+1); i1 >= 0; i1--) {
 for (int i2 = chars.length - (swap_index_2+1); i2 >= 0; i2--) {
 for (int i3 = chars.length - (swap_index_3+1); i3 >= 0; i3--) {
 for (int i4 = chars.length - 1; i4 >= (swap_index_4); i4--) {
 char temp4 = chars[i4];
 chars[i4] = chars[i4 - swap_index_4];
 chars[i4 - swap_index_4] = temp4;
 }
 char temp3 = chars[i3];
 chars[i3] = chars[i3 + swap_index_3];
 chars[i3 + swap_index_3] = temp3;
 }
 char temp2 = chars[i2];
 chars[i2] = chars[i2 + swap_index_2];
 chars[i2 + swap_index_2] = temp2;
 }
 char temp = chars[i1];
 chars[i1] = chars[i1 + swap_index_1];
 chars[i1 + swap_index_1] = temp;
 }
 return chars;
 }
 /*
 * Method which swaps the elements match to the character set
 * whith the correspondnt key element. The method will also create
 * an array holing information about the case of each character. The method
 * will also perform a character swap with a call to the swapCharacters method. After
 * the process is completed this method will return a set of characters holding the
 * coded message along with a set of characters holding case information. The
 * two are divided by a special sequence of symbols in order to distinguish the
 * the two. The return message will then be passed further for further encryption.
 */
 private final static EncryptedMessage applySubstitution(char[] message) {
 char[] case_Binary = new char[message.length];
 char[] code_Message = new char[message.length];
 for(int i = 0; i < message.length; i++) {
 if (Character.isUpperCase(message[i])) {
 case_Binary[i] = '1';
 }
 if (Character.isLowerCase(message[i])) {
 case_Binary[i] = '0';
 }
 code_Message[i] = Character.toUpperCase(message[i]);
 if(plain_Map.containsKey(code_Message[i])){
 code_Message[i] = plain_Map.get(code_Message[i]);
 }
 }
 return new EncryptedMessage(swapCharacters(code_Message),case_Binary);
 }
 /*
 * Method which reverts the character substitution performed by the
 * applySubstitution. It does this by reverting the pattern in which the substitution
 * was made. This will separate and analyze the message along with the case data
 * and once this is done it will also peform a call to the revertCharacterSwap method
 * in order to also unswap the order of the characters to their original state.
 * Once the substitution and the character swap has been reversed it wil further
 * analyze case data determine the case of each character. Upon completion it
 * will return the decrypted message.
 */
 private final static String revertSubstitution(EncryptedMessage message) {
 char[] code_Message = revertCharacterSwap(message.getCharMessage());
 char[] case_Message = message.getCharCase();
 for (int i = 0; i < code_Message.length; i++) {
 if(key_Map.containsKey(code_Message[i])){
 code_Message[i] = key_Map.get(code_Message[i]);
 }
 if (case_Message[i] == '1') {
 code_Message[i] = Character.toUpperCase(code_Message[i]);
 }
 if (case_Message[i] == '0') {
 code_Message[i] = Character.toLowerCase(code_Message[i]);
 }
 }
 return String.valueOf(code_Message);
 }
 /*
 * Method used to further increases the obsfuscation level of the message by adding
 * random numbers and characters to the body of the already encrypted message. This
 * is done at key places of the message in order to allow the substraction of the oginal
 * version of the encryption witout having to deal with the extrac characters and numbers
 * added by this function. The function a
 * the process can then be reversed with an additional key.
 */
 private final static LinkedList<String> addRandom(String code) {
 LinkedList<String> cypherList = new LinkedList<>();
 EncryptedMessage case_and_code = applySubstitution(code.toCharArray());
 String code_message = case_and_code.getMessage();
 String code_case = case_and_code.getCase();
 for (int index = 0; index < code_message.length(); index++) {
 cypherList.add(EncryptionUtils.getRandomString(max_additions,code_message.charAt(index),insertion_index));
 }

 }
 
 cypherList.addFirst("" + (EncryptionUtils.getRandomInterval(100,999)));
 cypherList.addLastadd(String.valueOf(code_case) + EncryptionUtils.getRandomInterval(100,999)+EncryptionUtils.getRandomStringgetRandom(210));
 return cypherList;
 }
 /*
 * Method used to remove all previously added obsfuscation elements. The method
 * will loop through the values of a given list and it will filter the orignal's
 * message values into their respective char arrays, one holding the code and the
 * othe holding the case related data.
 */
 private final static EncryptedMessage removeRandom(List<String> cypher_List) {
 StringBuilder string_Builder = new StringBuilder();
 char[] case_message = new char[cypher_List.get(cypher_List.size()-1).length()-5]; 2];
 char[] code_message = new char[cypher_List.size()-1];
 for (int index = 0; index < cypher_List.size() - 1; index++) {
 if (index >= 1){
 try{
 string_Builder.append(String.valueOf(cypher_List.get(index).toCharArray()[insertion_index]));
 }catch(ArrayIndexOutOfBoundsException e){ /*TODO NOTHING*/}
 }
 if (index < case_message.length){
 case_message[index] = cypher_List.get(cypher_List.size() - 1).toCharArray()[index];
 }
 }

 code_message = string_Builder.toString().toCharArray();
 return new EncryptedMessage(code_message, case_message);
 }
 /*
 * Method used to further encrypt the message by replacing the
 * first first digit of every value on every index of the byte array
 * except for indexes that hold a negative value. This method converts
 * the byte value to Stringstring which is than formated and casted back to
 * a byte. A modification can be perform that may allow each index to
 * be replace using a numerical value check!
 */
 private final static Byte[] replaceBytes(Byte[] bytes) {
 Byte[] temp_Bytes = Arrays.copyOf(bytes, bytes.length);
 for (int i = 0; i < temp_Bytes.length; i++) {
 if (Integer.toString(temp_Bytes[i]).charAt(0) != '-') {
 String temp_String = String.valueOf(temp_Bytes[i]);
 String new_Value = plain_Byte_Map.get(Integer.toString(temp_Bytes[i]).substring(0, 1))+ temp_String.substring(1);
 temp_Bytes[i] = Byte.valueOf(new_Value);
 }
 }
 return temp_Bytes;
 }
 /*
 * Method used to revert the previously replaced bytes back to
 * to normal. The byte array will go throug an identical procedure
 * as the one performed in the replace bytes method in order to
 * give each byte index the original value of the first index.
 */
 private final static Byte[] revertByteReplacement(Byte[] bytes) {
 Byte[] temp_Bytes = Arrays.copyOf(bytes, bytes.length);
 for (int i = 0; i < temp_Bytes.length; i++) {
 if (Integer.toString(temp_Bytes[i]).charAt(0) != '-') {
 String temp_String = String.valueOf(temp_Bytes[i]);
 String new_Value = key_Byte_Map.get(Integer.toString(temp_Bytes[i]).substring(0, 1))+ temp_String.substring(1);
 temp_Bytes[i] = Byte.valueOf(new_Value);
 }
 }
 return temp_Bytes;
 }
 /*
 * Method used to swapp the elements of the input array.
 * The elements will be swapped using 3 nested loops with
 * different swap indexes. The elements are swapped around
 * millions of times.
 */
 private final static byte[] swapBytes(byte[] bytes){
 for(int i1 = 0; i1<bytes.length-swap_index_1; i1++){
 byte temp = bytes[i1];
 bytes[i1] = bytes[i1+swap_index_1];
 bytes[i1+swap_index_1] = temp;
 for(int i2 = 0; i2<bytes.length-swap_index_2; i2++){
 byte temp2 = bytes[i2];
 bytes[i2] = bytes[i2+swap_index_2];
 bytes[i2+swap_index_2] = temp2;
 for(int i3 = swap_index_4; i3<bytes.length; i3++){
 byte temp3 = bytes[i3];
 bytes[i3] = bytes[i3-swap_index_4];
 bytes[i3-swap_index_4] = temp3;
 }
 }
 }
 return bytes;
 }
 /*
 * Method used to swapp the elements which were previously swapped
 * by the swapBytes method back to their original index. The swap
 */
 private final static byte[] unSwapBytes(byte[] bytes){
 for (int i1 = bytes.length - (swap_index_1+1); i1 >= 0; i1--) {
 for (int i2 = bytes.length - (swap_index_2+1); i2 >= 0; i2--) {
 for (int i3 = bytes.length - 1; i3 >= (swap_index_4); i3--) {
 byte temp3 = bytes[i3];
 bytes[i3] = bytes[i3 - swap_index_4];
 bytes[i3 - swap_index_4] = temp3;
 }
 byte temp2 = bytes[i2];
 bytes[i2] = bytes[i2 + swap_index_2];
 bytes[i2 + swap_index_2] = temp2;
 }
 byte temp = bytes[i1];
 bytes[i1] = bytes[i1 + swap_index_1];
 bytes[i1 + swap_index_1] = temp;
 }
 return bytes;
 }
 /**
 * Reverses the byte array for further increase obfuscation.
 */
 private final static byte[] revertBytes(Byte[] encryption){
 Byte[] byte_Array = encryption;
 List<Byte> byte_List = Arrays.asList(byte_Array);
 Collections.reverse(byte_List);
 return EncryptionUtils.toPrimitives(replaceBytes(byte_Array));
 }
 /**
 * Reverses the byte array to its original state
 */
 private final static byte[] revertBytesBack(Byte[] encryption){
 Byte[] byte_Array = encryption;
 List<Byte> byte_List = Arrays.asList(byte_Array);
 Collections.reverse(byte_List);
 return EncryptionUtils.toPrimitives(revertByteReplacement(byte_Array));
 }
 /*
 * Method which checks the security level required by the user
 * and base on the specifications it will adjust the amount of characters per character
 * which are to be added to the encrypted message. The higher the security level the
 * higher the number of added characters and vice versa.
 */
 private final static void setSecurityLevel(String password, SecurityLevel security){
 if(security!=null){
// SecureRandom rand = new SecureRandom();
// rand.setSeed(password.getBytes(format));
 switch(security){
 case LOW:
 max_additions = 1;
 insertion_index = 0;
 break;
 case MEDIUM:
 max_additions = 4;
 insertion_index = 3;
 break;
 case HIGH:
 max_additions = 6;
 insertion_index = 2;
 break;
 case VERY_HIGH:
 max_additions = 10;
 insertion_index = 7;
 break;
 default:
 break;
 }
 }
 }
 /**
 * <h1>Encrypted Message</h1>
 *
 * This class is used as a wrapper containing both
 * the code of the actual Stringstring and case data of
 * said Stringstring.
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
 private static class EncryptedMessage{
 private final String code_message;
 private final String case_message;
 public EncryptedMessage(char[] codeX, char[] caseX){
 this.code_message = String.valueOf(codeX);
 this.case_message = String.valueOf(caseX);
 }
 public final String getMessage(){
 return code_message;
 }
 public final String getCase(){
 return case_message;
 }
 public final char[] getCharMessage(){
 return code_message.toCharArray();
 }
 public final char[] getCharCase(){
 return case_message.toCharArray();
 }
 }
 /**
 * <h1>Encryption Utility</h1>
 *
 * This class contains various functions used by the program.
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
 publicprivate static class EncryptionUtils{
 /*
 * Method which converts an Object byte array to a primitive type.
 */
 private static byte[] toPrimitives(Byte[] byte_Object){
 byte[] bytes = new byte[byte_Object.length];
 int i = 0;
 for(Byte byte_Objects : byte_Object)bytes[i++] = byte_Objects;
 return bytes;
 }
 /*
 * Method which converts a primitive byte array to an object byte array.
 */
 private static Byte[] toByteObject(byte[] byte_prime) {
 Byte[] bytes = new Byte[byte_prime.length];
 int i = 0;
 for (byte byte_Primes : byte_prime) bytes[i++] = byte_Primes;
 return bytes;
 }
 /*
 * Method which converts an Object byte array to a primitive type.
 */
 @SuppressWarnings("unused")
 private static char[] toCharPrimitive(Character[] char_Object){
 char[] chars = new char[char_Object.length];
 int i = 0;
 for(Character char_Objects : char_Object)chars[i++] = char_Objects;
 return chars;
 }
 /*
 * Method which converts a primitive byte array to an object byte array.
 */
 @SuppressWarnings("unused")
 private static Character[] toCharObject(char[] char_prime) {
 Character[] chars = new Character[char_prime.length];
 int i = 0;
 for (char chars_Primes : char_prime) chars[i++] = chars_Primes;
 return chars;
 }
 /*
 * Method which prints the content of a byte array.
 */
 publicprivate static String printBytes(byte[] binaryEncription){
  if(binaryEncription!=null){
 return new String(binaryEncription, format);
 }
 else
 return "";
 }
 /*
 * Method which splits a Stringstring at a given character sequence
 * and returns List made out of all the sections.
 */
 private static List<String> fromStringToList(String list, String sequence) {
 return Arrays.asList(list.split(sequence));
 }
 /*
 * Method which generates a secure random within a
 * given range.
 */
 private static int getRandom(int value){
 SecureRandom rand = new SecureRandom();
 return rand.nextInt(value);
 }
 /*
 * Method which generates a secure random within a
 * given interval.
 */
 private static int getRandomInterval(int minValue, int maxValue) {
 SecureRandom rand = new SecureRandom();
 return rand.nextInt(maxValue + 1 - minValue) + minValue;
 }
 /*
 * Method which returns a random Stringstring of the specified
 * lenght containing a non random element located at the given index.
 */
 private static String getRandomString(int length, char code, int index){
 char[] randomString = new char[length];
 for(int i = 0;i<length; i++){
 randomString[i] =added[getRandom(added.length)];
 if(i==index){
 randomString[i] = code;
 }
 }
 return String.valueOf(randomString);
 }
 /*
 * Method which returns a radom Stringstring of the specified
 * lenght.
 */
 @SuppressWarnings("unused")
 private static String getRandomString(int length){
 char[] randomString = new char[length];
 for(int i = 0;i<length; i++){
 randomString[i] =added[getRandom(added.length)];
 }
 return String.valueOf(randomString);
 }

 /*
 * Method which checks if a char array contains any duplicate values
 */
 public static boolean containsDuplicates(final char[] chars) {
 final int max_size = 99999;
 BitSet bitset = new BitSet(max_size + 1);
 bitset.set(0, max_size, false);
 for (int item : chars) {
 if (!bitset.get(item)) {
 bitset.set(item, true);
 } else
 return true;
 }
 return false;
 }
 }
 /**
 * Class which is in charge of generating new unique keys based on the
 * the given password and character set if any. Each
 * @author Eudy Contreras
 *
 */
 private static class KeyGenerator {
 private char[] char_key_set;
 private char[] char_base_set;
 private String[] byte_key_set;
 private String[] byte_base_set;
 private SecureRandom charRandom = new SecureRandom();
 private SecureRandom byteRandom = new SecureRandom();
 public KeyGenerator(String password, char[] charSet, String[] byteSet) {
 this.generateKey(password,charRandom,charSet);
 this.generateKey(password,byteRandom,byteSet);
 this.shuffle(char_key_set,charRandom,ShuffelMethod.RICHARD_DURSTENFELD_SHUFFLE);
 this.shuffle(byte_key_set,byteRandom);
 }
 /*
 * Creates a new key based on a given password. The password given will
 * always reproduce the same key if combined with the same set of
 * characters.
 */
 private void generateKey(String password,SecureRandom charRandom, char[] baseChars) {
 charRandom.setSeed(password.getBytes(format));
 char_base_set = new char[baseChars.length];
 char_base_set = Arrays.copyOf(baseChars, baseChars.length);
 char_key_set = new char[char_base_set.length];
 char_key_set = Arrays.copyOf(char_base_set, baseChars.length);
 }
 private void generateKey(String password, SecureRandom byteRandom, String[] baseBytes) {
 byteRandom.setSeed(password.getBytes(format));
 byte_base_set = new String[baseBytes.length];
 byte_base_set = Arrays.copyOf(baseBytes, baseBytes.length);
 byte_key_set = new String[byte_base_set.length];
 byte_key_set = Arrays.copyOf(byte_base_set, baseBytes.length);
 }
 /*
 * Method which securely shuffles an array using different conventional
 * methods
 */
 private void shuffle(char[] char_key,SecureRandom charRandom, ShuffelMethod method) {
 switch (method) {
 case FISHER_YATES_SHUFFLE:
 int index;
 for (int i = char_key.length - 1; i > 0; i--) {
 index = charRandom.nextInt(i + 1);
 if (index != i) {
 char_key[index] ^= char_key[i];
 char_key[i] ^= char_key[index];
 char_key[index] ^= char_key[i];
 }
 }
 break;
 case RICHARD_DURSTENFELD_SHUFFLE:
 for (int i = char_key.length - 1; i > 0; i--) {
 index = charRandom.nextInt(i + 1);
 char temp = char_key[index];
 char_key[index] = char_key[i];
 char_key[i] = temp;
 }
 break;
 default:
 break;
 }
 }
 /*
 * Method which securely shuffles an array using different conventional
 * methods
 */
 private void shuffle(String[] byte_key, SecureRandom byteRandom) {
 int index;
 for (int i = byte_key.length - 1; i > 0; i--) {
 index = byteRandom.nextInt(i + 1);
 String temp = byte_key[index];
 byte_key[index] = byte_key[i];
 byte_key[i] = temp;
 }
 }
 public enum ShuffelMethod {
 FISHER_YATES_SHUFFLE, RICHARD_DURSTENFELD_SHUFFLE,
 }
 public char[] getBase_key() {
 return char_base_set;
 }
 public String[] getBase_Byte() {
 return byte_base_set;
 }
 public char[] getNew_Key() {
 return char_key_set;
 }
 public String[] getNew_Byte() {
 return byte_key_set;
 }
 }
 /**
 * Password class used by the String Encryption Utility
 * the pass word must contain at least 6 character.
 * @author Eudy Contreras
 *
 */
 public static class Password{
 private String password;
 public Password(String password){
 this.password = password;
 }
 private String getPassword(){
 return password;
 }
 private boolean isPasswordOk(){
 return password.length()>=6 && password!=null;
 }
 }
 public enum SecurityLevel{
 LOW,MEDIUM,HIGH,VERY_HIGH
 }
 private static class InvalidPasswordException extends Exception {
 private static final long serialVersionUID = 1L;
 public InvalidPasswordException(String message) {
 super(message);
 System.err.println(this.getMessage());
 System.err.println("Please look at the documentation for more information");
 }
 }
 private static class InvalidCharacterSetException extends Exception {
 private static final long serialVersionUID = 1L;
 public InvalidCharacterSetException(String message) {
 super(message);
 System.err.println(this.getMessage());
 System.err.println("Please look at the documentation for more information");
 }
 }
 public static void main(String[] args) {
 char[] new_char_set =
 {'D',' ','F','G','H','Ä','U','J',
 'A','L','Z','Å','N',',','P','Q',
 // 'W','S','T','Ö','EncryptionUtils.','V','R','X',
 'Y','M','!','B','O','4','6','1',
 '8','3','2','9','0','5','7','E',
 'C','?','I','K','$','/'getRandomString(10,'@''Ö','*'}1);
 long encrypt_start_time = System.currentTimeMillis();
 byte[] encryption = StringEncrypter.encrypt("Your message"What is now secureup!!", newNot Password("password"),new_char_set,much SecurityLevel.MEDIUMwhy??");
 long encrypt_end_time = System.currentTimeMillis();
 System.out.println("Encryption speed: "+(encrypt_end_time - encrypt_start_time)+ " Milliseconds");

 System.out.println("Actual encrypted message:");
 System.out.println("////////////////////////////////////////////////////////////////////////////////");
 System.out.println("");
 System.out.println(EncryptionUtils.printBytes(encryption));
 System.out.println("");
 System.out.println("////////////////////////////////////////////////////////////////////////////////");

// System.out.println(Arrays.toString(encryption));
 long decrypt_start_time = System.currentTimeMillis();
 System.out.println(StringEncrypter.decrypt(encryption,new Password("password"),new_char_set,SecurityLevel.MEDIUM));
 long decrypt_end_time = System.currentTimeMillis();
 System.out.println("Decryption speed: "+(decrypt_end_time - decrypt_start_time)+ " Milliseconds");
 }
}

I know the code is long but I tried to documented well and structure it to make easy to read. I sincerely appreciate all your time and I hope my question is well formulated and on topic.

import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
 * <h1>String Encrypter</h1>
 *
 * This programs allows you encrypt a String and store as a byte array.
 * the program provides a simple encryption set of methods which make use of
 * scrambling/adding/replacing/swapping/ the core structure of the String.
 * The encrypted message is the store as byte array object which can be sent through sockets
 * or stored locally. In order to be able to view the content of the String the object
 * must be passed through the decrypt method of this program which will format and reconstruc the
 * String to it's original state.
 *
 * If the message is infiltrated while stored as an encrypted byte array whether if it is traveling
 * through a socket or store locally on a system. the thief wont be able to see
 * the content of the message without the key used by this class
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
public class StringEncrypter {
 private final static Charset format = Charset.forName("UTF-8");
 private static char[] added  = {'L','3','5','G','0','Ä','1','0',
 'A','D','9','Å','N','C','0','Y',
 'W','S','8','Ö','4','V','4','1',
 'Q','7','K','6','O','3','6','X',
 '8','3','2','9','0','5','7'};
 /*
 * Meps which hold the encryption base and key data structures.
 */
 private static final Map<Character, Character> plain_Map = new HashMap<Character, Character>();
 private static final Map<Character, Character> key_Map = new HashMap<Character, Character>();
 private static final Map<String, String> plain_Byte_Map = new HashMap<String, String>();
 private static final Map<String, String> key_Byte_Map = new HashMap<String, String>();
 /**
 * This values determined the swap indexes at which the swapping methods
 * will operate. More swapp indexes may be added for increase security.
 */
 private final static int swap_index_1 = 2;
 private final static int swap_index_2 = 6;
 private final static int swap_index_3 = 4;
 private final static int swap_index_4 = 3;
 /*
 * The higher the number the more random characters will be added to the encryption.
 * The number set here will affect the performace of the application. The higher the
 * number the lower the performance will be but the more populated with random characters
 * he encryption will be.
 * HIgher = more secure but slower.
 * Lower = less secure but faster.
 * recommended: 6
 */
 private static int max_additions = 5;
 /*
 * The index in which the actually code character will be inserted.
 * the index must be a number between 0 and the max_additions value-1.
 */
 private static int insertion_index = 2;
 /**
 * Method used for encrypting a String. The String passed through
 * this method will be encrypted and returned as byte array.
 * The String will go through a series of encryption and obsfuscation
 * methods in order to assure that the contents of the String are kept
 * private and secure.
 * This method allows the input of a custom password to be associated with the
 * generated key. The password will be needed for decryption of Strings
 * which were encrypted using the submitted password.
 * <p>
 * @param message String message which you wish to encrypt.
 * @param password :The password to be associated with the encryption. The password must be at least 6 characters long.
 * The password must be at least 6 characters long.
 * @return Returns the String given String as an encrypted byte array.
 */
 public static byte[] encrypt(String message,Password password){
 return encrypt(message,password,null,null);
 }
 /**
 * Method used for encrypting a String. The String passed through
 * this method will be encrypted and returned as byte array.
 * The String will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the String are kept
 * private and secure.
 * This method allows the input of a custom character set and a password
 * which are to be associated with the generated key. both the password and
 * the submitted character set will be needed for decryption of Strings which were encrypted using the
 * submitted password and character set.
 * <p>
 * @param message String message which you wish to encrypt.
 * @param password :The password to be associated with the encryption. The password must be at least 6 characters long.
 * @param new_CharSet :The character set used by the encrypted String. The character
 * set cannot contain any duplicates and must be at least 40 characters long.
 * @return Returns the String given String as an encrypted byte array.
 */
 public static byte[] encrypt(String message, Password password, char[] new_CharSet){
 return encrypt(message,password,new_CharSet,null);
 }
 /**
 * Method used for encrypting a String. The String passed through
 * this method will be encrypted and returned as byte array.
 * The String will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the String are kept
 * private and secure.
 * This method allows the input of a custom character set, a password and the security level
 * which is to be associated with the generated key. The password, the security level and
 * the submitted character set will be needed for decryption of Strings which were encrypted using the
 * submitted password, character set and security level.
 * <p>
 * @param message String message which you wish to encrypt.
 * @param password :The password to be associated with the encryption. The password must be at least 6 characters long.
 * @param new_CharSet :The character set used by the encrypted String. The character
 * set cannot contain any duplicates and must be at least 40 characters long.
 * @param security :The level of security which is to be assign to the encrypted message. The higher the security level
 * the higher the level of encryption but also the slower the encryption process will be. The lower the security level
 * the lower the encryption but the faster the encryption will be.
 * @return Returns the String given String as an encrypted byte array.
 */
 public static byte[] encrypt(String message, Password password, char[] new_CharSet, SecurityLevel security){
 if(prepareEncryption(new_CharSet, password, security)){
 String cypher = addRandom(message).toString();
 byte[] encryption = cypher.getBytes(format);
 byte[] swapped_Bytes = revertBytes(EncryptionUtils.toByteObject(encryption));
 return swapBytes(swapped_Bytes);

 }else{
 return null;
 }
 }
 /**
 * Method used for decrypting a String in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 * This method allows the input of the password associated with
 * the encrypted file which is needed in order to be able to view the file.
 * <p>
 * @param encryption :byte array containing the encrypted String.
 * @param password :The password associated to the file. Needed in order
 * to view the file! The password must match the password used to encrypt the file
 * @return :Returns a decypted String.
 */
 public static String decrypt(byte[] encryption, Password password){
 return decrypt(encryption,password,null,null);
 }
 /**
 * Method used for decrypting a String in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 *
 * This method allows the input of the character set and the password
 * associated with the encrypted file. Both the character set and the password
 * are needed in order to view the original String content
 * <p>
 * @param encryption :byte array containing the encrypted String.
 * @param password :The password associated to the file. Needed in order
 * to view the file! The password must match the password used to encrypt the file
 * @param new_CharSet :The character set associated with the encrypted file.
 * needed in order to view the file! Must match the character set used to encrypt the String
 * @return Returns a decypted String.
 */
 public static String decrypt(byte[] encryption, Password password, char[] new_CharSet){
 return decrypt(encryption,password,new_CharSet,null);
 }
 /**
 * Method used for decrypting a String in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 *
 * This method allows the input of the character set, the password and the security level
 * associated with the encrypted file. All of the inputs are needed in order to view the original
 * content of the file.
 * <p>
 * @param encryption :byte array containing the encrypted String.
 * @param password :The password associated to the file. Needed in order
 * to view the file! The password must match the password used to encrypt the String.
 * @param new_CharSet :The character set associated with the encrypted file.Must match the character
 * set used to encrypt the String.
 * @param security :The security level which is associated with the encrypted String.Muse match
 * the security level used to encrypt the String.
 * @return Returns a decypted String.
 */
 public static String decrypt(byte[] encryption, Password password, char[] new_CharSet, SecurityLevel security){
 if(prepareEncryption(new_CharSet, password, security)){
 byte[] unswapped_Bytes = revertBytesBack(EncryptionUtils.toByteObject(unSwapBytes(encryption)));
 List<String> list = EncryptionUtils.fromStringToList(new String(unswapped_Bytes, format),", ");
 EncryptedMessage unScrambled = removeRandom(list);
 String decyphered = revertSubstitution(unScrambled);
 return decyphered;
 }
 else{
 return "";
 }
 }
 /*
 * Method incharged of processing the encryption and decryption request made
 * by the user. This method will perform checks on the validity of the password and the character
 * set if any. If both the password and the character set are valid the method will then generate a key
 * and allow the encryption to proceed further.
 */
 private static boolean prepareEncryption(char[] new_CharSet, Password password, SecurityLevel security){
 boolean duplicates = false;
 String[] byte_Plain =
 {"1","2","3","4","5","6","7","8","9","0"};
 char[] plain_char_set =
 {'A','B','C','D','E','F','G','H',
 'I','J','K','L','M','N','O','P',
 'Q','R','S','T','U','V','W','X',
 'Y','Z','Ö','Ä','Å','0','1','2',
 '3','4','5','6','7','8','9',' ',
 ',','?','.','!'};

 if (password.isPasswordOk() && new_CharSet != null) {
  duplicates = EncryptionUtils.containsDuplicates(new_CharSet) ;
 if(!duplicates && new_CharSet.length>=40) {
 KeyGenerator keyGen = new KeyGenerator(password.getPassword(),new_CharSet, byte_Plain);
  setSecurityLevel(password.getPassword(), security);
 key_Map.clear();
 plain_Map.clear();
 key_Byte_Map.clear();
 plain_Byte_Map.clear();
 for(int i = 0; i < new_CharSet.length; i++){
 plain_Map.put(keyGen.getBase_key()[i], keyGen.getNew_Key()[i]);
 key_Map.put(keyGen.getNew_Key()[i], keyGen.getBase_key()[i]);
 }
 for (int i = 0; i < byte_Plain.length; i++) {
 plain_Byte_Map.put(keyGen.getBase_Byte()[i], keyGen.getNew_Byte()[i]);
 key_Byte_Map.put(keyGen.getNew_Byte()[i], keyGen.getBase_Byte()[i]);
 }
 return true;
 }
 else if(duplicates && new_CharSet.length>=40){
 new InvalidCharacterSetException("The submitted character set contains duplicates!");
 return false;
 }
  else if(!duplicates && new_CharSet.length<40){
 new InvalidCharacterSetException("The submitted character set does not meet the character amount specification!");
 return false;
 }
 else{
 new InvalidCharacterSetException("The submitted character set contains less than then minimum allow amount of characters!");
 return false;
 }
 }
 else if (password.isPasswordOk() && new_CharSet == null) {
  KeyGenerator keyGen = new KeyGenerator(password.getPassword(),plain_char_set, byte_Plain);
 setSecurityLevel(password.getPassword(), security);
 key_Map.clear();
 plain_Map.clear();
 key_Byte_Map.clear();
 plain_Byte_Map.clear();
 for(int i = 0; i < plain_char_set.length; i++){
 plain_Map.put(keyGen.getBase_key()[i], keyGen.getNew_Key()[i]);
  key_Map.put(keyGen.getNew_Key()[i], keyGen.getBase_key()[i]);
 }
 for (int i = 0; i < byte_Plain.length; i++){
 plain_Byte_Map.put(keyGen.getBase_Byte()[i], keyGen.getNew_Byte()[i]);
 key_Byte_Map.put(keyGen.getNew_Byte()[i], keyGen.getBase_Byte()[i]);
 }
 return true;
 } else {
 new InvalidPasswordException("The submitted password is not valid");
 return false;
 }
 }
 /*
 * Method used to swapp the elements of the input array.
 * The elements will be swapped using 4 nested loops with
 * different swap indexes. The elements are swapped around
 * millions of times
 */
 private static char[] swapCharacters(char[] chars){
 for(int i1 = 0; i1<chars.length-swap_index_1; i1++){
 char temp = chars[i1];
 chars[i1] = chars[i1+swap_index_1];
 chars[i1+swap_index_1] = temp;
 for(int i2 = 0; i2<chars.length-swap_index_2; i2++){
 char temp2 = chars[i2];
 chars[i2] = chars[i2+swap_index_2];
 chars[i2+swap_index_2] = temp2;
 for(int i3 = 0; i3<chars.length-swap_index_3; i3++){
 char temp3 = chars[i3];
 chars[i3] = chars[i3+swap_index_3];
 chars[i3+swap_index_3] = temp3;
 for(int i4 = swap_index_4; i4<chars.length; i4++){
 char temp4 = chars[i4];
 chars[i4] = chars[i4-swap_index_4];
 chars[i4-swap_index_4] = temp4;
 }
 }
 }
 }
 return chars;
 }
 /*
 * Method used to swapp the elements which were previously swapped
 * by the swapCharacters method back to their original index. The swap
 */
 private static char[] revertCharacterSwap(char[] chars) {
 for (int i1 = chars.length - (swap_index_1+1); i1 >= 0; i1--) {
 for (int i2 = chars.length - (swap_index_2+1); i2 >= 0; i2--) {
 for (int i3 = chars.length - (swap_index_3+1); i3 >= 0; i3--) {
 for (int i4 = chars.length - 1; i4 >= (swap_index_4); i4--) {
 char temp4 = chars[i4];
 chars[i4] = chars[i4 - swap_index_4];
 chars[i4 - swap_index_4] = temp4;
 }
 char temp3 = chars[i3];
 chars[i3] = chars[i3 + swap_index_3];
 chars[i3 + swap_index_3] = temp3;
 }
 char temp2 = chars[i2];
 chars[i2] = chars[i2 + swap_index_2];
 chars[i2 + swap_index_2] = temp2;
 }
 char temp = chars[i1];
 chars[i1] = chars[i1 + swap_index_1];
 chars[i1 + swap_index_1] = temp;
 }
 return chars;
 }
 /*
 * Method which swaps the elements match to the character set
 * whith the correspondnt key element. The method will also create
 * an array holing information about the case of each character. The method
 * will also perform a character swap with a call to the swapCharacters method. After
 * the process is completed this method will return a set of characters holding the
 * coded message along with a set of characters holding case information. The
 * two are divided by a special sequence of symbols in order to distinguish the
 * the two. The return message will then be passed further for further encryption.
 */
 private final static EncryptedMessage applySubstitution(char[] message) {
 char[] case_Binary = new char[message.length];
 char[] code_Message = new char[message.length];
 for(int i = 0; i < message.length; i++) {
 if (Character.isUpperCase(message[i])) {
 case_Binary[i] = '1';
 }
 if (Character.isLowerCase(message[i])) {
 case_Binary[i] = '0';
 }
 code_Message[i] = Character.toUpperCase(message[i]);
 if(plain_Map.containsKey(code_Message[i])){
 code_Message[i] = plain_Map.get(code_Message[i]);
 }
 }
 return new EncryptedMessage(swapCharacters(code_Message),case_Binary);
 }
 /*
 * Method which reverts the character substitution performed by the
 * applySubstitution. It does this by reverting the pattern in which the substitution
 * was made. This will separate and analyze the message along with the case data
 * and once this is done it will also peform a call to the revertCharacterSwap method
 * in order to also unswap the order of the characters to their original state.
 * Once the substitution and the character swap has been reversed it wil further
 * analyze case data determine the case of each character. Upon completion it
 * will return the decrypted message.
 */
 private final static String revertSubstitution(EncryptedMessage message) {
 char[] code_Message = revertCharacterSwap(message.getCharMessage());
 char[] case_Message = message.getCharCase();
 for (int i = 0; i < code_Message.length; i++) {
 if(key_Map.containsKey(code_Message[i])){
 code_Message[i] = key_Map.get(code_Message[i]);
 }
 if (case_Message[i] == '1') {
 code_Message[i] = Character.toUpperCase(code_Message[i]);
 }
 if (case_Message[i] == '0') {
 code_Message[i] = Character.toLowerCase(code_Message[i]);
 }
 }
 return String.valueOf(code_Message);
 }
 /*
 * Method used to further increases the obsfuscation level of the message by adding
 * random numbers and characters to the body of the already encrypted message. This
 * is done at key places of the message in order to allow the substraction of the oginal
 * version of the encryption witout having to deal with the extrac characters and numbers
 * added by this function. The function a
 * the process can then be reversed with an additional key.
 */
 private final static LinkedList<String> addRandom(String code) {
 LinkedList<String> cypherList = new LinkedList<>();
 EncryptedMessage case_and_code = applySubstitution(code.toCharArray());
 String code_message = case_and_code.getMessage();
 String code_case = case_and_code.getCase();
 for (int index = 0; index < code_message.length(); index++) {
 cypherList.add(EncryptionUtils.getRandomString(max_additions,code_message.charAt(index),insertion_index));
 }

 cypherList.addFirst("" + (EncryptionUtils.getRandomInterval(100,999)));
 cypherList.addLast(code_case + EncryptionUtils.getRandomInterval(100,999)+EncryptionUtils.getRandomString(2));
 return cypherList;
 }
 /*
 * Method used to remove all previously added obsfuscation elements. The method
 * will loop through the values of a given list and it will filter the orignal's
 * message values into their respective char arrays, one holding the code and the
 * othe holding the case related data.
 */
 private final static EncryptedMessage removeRandom(List<String> cypher_List) {
 StringBuilder string_Builder = new StringBuilder();
 char[] case_message = new char[cypher_List.get(cypher_List.size()-1).length()-5];
 char[] code_message = new char[cypher_List.size()-1];
 for (int index = 0; index < cypher_List.size() - 1; index++) {
 if (index >= 1){
 try{
 string_Builder.append(String.valueOf(cypher_List.get(index).toCharArray()[insertion_index]));
 }catch(ArrayIndexOutOfBoundsException e){ /*TODO NOTHING*/}
 }
 if (index < case_message.length){
 case_message[index] = cypher_List.get(cypher_List.size() - 1).toCharArray()[index];
 }
 }
 code_message = string_Builder.toString().toCharArray();
 return new EncryptedMessage(code_message, case_message);
 }
 /*
 * Method used to further encrypt the message by replacing the
 * first first digit of every value on every index of the byte array
 * except for indexes that hold a negative value. This method converts
 * the byte value to String which is than formated and casted back to
 * a byte. A modification can be perform that may allow each index to
 * be replace using a numerical value check!
 */
 private final static Byte[] replaceBytes(Byte[] bytes) {
 Byte[] temp_Bytes = Arrays.copyOf(bytes, bytes.length);
 for (int i = 0; i < temp_Bytes.length; i++) {
 if (Integer.toString(temp_Bytes[i]).charAt(0) != '-') {
 String temp_String = String.valueOf(temp_Bytes[i]);
 String new_Value = plain_Byte_Map.get(Integer.toString(temp_Bytes[i]).substring(0, 1))+ temp_String.substring(1);
 temp_Bytes[i] = Byte.valueOf(new_Value);
 }
 }
 return temp_Bytes;
 }
 /*
 * Method used to revert the previously replaced bytes back to
 * to normal. The byte array will go throug an identical procedure
 * as the one performed in the replace bytes method in order to
 * give each byte index the original value of the first index.
 */
 private final static Byte[] revertByteReplacement(Byte[] bytes) {
 Byte[] temp_Bytes = Arrays.copyOf(bytes, bytes.length);
 for (int i = 0; i < temp_Bytes.length; i++) {
 if (Integer.toString(temp_Bytes[i]).charAt(0) != '-') {
 String temp_String = String.valueOf(temp_Bytes[i]);
 String new_Value = key_Byte_Map.get(Integer.toString(temp_Bytes[i]).substring(0, 1))+ temp_String.substring(1);
 temp_Bytes[i] = Byte.valueOf(new_Value);
 }
 }
 return temp_Bytes;
 }
 /*
 * Method used to swapp the elements of the input array.
 * The elements will be swapped using 3 nested loops with
 * different swap indexes. The elements are swapped around
 * millions of times.
 */
 private final static byte[] swapBytes(byte[] bytes){
 for(int i1 = 0; i1<bytes.length-swap_index_1; i1++){
 byte temp = bytes[i1];
 bytes[i1] = bytes[i1+swap_index_1];
 bytes[i1+swap_index_1] = temp;
 for(int i2 = 0; i2<bytes.length-swap_index_2; i2++){
 byte temp2 = bytes[i2];
 bytes[i2] = bytes[i2+swap_index_2];
 bytes[i2+swap_index_2] = temp2;
 for(int i3 = swap_index_4; i3<bytes.length; i3++){
 byte temp3 = bytes[i3];
 bytes[i3] = bytes[i3-swap_index_4];
 bytes[i3-swap_index_4] = temp3;
 }
 }
 }
 return bytes;
 }
 /*
 * Method used to swapp the elements which were previously swapped
 * by the swapBytes method back to their original index. The swap
 */
 private final static byte[] unSwapBytes(byte[] bytes){
 for (int i1 = bytes.length - (swap_index_1+1); i1 >= 0; i1--) {
 for (int i2 = bytes.length - (swap_index_2+1); i2 >= 0; i2--) {
 for (int i3 = bytes.length - 1; i3 >= (swap_index_4); i3--) {
 byte temp3 = bytes[i3];
 bytes[i3] = bytes[i3 - swap_index_4];
 bytes[i3 - swap_index_4] = temp3;
 }
 byte temp2 = bytes[i2];
 bytes[i2] = bytes[i2 + swap_index_2];
 bytes[i2 + swap_index_2] = temp2;
 }
 byte temp = bytes[i1];
 bytes[i1] = bytes[i1 + swap_index_1];
 bytes[i1 + swap_index_1] = temp;
 }
 return bytes;
 }
 /**
 * Reverses the byte array for further increase obfuscation.
 */
 private final static byte[] revertBytes(Byte[] encryption){
 Byte[] byte_Array = encryption;
 List<Byte> byte_List = Arrays.asList(byte_Array);
 Collections.reverse(byte_List);
 return EncryptionUtils.toPrimitives(replaceBytes(byte_Array));
 }
 /**
 * Reverses the byte array to its original state
 */
 private final static byte[] revertBytesBack(Byte[] encryption){
 Byte[] byte_Array = encryption;
 List<Byte> byte_List = Arrays.asList(byte_Array);
 Collections.reverse(byte_List);
 return EncryptionUtils.toPrimitives(revertByteReplacement(byte_Array));
 }
 /*
 * Method which checks the security level required by the user
 * and base on the specifications it will adjust the amount of characters per character
 * which are to be added to the encrypted message. The higher the security level the
 * higher the number of added characters and vice versa.
 */
 private final static void setSecurityLevel(String password, SecurityLevel security){
 if(security!=null){
// SecureRandom rand = new SecureRandom();
// rand.setSeed(password.getBytes(format));
 switch(security){
 case LOW:
 max_additions = 1;
 insertion_index = 0;
 break;
 case MEDIUM:
 max_additions = 4;
 insertion_index = 3;
 break;
 case HIGH:
 max_additions = 6;
 insertion_index = 2;
 break;
 case VERY_HIGH:
 max_additions = 10;
 insertion_index = 7;
 break;
 default:
 break;
 }
 }
 }
 /**
 * <h1>Encrypted Message</h1>
 *
 * This class is used as a wrapper containing both
 * the code of the actual String and case data of
 * said String.
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
 private static class EncryptedMessage{
 private final String code_message;
 private final String case_message;
 public EncryptedMessage(char[] codeX, char[] caseX){
 this.code_message = String.valueOf(codeX);
 this.case_message = String.valueOf(caseX);
 }
 public final String getMessage(){
 return code_message;
 }
 public final String getCase(){
 return case_message;
 }
 public final char[] getCharMessage(){
 return code_message.toCharArray();
 }
 public final char[] getCharCase(){
 return case_message.toCharArray();
 }
 }
 /**
 * <h1>Encryption Utility</h1>
 *
 * This class contains various functions used by the program.
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
 public static class EncryptionUtils{
 /*
 * Method which converts an Object byte array to a primitive type.
 */
 private static byte[] toPrimitives(Byte[] byte_Object){
 byte[] bytes = new byte[byte_Object.length];
 int i = 0;
 for(Byte byte_Objects : byte_Object)bytes[i++] = byte_Objects;
 return bytes;
 }
 /*
 * Method which converts a primitive byte array to an object byte array.
 */
 private static Byte[] toByteObject(byte[] byte_prime) {
 Byte[] bytes = new Byte[byte_prime.length];
 int i = 0;
 for (byte byte_Primes : byte_prime) bytes[i++] = byte_Primes;
 return bytes;
 }
 /*
 * Method which converts an Object byte array to a primitive type.
 */
 @SuppressWarnings("unused")
 private static char[] toCharPrimitive(Character[] char_Object){
 char[] chars = new char[char_Object.length];
 int i = 0;
 for(Character char_Objects : char_Object)chars[i++] = char_Objects;
 return chars;
 }
 /*
 * Method which converts a primitive byte array to an object byte array.
 */
 @SuppressWarnings("unused")
 private static Character[] toCharObject(char[] char_prime) {
 Character[] chars = new Character[char_prime.length];
 int i = 0;
 for (char chars_Primes : char_prime) chars[i++] = chars_Primes;
 return chars;
 }
 /*
 * Method which prints the content of a byte array.
 */
 public static String printBytes(byte[] binaryEncription){
  if(binaryEncription!=null){
 return new String(binaryEncription, format);
 }
 else
 return "";
 }
 /*
 * Method which splits a String at a given character sequence
 * and returns List made out of all the sections.
 */
 private static List<String> fromStringToList(String list, String sequence) {
 return Arrays.asList(list.split(sequence));
 }
 /*
 * Method which generates a secure random within a
 * given range.
 */
 private static int getRandom(int value){
 SecureRandom rand = new SecureRandom();
 return rand.nextInt(value);
 }
 /*
 * Method which generates a secure random within a
 * given interval.
 */
 private static int getRandomInterval(int minValue, int maxValue) {
 SecureRandom rand = new SecureRandom();
 return rand.nextInt(maxValue + 1 - minValue) + minValue;
 }
 /*
 * Method which returns a random String of the specified
 * lenght containing a non random element located at the given index.
 */
 private static String getRandomString(int length, char code, int index){
 char[] randomString = new char[length];
 for(int i = 0;i<length; i++){
 randomString[i] =added[getRandom(added.length)];
 if(i==index){
 randomString[i] = code;
 }
 }
 return String.valueOf(randomString);
 }
 /*
 * Method which returns a radom String of the specified
 * lenght.
 */
 private static String getRandomString(int length){
 char[] randomString = new char[length];
 for(int i = 0;i<length; i++){
 randomString[i] =added[getRandom(added.length)];
 }
 return String.valueOf(randomString);
 }

 /*
 * Method which checks if a char array contains any duplicate values
 */
 public static boolean containsDuplicates(final char[] chars) {
 final int max_size = 99999;
 BitSet bitset = new BitSet(max_size + 1);
 bitset.set(0, max_size, false);
 for (int item : chars) {
 if (!bitset.get(item)) {
 bitset.set(item, true);
 } else
 return true;
 }
 return false;
 }
 }
 /**
 * Class which is in charge of generating new unique keys based on the
 * the given password and character set if any. Each
 * @author Eudy Contreras
 *
 */
 private static class KeyGenerator {
 private char[] char_key_set;
 private char[] char_base_set;
 private String[] byte_key_set;
 private String[] byte_base_set;
 private SecureRandom charRandom = new SecureRandom();
 private SecureRandom byteRandom = new SecureRandom();
 public KeyGenerator(String password, char[] charSet, String[] byteSet) {
 this.generateKey(password,charRandom,charSet);
 this.generateKey(password,byteRandom,byteSet);
 this.shuffle(char_key_set,charRandom,ShuffelMethod.RICHARD_DURSTENFELD_SHUFFLE);
 this.shuffle(byte_key_set,byteRandom);
 }
 /*
 * Creates a new key based on a given password. The password given will
 * always reproduce the same key if combined with the same set of
 * characters.
 */
 private void generateKey(String password,SecureRandom charRandom, char[] baseChars) {
 charRandom.setSeed(password.getBytes(format));
 char_base_set = new char[baseChars.length];
 char_base_set = Arrays.copyOf(baseChars, baseChars.length);
 char_key_set = new char[char_base_set.length];
 char_key_set = Arrays.copyOf(char_base_set, baseChars.length);
 }
 private void generateKey(String password, SecureRandom byteRandom, String[] baseBytes) {
 byteRandom.setSeed(password.getBytes(format));
 byte_base_set = new String[baseBytes.length];
 byte_base_set = Arrays.copyOf(baseBytes, baseBytes.length);
 byte_key_set = new String[byte_base_set.length];
 byte_key_set = Arrays.copyOf(byte_base_set, baseBytes.length);
 }
 /*
 * Method which securely shuffles an array using different conventional
 * methods
 */
 private void shuffle(char[] char_key,SecureRandom charRandom, ShuffelMethod method) {
 switch (method) {
 case FISHER_YATES_SHUFFLE:
 int index;
 for (int i = char_key.length - 1; i > 0; i--) {
 index = charRandom.nextInt(i + 1);
 if (index != i) {
 char_key[index] ^= char_key[i];
 char_key[i] ^= char_key[index];
 char_key[index] ^= char_key[i];
 }
 }
 break;
 case RICHARD_DURSTENFELD_SHUFFLE:
 for (int i = char_key.length - 1; i > 0; i--) {
 index = charRandom.nextInt(i + 1);
 char temp = char_key[index];
 char_key[index] = char_key[i];
 char_key[i] = temp;
 }
 break;
 default:
 break;
 }
 }
 /*
 * Method which securely shuffles an array using different conventional
 * methods
 */
 private void shuffle(String[] byte_key, SecureRandom byteRandom) {
 int index;
 for (int i = byte_key.length - 1; i > 0; i--) {
 index = byteRandom.nextInt(i + 1);
 String temp = byte_key[index];
 byte_key[index] = byte_key[i];
 byte_key[i] = temp;
 }
 }
 public enum ShuffelMethod {
 FISHER_YATES_SHUFFLE, RICHARD_DURSTENFELD_SHUFFLE,
 }
 public char[] getBase_key() {
 return char_base_set;
 }
 public String[] getBase_Byte() {
 return byte_base_set;
 }
 public char[] getNew_Key() {
 return char_key_set;
 }
 public String[] getNew_Byte() {
 return byte_key_set;
 }
 }
 /**
 * Password class used by the String Encryption Utility
 * the pass word must contain at least 6 character.
 * @author Eudy Contreras
 *
 */
 public static class Password{
 private String password;
 public Password(String password){
 this.password = password;
 }
 private String getPassword(){
 return password;
 }
 private boolean isPasswordOk(){
 return password.length()>=6 && password!=null;
 }
 }
 public enum SecurityLevel{
 LOW,MEDIUM,HIGH,VERY_HIGH
 }
 private static class InvalidPasswordException extends Exception {
 private static final long serialVersionUID = 1L;
 public InvalidPasswordException(String message) {
 super(message);
 System.err.println(this.getMessage());
 System.err.println("Please look at the documentation for more information");
 }
 }
 private static class InvalidCharacterSetException extends Exception {
 private static final long serialVersionUID = 1L;
 public InvalidCharacterSetException(String message) {
 super(message);
 System.err.println(this.getMessage());
 System.err.println("Please look at the documentation for more information");
 }
 }
 public static void main(String[] args) {
 char[] new_char_set =
 {'D',' ','F','G','H','Ä','U','J',
 'A','L','Z','Å','N',',','P','Q',
  'W','S','T','Ö','.','V','R','X',
 'Y','M','!','B','O','4','6','1',
 '8','3','2','9','0','5','7','E',
 'C','?','I','K','$','/','@','*'};
 long encrypt_start_time = System.currentTimeMillis();
 byte[] encryption = StringEncrypter.encrypt("Your message is now secure!!", new Password("password"),new_char_set, SecurityLevel.MEDIUM);
 long encrypt_end_time = System.currentTimeMillis();
 System.out.println("Encryption speed: "+(encrypt_end_time - encrypt_start_time)+ " Milliseconds");

 System.out.println("Actual encrypted message:");
 System.out.println("////////////////////////////////////////////////////////////////////////////////");
 System.out.println("");
 System.out.println(EncryptionUtils.printBytes(encryption));
 System.out.println("");
 System.out.println("////////////////////////////////////////////////////////////////////////////////");

// System.out.println(Arrays.toString(encryption));
 long decrypt_start_time = System.currentTimeMillis();
 System.out.println(StringEncrypter.decrypt(encryption,new Password("password"),new_char_set,SecurityLevel.MEDIUM));
 long decrypt_end_time = System.currentTimeMillis();
 System.out.println("Decryption speed: "+(decrypt_end_time - decrypt_start_time)+ " Milliseconds");
 }
}
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
 * <h1>String Encrypter</h1>
 *
 * This programs allows you encrypt a string and store as a byte array.
 * the program provides a simple encryption set of methods which make use of
 * scrambling/adding/replacing/swapping/ the core structure of the string.
 * The encrypted message is the store as byte array object which can be sent through sockets
 * or stored locally. In order to be able to view the content of the string the object
 * must be passed through the decrypt method of this program which will format and reconstruc the
 * string to it's original state.
 *
 * If the message is infiltrated while stored as an encrypted byte array whether if it is traveling
 * through a socket or store locally on a system. the thief wont be able to see
 * the content of the message without the key used by this class
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
public class StringEncrypter {
 private final static Charset format = Charset.forName("UTF-8");
 private final static char[] plain =
 {'A','B','C','D','E','F','G','H',
 'I','J','K','L','M','N','O','P',
 'Q','R','S','T','U','V','W','X',
 'Y','Z','Ö','Ä','Å','0','1','2',
 '3','4','5','6','7','8','9',' ',
 ',','?','.','!'};
 private final static char[] key =  {'D',' ','F','G','H','Ä','U','J',
 'A','L','Z','Å','N',',','P','Q',
 'W','S','T','Ö','.','V','R','X',
 'Y','M','!','B','O','4','6','1',
 '8','3','2','9','0','5','7','E',
 'C','?','I','K'};
 private final static char[] added =
 {'L','3','5','G','0','Ä','1','0',
  'A','D','9','Å','N','C','0','Y',
  'W','S','8','Ö','4','V','4','1',
 'Q','7','K','6','O','3','6','X',
 '8','3','2','9','0','5','7'};
 private final static String[] byte_Plain =
 {"1","2","3","4","5","6","7","8","9","0"};
 private final static String[] byte_Key =
 {"8","0","5","4","9","6","1","3","7","2"};
 private final static Map<Character, Character> plain_Map;
 static
 {
 plain_Map = new HashMap<Character, Character>();
 for(int i = 0; i<plain.length; i++){
 plain_Map.put(plain[i],key[i]);
 }
 }
 private final static Map<Character, Character> key_Map;
 static
 {
 key_Map = new HashMap<Character, Character>();
 for(int i = 0; i<plain.length; i++){
 key_Map.put(key[i],plain[i]);
 }
 }
 private static Map<String, String> plain_Byte_Map;
 static
 {
 plain_Byte_Map = new HashMap<String, String>();
 for(int i = 0; i<byte_Plain.length; i++){
 plain_Byte_Map.put(byte_Plain[i],byte_Key[i]);
 }
 }
 private final static Map<String, String> key_Byte_Map;
 static
 {
 key_Byte_Map = new HashMap<String, String>();
 for(int i = 0; i<byte_Plain.length; i++){
 key_Byte_Map.put(byte_Key[i],byte_Plain[i]);
 }
 }
 /**
 * This values determined the swap indexes at which the swapping methods
 * will operate.
 */
 private final static int swap_index_1 = 2;
 private final static int swap_index_2 = 6;
 private final static int swap_index_3 = 4;
 private final static int swap_index_4 = 3;

 /*
 * The higher the number the more random characters will be added to the encryption.
 * The number set here will affect the performace of the application. The higher the
 * number the lower the performance will be but the more populated with random characters
 * he encryption will be.
 */
 private final static int max_additions = 6;

 /*
 * The index in which the actually code character will be added too
 * the index must be a number between 0 and max_additions-1.
 */
 private final static int insertion_index = 2;
 /**
 * Method used for encrypting a string. The String passed through
 * this method will be encrypted and returned as byte array.
 * The string will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the string are kept
 * private static and secure.
 *
 * @param message String message which you wish to encrypt.
 * @return Returns the string given string as an encrypted byte array.
 */
 public static byte[] encrypt(String message){
 return encrypt(message,null,null,null);
 }
 /**
 * Method used for encrypting a string. The String passed through
 * this method will be encrypted and returned as byte array.
 * The string will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the string are kept
 * private and secure.
 * This method allows the input of a custom key set to be used
 * by this program in replacement of the originals. The key must contain all letters of the
 * swedish dictionary as well as a space character represented as
  * a character with a space in between and the standard comma sign.
 *  * <h1>Knowing the key used by this program is not enough in order
 * to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param message String message which you wish to encrypt.
 * @param new_Key :The key to be passed as a new replacement key. The key set must * be 44 characters long and cannot contain duplicates. If the key is
 * not 44 characters long it will simply be ignore and not used. The key
 * must contain the standard comma, period, question mark, exclamation mark
 * as well as the space chararcter ' '.
 * @return Returns the string given string as an encrypted byte array.
 */
 public static byte[] encrypt(String message,char[]new_Key){
 return encrypt(message,null,new_Key,null);
 }
 /**
 * Method used for encrypting a string. The String passed through
 * this method will be encrypted and returned as byte array.
 * The string will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the string are kept
 * private and secure.
 * This method allows the input of a custom character set and a key set to be used
 * by this program in replacement of the originals. The character sets passed through
 * this constructor cannot contain any duplicates.
 * <p>
 * <h1>The character set and the key set must be  * of equal lenghts and neither the character set nor the key may have repeating elements.
 * Every element found in the character set must be present in the key set and most preferably
 * at a different index<h1>
 * <p>
 * <h1>Knowing either the chararcter set or the key used by this program doest not garantee
 * the ability to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param message String message which you wish to encrypt.
 * @param new_CharSet :The new character set to be passed as a new chararcter set. The character
 * set cannot contain duplicates.
 * @param new_Key :The key to be passed as a new replacement key. The key set must contain
 * all the characters present in the character set and cannot contain duplicates
 * @return Returns the string given string as an encrypted byte array.
 */
 public static byte[] encrypt(String message, char[] new_CharSet, char[]new_Key){
 return encrypt(message,new_CharSet,new_Key,null);
 }
 /**
 * Method used for encrypting a string. The String passed through
 * this method will be encrypted and returned as byte array.
 * The string will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the string are kept
 * private and secure.
 * This method allows the input of a custom character set, key set and Byte key to be used
 * by this program in replacement of the originals. The character sets passed through
  * this constructor cannot contain any duplicates.
 * <p>
  * <h1>The character set and the key set must be * of equal lenghts and neither the character set nor the key may have repeating elements.
 * Every element found in the character set must be present in the key set and most preferably
 * at a different index<h1>
 * <p>
 * <h1>Knowing either the chararcter set or the key used by this program doest not garantee
 * the ability to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * The byte key must contain 10 unique digits with numbers
 * from 0 to 9 in any desired order.
 *
 * <h1>Knowing the byte key used by this program is not enough in order
 * to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param message String message which you wish to encrypt.
 * @param new_CharSet : The new character set to be passed as a new chararcter set. The character
 * set cannot contain duplicates.
 * @param new_Key :The key to be passed as a new replacement key. The key set must contain
 * all the characters present in the character set and cannot contain duplicates
 * @param new_byte_Key :The key to be passed as a new replacement key.
 * The key set mus be 10 characters long and cannot contain duplicates.
 * @return Returns the string given string as an encrypted byte array.
 */
 public static byte[] encrypt(String message, char[] new_CharSet, char[]new_Key, String[] new_byte_Key){
 setCharset_setKey_setByteKey(new_CharSet,new_Key,new_byte_Key);
 String cypher = addRandom(message).toString();
 byte[] encryption = cypher.getBytes(format);
 byte[] swapped_Bytes = revertBytes(EncryptionUtils.toByteObject(encryption));
 return swapBytes(swapped_Bytes);
 }
 /**
 * Method used for decrypting a string in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content
 *
 * @param encryption :byte array containing the encrypted string.
 * @return :Returns a decypted string.
 */
 public static String decrypt(byte[] encryption){
 return decrypt(encryption,null,null,null);
 }
 /**
 * Method used for decrypting a string in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 * This method allows the input of a custom key set to be used
 * by this program in replacement of the originals. The key must contain all letters of the
 * swedish dictionary as well as a space character represented as
  * a character with a space in between and the standard comma sign.
 *
 * <h1>Knowing the key used by this program is not enough in order * to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param encryption :byte array containing the encrypted string.
 * @param new_Key :The key to be passed as a new replacement key. The key set must
 * be 44 characters long and cannot contain duplicates. If the key is
 * not 44 characters long it will simply be ignore and not used. The key
  * must contain the standard comma, period, question mark, exclamation mark
 * as well as the space chararcter ' '.
 * @return Returns a decypted string.
 */
 public static String decrypt(byte[] encryption, char[] new_Key){
 return decrypt(encryption,null,new_Key,null);
 }
 /**
 * Method used for decrypting a string in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 *
 * This method allows the input of a custom character set and a key set to be used
 * by this program in replacement of the originals. The character sets passed through
 * this constructor cannot contain any duplicates.
 * <p>
 * <h1>The character set and the key set must be
 * of equal lenghts and neither the character set nor the key may have repeating elements.  * Every element found in the character set must be present in the key set and most preferably
 * at a different index<h1>
  * <p>
  * <h1>Knowing either the chararcter set or the key used by this program doest not garantee
 * the ability to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param encryption :byte array containing the encrypted string.
 * @param new_CharSet :The new character set to be passed as a new chararcter set. The character
 * set cannot contain duplicates.
 * @param new_Key :The key to be passed as a new replacement key. The key set must contain
 * all the characters present in the character set and cannot contain duplicates
 * @return Returns a decypted string.
 */
 public static String decrypt(byte[] encryption, char[] new_CharSet, char[]new_Key){
 return decrypt(encryption,new_CharSet,new_Key,null);
 }
 /**
 * Method used for decrypting a string in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 *
 * This method allows the input of a custom character set, key set and Byte key to be used
 * by this program in replacement of the originals. The character sets passed through
 * this constructor cannot contain any duplicates.
 * <p>
 * <h1>The character set and the key set must be
 * of equal lenghts and neither the character set nor the key may have repeating elements.  * Every element found in the character set must be present in the key set and most preferably
 * at a different index<h1>
 * <p>
 * <h1>Knowing either the chararcter set or the key used by this program doest not garantee
 * the ability to decode the content of the strings encrypted by this program!</h1>
 * <p>
  * The byte key must contain 10 unique digits with numbers
 * from 0 to 9 in any desired order.
 *
  * <h1>Knowing the byte key used by this program is not enough in order
  * to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param encryption :byte array containing the encrypted string.
 * @param new_CharSet :The new character set to be passed as a new chararcter set. The character
 * set cannot contain duplicates.
 * @param new_Key :The key to be passed as a new replacement key. The key set must contain
 * all the characters present in the character set and cannot contain duplicates
  * @param new_byte_Key :The key to be passed as a new replacement key.
 * The key set mus be 10 characters long and cannot contain duplicates.
 * @return Returns a decypted string.
 */
 public static String decrypt(byte[] encryption, char[] new_CharSet, char[]new_Key, String[] new_byte_Key){
 setCharset_setKey_setByteKey(new_CharSet,new_Key,new_byte_Key);
 byte[] unswapped_Bytes = revertBytesBack(EncryptionUtils.toByteObject(unSwapBytes(encryption)));
 List<String> list = EncryptionUtils.fromStringToList(new String(unswapped_Bytes, format),", ");
 EncryptedMessage unScrambled = removeRandom(list);
 String decyphered = revertSubstitution(unScrambled);
 return decyphered;
 }
 private static void setCharset_setKey_setByteKey(char[] new_CharSet, char[]new_Key, String[] new_byte_Key){
 if(new_Key!=null && new_CharSet!=null && new_Key.length == new_CharSet.length){
 key_Map.clear();
 plain_Map.clear();
 for(int i = 0; i<new_CharSet.length; i++){
 key_Map.put(new_Key[i],new_CharSet[i]);
 plain_Map.put(new_CharSet[i], new_Key[i]);
 }
 }
 else if(new_Key!=null && new_CharSet==null && new_Key.length==plain.length){
 key_Map.clear();
 for(int i = 0; i<key.length; i++){
 key_Map.put(new_Key[i],plain[i]);
 }
 }
 if(new_byte_Key!=null && new_byte_Key.length==byte_Plain.length){
 key_Byte_Map.clear();
  for(int i = 0; i<byte_Plain.length; i++){
 key_Byte_Map.put(new_byte_Key[i],byte_Plain[i]);
 }
 }
 }
 /*
 * Method used to swapp the elements of the input array.
 * The elements will be swapped using 4 nested loops with
 * different swap indexes. The elements are swapped around
 * millions of times
 */
 private static char[] swapCharacters(char[] chars){
 for(int i1 = 0; i1<chars.length-swap_index_1; i1++){
 char temp = chars[i1];
 chars[i1] = chars[i1+swap_index_1];
 chars[i1+swap_index_1] = temp;
 for(int i2 = 0; i2<chars.length-swap_index_2; i2++){
 char temp2 = chars[i2];
 chars[i2] = chars[i2+swap_index_2];
 chars[i2+swap_index_2] = temp2;
 for(int i3 = 0; i3<chars.length-swap_index_3; i3++){
 char temp3 = chars[i3];
 chars[i3] = chars[i3+swap_index_3];
 chars[i3+swap_index_3] = temp3;
 for(int i4 = swap_index_4; i4<chars.length; i4++){
 char temp4 = chars[i4];
 chars[i4] = chars[i4-swap_index_4];
 chars[i4-swap_index_4] = temp4;
 }
 }
 }
 }
 return chars;
 }
 /*
 * Method used to swapp the elements which were previously swapped
 * by the swapCharacters method back to their original index. The swap
 */
 private static char[] revertCharacterSwap(char[] chars) {
 for (int i1 = chars.length - (swap_index_1+1); i1 >= 0; i1--) {
 for (int i2 = chars.length - (swap_index_2+1); i2 >= 0; i2--) {
 for (int i3 = chars.length - (swap_index_3+1); i3 >= 0; i3--) {
 for (int i4 = chars.length - 1; i4 >= (swap_index_4); i4--) {
 char temp4 = chars[i4];
 chars[i4] = chars[i4 - swap_index_4];
 chars[i4 - swap_index_4] = temp4;
 }
 char temp3 = chars[i3];
 chars[i3] = chars[i3 + swap_index_3];
 chars[i3 + swap_index_3] = temp3;
 }
 char temp2 = chars[i2];
 chars[i2] = chars[i2 + swap_index_2];
 chars[i2 + swap_index_2] = temp2;
 }
 char temp = chars[i1];
 chars[i1] = chars[i1 + swap_index_1];
 chars[i1 + swap_index_1] = temp;
 }
 return chars;
 }
 /*
 * Method which swaps the elements match to the character set
 * whith the correspondnt key element. The method will also create
 * an array holing information about the case of each character. The method
 * will also perform a character swap with a call to the swapCharacters method. After
 * the process is completed this method will return a set of characters holding the
 * coded message along with a set of characters holding case information. The
 * two are divided by a special sequence of symbols in order to distinguish the
 * the two. The return message will then be passed further for further encryption.
 */
 private final static EncryptedMessage applySubstitution(char[] message) {
 char[] case_Binary = new char[message.length];
 char[] code_Message = new char[message.length];
 for(int i = 0; i < message.length; i++) {
 if (Character.isUpperCase(message[i])) {
 case_Binary[i] = '1';
 }
 if (Character.isLowerCase(message[i])) {
 case_Binary[i] = '0';
 }
 code_Message[i] = Character.toUpperCase(message[i]);
 if(plain_Map.containsKey(code_Message[i])){
 code_Message[i] = plain_Map.get(code_Message[i]);
 }
 }
 return new EncryptedMessage(swapCharacters(code_Message),case_Binary);
 }
 /*
 * Method which reverts the character substitution performed by the
 * applySubstitution. It does this by reverting the pattern in which the substitution
 * was made. This will separate and analyze the message along with the case data
 * and once this is done it will also peform a call to the revertCharacterSwap method
 * in order to also unswap the order of the characters to their original state.
 * Once the substitution and the character swap has been reversed it wil further
 * analyze case data determine the case of each character. Upon completion it
 * will return the decrypted message.
 */
 private final static String revertSubstitution(EncryptedMessage message) {
 char[] code_Message = revertCharacterSwap(message.getCharMessage());
 char[] case_Message = message.getCharCase();
 for (int i = 0; i < code_Message.length; i++) {
 if(key_Map.containsKey(code_Message[i])){
 code_Message[i] = key_Map.get(code_Message[i]);
 }
 if (case_Message[i] == '1') {
 code_Message[i] = Character.toUpperCase(code_Message[i]);
 }
 if (case_Message[i] == '0') {
 code_Message[i] = Character.toLowerCase(code_Message[i]);
 }
 }
 return String.valueOf(code_Message);
 }
 /*
 * Method used to further increases the obsfuscation level of the message by adding
 * random numbers and characters to the body of the already encrypted message. This
 * is done at key places of the message in order to allow the substraction of the oginal
 * version of the encryption witout having to deal with the extrac characters and numbers
 * added by this function. The function a
 * the process can then be reversed with an additional key.
 */
 private final static LinkedList<String> addRandom(String code) {
 LinkedList<String> cypherList = new LinkedList<>();
 EncryptedMessage case_and_code = applySubstitution(code.toCharArray());
 String code_message = case_and_code.getMessage();
 String code_case = case_and_code.getCase();
 for (int index = 0; index < code_message.length(); index++) {
 cypherList.add(EncryptionUtils.getRandomString(max_additions,code_message.charAt(index),insertion_index));
 }
 
 cypherList.addFirst("" + (EncryptionUtils.getRandomInterval(100,999)));
 cypherList.add(String.valueOf(code_case) + EncryptionUtils.getRandom(10));
 return cypherList;
 }
 /*
 * Method used to remove all previously added obsfuscation elements. The method
 * will loop through the values of a given list and it will filter the orignal's
 * message values into their respective char arrays, one holding the code and the
 * othe holding the case related data.
 */
 private final static EncryptedMessage removeRandom(List<String> cypher_List) {
 StringBuilder string_Builder = new StringBuilder();
 char[] case_message = new char[cypher_List.size()- 2];
 char[] code_message = new char[cypher_List.size()-1];
 for (int index = 0; index < cypher_List.size() - 1; index++) {
 if (index >= 1)
 string_Builder.append(String.valueOf(cypher_List.get(index).toCharArray()[insertion_index]));
 if (index < case_message.length)
 case_message[index] = cypher_List.get(cypher_List.size() - 1).toCharArray()[index];
 }

 code_message = string_Builder.toString().toCharArray();
 return new EncryptedMessage(code_message, case_message);
 }
 /*
 * Method used to further encrypt the message by replacing the
 * first first digit of every value on every index of the byte array
 * except for indexes that hold a negative value. This method converts
 * the byte value to string which is than formated and casted back to
 * a byte. A modification can be perform that may allow each index to
 * be replace using a numerical value check!
 */
 private final static Byte[] replaceBytes(Byte[] bytes) {
 Byte[] temp_Bytes = Arrays.copyOf(bytes, bytes.length);
 for (int i = 0; i < temp_Bytes.length; i++) {
 if (Integer.toString(temp_Bytes[i]).charAt(0) != '-') {
 String temp_String = String.valueOf(temp_Bytes[i]);
 String new_Value = plain_Byte_Map.get(Integer.toString(temp_Bytes[i]).substring(0, 1))+ temp_String.substring(1);
 temp_Bytes[i] = Byte.valueOf(new_Value);
 }
 }
 return temp_Bytes;
 }
 /*
 * Method used to revert the previously replaced bytes back to
 * to normal. The byte array will go throug an identical procedure
 * as the one performed in the replace bytes method in order to
 * give each byte index the original value of the first index.
 */
 private final static Byte[] revertByteReplacement(Byte[] bytes) {
 Byte[] temp_Bytes = Arrays.copyOf(bytes, bytes.length);
 for (int i = 0; i < temp_Bytes.length; i++) {
 if (Integer.toString(temp_Bytes[i]).charAt(0) != '-') {
 String temp_String = String.valueOf(temp_Bytes[i]);
 String new_Value = key_Byte_Map.get(Integer.toString(temp_Bytes[i]).substring(0, 1))+ temp_String.substring(1);
 temp_Bytes[i] = Byte.valueOf(new_Value);
 }
 }
 return temp_Bytes;
 }
 /*
 * Method used to swapp the elements of the input array.
 * The elements will be swapped using 3 nested loops with
 * different swap indexes. The elements are swapped around
 * millions of times.
 */
 private final static byte[] swapBytes(byte[] bytes){
 for(int i1 = 0; i1<bytes.length-swap_index_1; i1++){
 byte temp = bytes[i1];
 bytes[i1] = bytes[i1+swap_index_1];
 bytes[i1+swap_index_1] = temp;
 for(int i2 = 0; i2<bytes.length-swap_index_2; i2++){
 byte temp2 = bytes[i2];
 bytes[i2] = bytes[i2+swap_index_2];
 bytes[i2+swap_index_2] = temp2;
 for(int i3 = swap_index_4; i3<bytes.length; i3++){
 byte temp3 = bytes[i3];
 bytes[i3] = bytes[i3-swap_index_4];
 bytes[i3-swap_index_4] = temp3;
 }
 }
 }
 return bytes;
 }
 /*
 * Method used to swapp the elements which were previously swapped
 * by the swapBytes method back to their original index. The swap
 */
 private final static byte[] unSwapBytes(byte[] bytes){
 for (int i1 = bytes.length - (swap_index_1+1); i1 >= 0; i1--) {
 for (int i2 = bytes.length - (swap_index_2+1); i2 >= 0; i2--) {
 for (int i3 = bytes.length - 1; i3 >= (swap_index_4); i3--) {
 byte temp3 = bytes[i3];
 bytes[i3] = bytes[i3 - swap_index_4];
 bytes[i3 - swap_index_4] = temp3;
 }
 byte temp2 = bytes[i2];
 bytes[i2] = bytes[i2 + swap_index_2];
 bytes[i2 + swap_index_2] = temp2;
 }
 byte temp = bytes[i1];
 bytes[i1] = bytes[i1 + swap_index_1];
 bytes[i1 + swap_index_1] = temp;
 }
 return bytes;
 }
 /**
 * Reverses the byte array for further increase obfuscation.
 */
 private final static byte[] revertBytes(Byte[] encryption){
 Byte[] byte_Array = encryption;
 List<Byte> byte_List = Arrays.asList(byte_Array);
 Collections.reverse(byte_List);
 return EncryptionUtils.toPrimitives(replaceBytes(byte_Array));
 }
 /**
 * Reverses the byte array to its original state
 */
 private final static byte[] revertBytesBack(Byte[] encryption){
 Byte[] byte_Array = encryption;
 List<Byte> byte_List = Arrays.asList(byte_Array);
 Collections.reverse(byte_List);
 return EncryptionUtils.toPrimitives(revertByteReplacement(byte_Array));
 }
 /**
 * <h1>Encrypted Message</h1>
 *
 * This class is used as a wrapper containing both
 * the code of the actual string and case data of
 * said string.
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
 private static class EncryptedMessage{
 private final String code_message;
 private final String case_message;
 public EncryptedMessage(char[] codeX, char[] caseX){
 this.code_message = String.valueOf(codeX);
 this.case_message = String.valueOf(caseX);
 }
 public final String getMessage(){
 return code_message;
 }
 public final String getCase(){
 return case_message;
 }
 public final char[] getCharMessage(){
 return code_message.toCharArray();
 }
 public final char[] getCharCase(){
 return case_message.toCharArray();
 }
 }
 /**
 * <h1>Encryption Utility</h1>
 *
 * This class contains various functions used by the program.
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
 private static class EncryptionUtils{
 /*
 * Method which converts an Object byte array to a primitive type.
 */
 private static byte[] toPrimitives(Byte[] byte_Object){
 byte[] bytes = new byte[byte_Object.length];
 int i = 0;
 for(Byte byte_Objects : byte_Object)bytes[i++] = byte_Objects;
 return bytes;
 }
 /*
 * Method which converts a primitive byte array to an object byte array.
 */
 private static Byte[] toByteObject(byte[] byte_prime) {
 Byte[] bytes = new Byte[byte_prime.length];
 int i = 0;
 for (byte byte_Primes : byte_prime) bytes[i++] = byte_Primes;
 return bytes;
 }
 /*
 * Method which prints the content of a byte array.
 */
 private static String printBytes(byte[] binaryEncription){
 return new String(binaryEncription, format);
 }
 /*
 * Method which splits a string at a given character sequence
 * and returns List made out of all the sections.
 */
 private static List<String> fromStringToList(String list, String sequence) {
 return Arrays.asList(list.split(sequence));
 }
 /*
 * Method which generates a secure random within a
 * given range.
 */
 private static int getRandom(int value){
 SecureRandom rand = new SecureRandom();
 return rand.nextInt(value);
 }
 /*
 * Method which generates a secure random within a
 * given interval.
 */
 private static int getRandomInterval(int minValue, int maxValue) {
 SecureRandom rand = new SecureRandom();
 return rand.nextInt(maxValue + 1 - minValue) + minValue;
 }
 /*
 * Method which returns a random string of the specified
 * lenght containing a non random element located at the given index.
 */
 private static String getRandomString(int length, char code, int index){
 char[] randomString = new char[length];
 for(int i = 0;i<length; i++){
 randomString[i] =added[getRandom(added.length)];
 if(i==index){
 randomString[i] = code;
 }
 }
 return String.valueOf(randomString);
 }
 /*
 * Method which returns a radom string of the specified
 * lenght.
 */
 @SuppressWarnings("unused")
 private static String getRandomString(int length){
 char[] randomString = new char[length];
 for(int i = 0;i<length; i++){
 randomString[i] =added[getRandom(added.length)];
 }
 return String.valueOf(randomString);
 }
 }
 public static void main(String[] args) {
// EncryptionUtils.getRandomString(10,'Ö',1);
 long encrypt_start_time = System.currentTimeMillis();
 byte[] encryption = StringEncrypter.encrypt("What is up!!, Not much why??");
 long encrypt_end_time = System.currentTimeMillis();
 System.out.println("Encryption speed: "+(encrypt_end_time - encrypt_start_time)+ " Milliseconds");
 System.out.println("Actual encrypted message:");
 System.out.println("////////////////////////////////////////////////////////////////////////////////");
 System.out.println("");
 System.out.println(EncryptionUtils.printBytes(encryption));
 System.out.println("");
 System.out.println("////////////////////////////////////////////////////////////////////////////////");
// System.out.println(Arrays.toString(encryption));
 long decrypt_start_time = System.currentTimeMillis();
 System.out.println(StringEncrypter.decrypt(encryption));
 long decrypt_end_time = System.currentTimeMillis();
 System.out.println("Decryption speed: "+(decrypt_end_time - decrypt_start_time)+ " Milliseconds");
 }
}

I know the code is long but I tried to documented well and structure it to make easy to read. I sincerely appreciate all your time and I hope my question is well formulated and on topic.

Updated to recommendations!. Generate key instead of allowing the input of one. Operate on passwords instead!
Source Link
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
 * <h1>String Encrypter</h1>
 *
 * This programs allows you encrypt a stringString and store as a byte array.
 * the program provides a simple encryption set of methods which make use of
 * scrambling/adding/replacing/swapping/ the core structure of the stringString.
 * The encrypted message is the store as byte array object which can be sent through sockets
 * or stored locally. In order to be able to view the content of the stringString the object
 * must be passed through the decrypt method of this program which will format and reconstruc the
 * stringString to it's original state.
 *
 * If the message is infiltrated while stored as an encrypted byte array whether if it is traveling
 * through a socket or store locally on a system. the thief wont be able to see
 * the content of the message without the key used by this class
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
public class StringEncrypter {
 private final static Charset format = Charset.forName("UTF-8");
 private final static char[] plain =
  added = {'A''L','B''3','C''5','D''G','E''0','F''Ä','G''1','H''0',
 'I','J','K','L','M','N','O','P',
 'Q','R','S','T','U','V','W','X',
 'Y','Z','Ö','Ä','Å','0','1','2',
 '3','4','5','6','7''A','8''D','9',' ''Å',
 ''N',''C','?''0','.''Y','!'};

 private final static char[] key =
 {'D',' ','F','G','H','Ä','U','J',
  'A','L','Z','Å','N',',','P','Q',
 'W','S','T''8','Ö','.''4','V','R','X',
 'Y','M','!','B','O','4','6','1',
 '8','3','2','9','0','5','7','E',
 'C','?','I','K'};
 private final static char[] added =
 {'L''Q','3''7','5''K','G''6','0''O','Ä''3','1''6','0''X',
 'A','D','9','Å','N','C','0','Y',
 'W','S','8','Ö','4','V','4','1',
 'Q','7','K','6','O','3','6','X',
 '8','3','2','9','0','5','7'};
 private final static String[] byte_Plain =/*
 * {"1","2","3","4","5","6","7","8","9","0"};
Meps which hold the privateencryption finalbase staticand String[]key byte_Keydata =structures.
 {"8","0","5","4","9","6","1","3","7","2"};
*/
 private final static final Map<Character, Character> plain_Map;
 static
 {
  plain_Map = new HashMap<Character, Character>();
 for(int i = 0; i<plain.length; i++){
 plain_Map.put(plain[i],key[i]);
 }
 }

 private final static final Map<Character, Character> key_Map;
 static
 {
  key_Map = new HashMap<Character, Character>();
 for(int i = 0; i<plain.length; i++){
 key_Map.put(key[i],plain[i]);
 }
 }
 private static final Map<String, String> plain_Byte_Map;
 static
 {
  plain_Byte_Map = new HashMap<String, String>();
 private static final Map<String, for(intString> ikey_Byte_Map = 0; i<byte_Plain.length; i++){
 new HashMap<String, plain_Byte_Map.putString>(byte_Plain[i],byte_Key[i]);
 }
 }
 private final static Map<String, String> key_Byte_Map;
 static
 {
 key_Byte_Map = new HashMap<String, String>();
 for(int i = 0; i<byte_Plain.length; i++){
 key_Byte_Map.put(byte_Key[i],byte_Plain[i]);
 }
 }
 /**
 * This values determined the swap indexes at which the swapping methods
 * will operate. More swapp indexes may be added for increase security.
 */
 private final static int swap_index_1 = 2;
 private final static int swap_index_2 = 6;
 private final static int swap_index_3 = 4;
 private final static int swap_index_4 = 3;

 /*
 * The higher the number the more random characters will be added to the encryption.
 * The number set here will affect the performace of the application. The higher the
 * number the lower the performance will be but the more populated with random characters
 * he encryption will be.
 * HIgher = more secure but slower.
 * Lower = less secure but faster.
 * recommended: 6
 */
 private final static int max_additions = 6;5;

 /*
 * The index in which the actually code character will be added tooinserted.
 * the index must be a number between 0 and the max_additions value-1.
 */
 private final static int insertion_index = 2;
 /**
 * Method used for encrypting a string. The String passed through
 * this method will be encrypted and returned as byte array.
 * The string will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the string are kept
 * private static and secure.
 *
 * @param message String message which you wish to encrypt.
 * @return Returns the string given string as an encrypted byte array.
 */
 public static byte[] encrypt(String message){
 return encrypt(message,null,null,null);
 }
 /**
 * Method used for encrypting a stringString. The String passed through
 * this method will be encrypted and returned as byte array.
 * The stringString will go through a series of encryption and obsfuscation
 * methodmethods in order to assure that the contents of the stringString are kept
 * private and secure.
 * This method allows the input of a custom key setpassword to be used
 * by this program in replacement of the originals. The key must contain all letters of the
 * swedish dictionary as well as a space character represented as
  * a characterassociated with a space in between and the standard comma sign.
 *
 * <h1>Knowing thegenerated key. usedThe bypassword thiswill programbe isneeded notfor enoughdecryption inof orderStrings
 * to decodewhich thewere contentencrypted ofusing the strings encrypted by thissubmitted program!</h1>password.
 * <p>
 * @param message String message which you wish to encrypt.
 * @param new_Keypassword :The keypassword to be passed as aassociated newwith replacementthe keyencryption. The key setpassword must be *at beleast 446 characters long and cannot contain duplicates. If the key is
 * not 44 characters long it will simply be ignore and not used. The key
  *password must contain the standard comma, period, question mark, exclamation mark
 * as well asbe theat spaceleast chararcter6 'characters 'long.
 * @return Returns the stringString given stringString as an encrypted byte array.
 */
 public static byte[] encrypt(String message,char[]new_KeyPassword password){
 return encrypt(message,nullpassword,new_Keynull,null);
 }
 /**
 * Method used for encrypting a stringString. The String passed through
 * this method will be encrypted and returned as byte array.
 * The stringString will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the stringString are kept
 * private and secure.
 * This method allows the input of a custom character set and a key set to be usedpassword
 * bywhich thisare programto inbe replacementassociated ofwith the originals. The character sets passed through
 * this constructor cannot contain anygenerated duplicateskey.
 * <p>
 * <h1>The character set andboth the key set must be
  * of equal lenghtspassword and neither the character set nor the key may have repeating elements.
 * Every element found in the submitted character set mustwill be present in the key set and most preferably
 * at a different index<h1>
  * <p>
 needed for *decryption <h1>Knowingof eitherStrings thewhich chararcterwere setencrypted orusing the key used by this program doest not garantee
 * the ability to decode the content of the stringssubmitted encryptedpassword byand thischaracter program!</h1>set.
 * <p>
 * @param message String message which you wish to encrypt.
 * @param new_CharSetpassword :The new character setpassword to be passed as aassociated newwith chararcterthe setencryption. The character
  password must be *at setleast cannot6 containcharacters duplicateslong.
 * @param new_Keynew_CharSet :The key to becharacter passedset asused aby newthe replacementencrypted keyString. The key set must containcharacter
 * allset thecannot characterscontain presentany induplicates theand charactermust setbe andat cannotleast contain40 duplicatescharacters long.
 * @return Returns the stringString given stringString as an encrypted byte array.
 */
 public static byte[] encrypt(String message, char[]Password new_CharSetpassword, char[]new_Keychar[] new_CharSet){
 return encrypt(message,new_CharSetpassword,new_Keynew_CharSet,null);
 }
 /**
 * Method used for encrypting a stringString. The String passed through
 * this method will be encrypted and returned as byte array.
 * The stringString will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the stringString are kept
 * private and secure.
 * This method allows the input of a custom character set, keya setpassword and Byte key tothe besecurity usedlevel
 * bywhich thisis programto inbe replacementassociated ofwith the originalsgenerated key. The character sets passed through
 * this constructorpassword, cannotthe containsecurity anylevel duplicates.and
 * <p>
 *the <h1>Thesubmitted character set and the key set mustwill be needed for *decryption of equal lenghts and neitherStrings thewhich characterwere setencrypted norusing the key may have repeating elements.
 * Every element found insubmitted thepassword, character set must be present in the key set and most preferably
 * at a different index<h1>
 * <p>
 * <h1>Knowing either the chararcter set or the key used by this program doest not garantee
 * the ability to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * The byte key must contain 10 unique digits with numbers
 * from 0 to 9 in any desiredsecurity orderlevel.
 *
 * <h1>Knowing the byte key used by this program is not enough in order
 * to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param message String message which you wish to encrypt.
 * @param new_CharSetpassword :The newpassword characterto setbe toassociated with the encryption. The password must be passedat asleast a6 newcharacters chararcterlong.
 * @param new_CharSet :The character set used by the encrypted String. The character
 * set cannot contain any duplicates and must be at least 40 characters long.
 * @param new_Keysecurity :The keylevel of security which is to be passed asassign ato newthe replacementencrypted keymessage. The keyhigher setthe mustsecurity containlevel
 * all the characters present inhigher the character set and cannot contain duplicates
level of encryption but also *the @paramslower new_byte_Keythe :Theencryption keyprocess towill be passed. asThe alower newthe replacementsecurity key.level
 * The keythe setlower musthe beencryption 10but charactersthe longfaster andthe cannotencryption containwill duplicatesbe.
 * @return Returns the stringString given stringString as an encrypted byte array.
 */
 public static byte[] encrypt(String message, char[]Password new_CharSetpassword, char[]new_Keychar[] new_CharSet, String[]SecurityLevel new_byte_Keysecurity){
 setCharset_setKey_setByteKey(new_CharSet,new_Key,new_byte_Key);
 if(prepareEncryption(new_CharSet, password, security)){
 String cypher = addRandom(message).toString();
 byte[] encryption = cypher.getBytes(format);
 byte[] swapped_Bytes = revertBytes(EncryptionUtils.toByteObject(encryption));
 return swapBytes(swapped_Bytes);
 }
 /**
 * Method used for decrypting a string in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content
 *
 * @param encryption :byte array containing the encrypted string.
 * @return :Returns a decypted string.
 */
 public static String decrypt(byte[] encryption){
 return decrypt(encryption,null,null,null);
 }

 }else{
 return null;
 }
 }
 /**
 * Method used for decrypting a stringString in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 * This method allows the input of a custom key set to be used
 * by this program in replacement of the originals. The key must contain all letters of the
 * swedish dictionary as well as a space character represented as
  * apassword characterassociated with a space in between and the standard comma sign.
 *
 * <h1>Knowing the key used byencrypted thisfile programwhich is not enoughneeded in order * to decodebe theable contentto ofview the strings encrypted by this program!</h1>file.
 * <p>
 * @param encryption :byte array containing the encrypted stringString.
 * @param new_Keypassword :The key to be passed aspassword aassociated newto replacementthe keyfile. The keyNeeded setin mustorder
 * be 44 characters long and cannot contain duplicates.to Ifview the key is
 * not 44 characters long it will simply be ignore and not used.file! The key
 *password must containmatch the standard comma, period, question mark, exclamation mark
 *password asused wellto asencrypt the space chararcter ' '.file
 * @return :Returns a decypted stringString.
 */
 public static String decrypt(byte[] encryption, char[]Password new_Keypassword){
 return decrypt(encryption,nullpassword,new_Keynull,null);
 }
 /**
 * Method used for decrypting a stringString in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 *
 * This method allows the input of a custom character set and a key set to be used
 * by this program in replacement of the originals. The character sets passed through
 * this constructor cannot contain any duplicates.
  * <p>
 * <h1>The character set and the key set must bepassword
 * of equal lenghts and neither the character setassociated norwith the key may have repeatingencrypted elementsfile. * Every element found inBoth the character set must be present in the key set and most preferably
 * at a different index<h1>
 * <p>
  * <h1>Knowing either the chararcter set or the key used by this program doest not garanteepassword
 * the abilityare toneeded decodein theorder contentto ofview the strings encrypted byoriginal thisString program!</h1>content
 * <p>
 * @param encryption :byte array containing the encrypted stringString.
 * @param new_CharSetpassword :The new characterpassword setassociated to bethe passedfile. asNeeded ain neworder
 chararcter set. * to view the file! The character
password must match the password *used setto cannotencrypt containthe duplicates.file
 * @param new_Keynew_CharSet :The key to becharacter passedset asassociated awith newthe replacementencrypted keyfile. The key set must contain
 * needed in order *to allview the charactersfile! presentMust inmatch the character set andused cannotto containencrypt duplicatesthe String
 * @return Returns a decypted stringString.
 */
 public static String decrypt(byte[] encryption, char[]Password new_CharSetpassword, char[]new_Keychar[] new_CharSet){
 return decrypt(encryption,new_CharSetpassword,new_Keynew_CharSet,null);
 }
 /**
 * Method used for decrypting a stringString in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 *
 * This method allows the input of a custom character set, key set and Byte key to be used
 * by this program in replacement of the originals. The character sets passed through
 * this constructor cannot contain any duplicates.
 * <p>
 * <h1>The character set and the key set must be
 * of equal lenghts and neither the character set nor the key may have repeating elements.
 * Every element found in the character set must be present in the key set and most preferably
 * at a different index<h1>
 * <p>
 * <h1>Knowing either the chararcter set or the key used by this program doest not garantee
 * the ability to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * The byte key must contain 10 unique digits with numbers
 * from 0 to 9 in any desired order.
 *
 * <h1>KnowingThis method allows the byteinput keyof usedthe bycharacter thisset, programthe ispassword notand enoughthe insecurity orderlevel
 * toassociated decodewith the contentencrypted file. All of the stringsinputs encryptedare byneeded thisin program!</h1>order to view the original
 * content of the file.
 * <p>
 * @param encryption :byte array containing the encrypted stringString.
 * @param new_CharSetpassword :The new characterpassword setassociated to bethe passedfile. asNeeded ain neworder
 chararcter set. * to view the file! The character
password must match the password *used setto cannotencrypt containthe duplicatesString.
 * @param new_Keynew_CharSet :The key to becharacter passedset asassociated awith newthe replacementencrypted keyfile. The keyMust setmatch mustthe containcharacter
 * all theset charactersused presentto inencrypt the character set and cannot contain duplicatesString.
 * @param new_byte_Keysecurity :The keysecurity tolevel bewhich passedis asassociated awith newthe replacementencrypted keyString.Muse match
 * The key set mus bethe 10security characterslevel longused andto cannotencrypt containthe duplicatesString.
 * @return Returns a decypted stringString.
 */
 public static String decrypt(byte[] encryption, char[]Password new_CharSetpassword, char[]new_Keychar[] new_CharSet, String[]SecurityLevel new_byte_Keysecurity){
 setCharset_setKey_setByteKeyif(prepareEncryption(new_CharSet,new_Key password,new_byte_Key security);){
 byte[] unswapped_Bytes = revertBytesBack(EncryptionUtils.toByteObject(unSwapBytes(encryption)));
 List<String> list = EncryptionUtils.fromStringToList(new String(unswapped_Bytes, format),", ");
 EncryptedMessage unScrambled = removeRandom(list);
 String decyphered = revertSubstitution(unScrambled);
 return decyphered;
 }
 else{
 return "";
 }
 }
 /*
 * Method incharged of processing the encryption and decryption request made
 * by the user. This method will perform checks on the validity of the password and the character
 * set if any. If both the password and the character set are valid the method will then generate a key
 * and allow the encryption to proceed further.
 */
 private static boolean prepareEncryption(char[] new_CharSet, Password password, SecurityLevel security){
 boolean duplicates = false;
 String[] byte_Plain =
 {"1","2","3","4","5","6","7","8","9","0"};

 private static void setCharset_setKey_setByteKey(char[] new_CharSetplain_char_set =
 {'A','B','C','D','E','F','G','H', char[]new_Key 'I','J','K','L','M','N','O','P',
 String[] new_byte_Key){ 'Q','R','S','T','U','V','W','X',
 'Y','Z','Ö','Ä','Å','0','1','2',
 '3','4','5','6','7','8','9',' ',
 ',','?','.','!'};
 if(new_Key!=nullpassword.isPasswordOk() && new_CharSet!=null= &&null) new_Key{
 duplicates = EncryptionUtils.lengthcontainsDuplicates(new_CharSet) ==;
  if(!duplicates && new_CharSet.lengthlength>=40){
 KeyGenerator keyGen = new KeyGenerator(password.getPassword(),new_CharSet, byte_Plain);
 setSecurityLevel(password.getPassword(), security);
 key_Map.clear();
 plain_Map.clear();
 key_Byte_Map.clear();
 plain_Byte_Map.clear();
 for(int i = 0; i<new_CharSeti < new_CharSet.length; i++){
 plain_Map.put(keyGen.getBase_key()[i], keyGen.getNew_Key()[i]);
 key_Map.put(new_Key[i]keyGen.getNew_Key()[i],new_CharSet[i] keyGen.getBase_key()[i]);
 plain_Map}
 for (int i = 0; i < byte_Plain.length; i++) {
 plain_Byte_Map.put(new_CharSet[i]keyGen.getBase_Byte()[i], new_Key[i]keyGen.getNew_Byte()[i]);
 key_Byte_Map.put(keyGen.getNew_Byte()[i], keyGen.getBase_Byte()[i]);
 }
 return true;
 }
 }
  else if(new_Key!=null && new_CharSet==nullduplicates && new_Key.length==plainnew_CharSet.lengthlength>=40){
 key_Map.clear();
 new forInvalidCharacterSetException(int"The isubmitted =character 0;set i<key.length;contains i++duplicates!"){;

 key_Map.put(new_Key[i],plain[i]);return false;
 }
 else if(!duplicates && new_CharSet.length<40){
 new InvalidCharacterSetException("The submitted character set does not meet the character amount specification!");
 return false;
 }
 else{
 new InvalidCharacterSetException("The submitted character set contains less than then minimum allow amount of characters!");
 return false;
 }
 }
 else if(new_byte_Key!=nullpassword.isPasswordOk() && new_byte_Keynew_CharSet == null) {
 KeyGenerator keyGen = new KeyGenerator(password.length==byte_PlaingetPassword(),plain_char_set, byte_Plain);
 setSecurityLevel(password.lengthgetPassword(){, security);
 key_Map.clear();
 plain_Map.clear();
 key_Byte_Map.clear();
 plain_Byte_Map.clear();
 for(int i = 0; i<byte_Plaini < plain_char_set.length; i++){
 plain_Map.put(keyGen.getBase_key()[i], keyGen.getNew_Key()[i]);
  key_Map.put(keyGen.getNew_Key()[i], keyGen.getBase_key()[i]);
 }
  for (int i = 0; i < byte_Plain.length; i++) {
 plain_Byte_Map.put(keyGen.getBase_Byte()[i], keyGen.getNew_Byte()[i]);
 key_Byte_Map.put(new_byte_Key[i]keyGen.getNew_Byte()[i],byte_Plain[i] keyGen.getBase_Byte()[i]);
 }
 return true;
 } else {
 new InvalidPasswordException("The submitted password is not valid");
 return false;
 }
 }
 /*
 * Method used to swapp the elements of the input array.
 * The elements will be swapped using 4 nested loops with
 * different swap indexes. The elements are swapped around
 * millions of times
 */
 private static char[] swapCharacters(char[] chars){
 for(int i1 = 0; i1<chars.length-swap_index_1; i1++){
 char temp = chars[i1];
 chars[i1] = chars[i1+swap_index_1];
 chars[i1+swap_index_1] = temp;
 for(int i2 = 0; i2<chars.length-swap_index_2; i2++){
 char temp2 = chars[i2];
 chars[i2] = chars[i2+swap_index_2];
 chars[i2+swap_index_2] = temp2;
 for(int i3 = 0; i3<chars.length-swap_index_3; i3++){
 char temp3 = chars[i3];
 chars[i3] = chars[i3+swap_index_3];
 chars[i3+swap_index_3] = temp3;
 for(int i4 = swap_index_4; i4<chars.length; i4++){
 char temp4 = chars[i4];
 chars[i4] = chars[i4-swap_index_4];
 chars[i4-swap_index_4] = temp4;
 }
 }
 }
 }
 return chars;
 }
 /*
 * Method used to swapp the elements which were previously swapped
 * by the swapCharacters method back to their original index. The swap
 */
 private static char[] revertCharacterSwap(char[] chars) {
 for (int i1 = chars.length - (swap_index_1+1); i1 >= 0; i1--) {
 for (int i2 = chars.length - (swap_index_2+1); i2 >= 0; i2--) {
 for (int i3 = chars.length - (swap_index_3+1); i3 >= 0; i3--) {
 for (int i4 = chars.length - 1; i4 >= (swap_index_4); i4--) {
 char temp4 = chars[i4];
 chars[i4] = chars[i4 - swap_index_4];
 chars[i4 - swap_index_4] = temp4;
 }
 char temp3 = chars[i3];
 chars[i3] = chars[i3 + swap_index_3];
 chars[i3 + swap_index_3] = temp3;
 }
 char temp2 = chars[i2];
 chars[i2] = chars[i2 + swap_index_2];
 chars[i2 + swap_index_2] = temp2;
 }
 char temp = chars[i1];
 chars[i1] = chars[i1 + swap_index_1];
 chars[i1 + swap_index_1] = temp;
 }
 return chars;
 }
 /*
 * Method which swaps the elements match to the character set
 * whith the correspondnt key element. The method will also create
 * an array holing information about the case of each character. The method
 * will also perform a character swap with a call to the swapCharacters method. After
 * the process is completed this method will return a set of characters holding the
 * coded message along with a set of characters holding case information. The
 * two are divided by a special sequence of symbols in order to distinguish the
 * the two. The return message will then be passed further for further encryption.
 */
 private final static EncryptedMessage applySubstitution(char[] message) {
 char[] case_Binary = new char[message.length];
 char[] code_Message = new char[message.length];
 for(int i = 0; i < message.length; i++) {
 if (Character.isUpperCase(message[i])) {
 case_Binary[i] = '1';
 }
 if (Character.isLowerCase(message[i])) {
 case_Binary[i] = '0';
 }
 code_Message[i] = Character.toUpperCase(message[i]);
 if(plain_Map.containsKey(code_Message[i])){
 code_Message[i] = plain_Map.get(code_Message[i]);
 }
 }
 return new EncryptedMessage(swapCharacters(code_Message),case_Binary);
 }
 /*
 * Method which reverts the character substitution performed by the
 * applySubstitution. It does this by reverting the pattern in which the substitution
 * was made. This will separate and analyze the message along with the case data
 * and once this is done it will also peform a call to the revertCharacterSwap method
 * in order to also unswap the order of the characters to their original state.
 * Once the substitution and the character swap has been reversed it wil further
 * analyze case data determine the case of each character. Upon completion it
 * will return the decrypted message.
 */
 private final static String revertSubstitution(EncryptedMessage message) {
 char[] code_Message = revertCharacterSwap(message.getCharMessage());
 char[] case_Message = message.getCharCase();
 for (int i = 0; i < code_Message.length; i++) {
 if(key_Map.containsKey(code_Message[i])){
 code_Message[i] = key_Map.get(code_Message[i]);
 }
 if (case_Message[i] == '1') {
 code_Message[i] = Character.toUpperCase(code_Message[i]);
 }
 if (case_Message[i] == '0') {
 code_Message[i] = Character.toLowerCase(code_Message[i]);
 }
 }
 return String.valueOf(code_Message);
 }
 /*
 * Method used to further increases the obsfuscation level of the message by adding
 * random numbers and characters to the body of the already encrypted message. This
 * is done at key places of the message in order to allow the substraction of the oginal
 * version of the encryption witout having to deal with the extrac characters and numbers
 * added by this function. The function a
 * the process can then be reversed with an additional key.
 */
 private final static LinkedList<String> addRandom(String code) {
 LinkedList<String> cypherList = new LinkedList<>();
 EncryptedMessage case_and_code = applySubstitution(code.toCharArray());
 String code_message = case_and_code.getMessage();
 String code_case = case_and_code.getCase();
 for (int index = 0; index < code_message.length(); index++) {
 cypherList.add(EncryptionUtils.getRandomString(max_additions,code_message.charAt(index),insertion_index));
 }

 cypherList.addFirst("" + (EncryptionUtils.getRandomInterval(100,999)));
 cypherList.add(String.valueOfaddLast(code_case) + EncryptionUtils.getRandomgetRandomInterval(10100,999)+EncryptionUtils.getRandomString(2));
 return cypherList;
 }
 /*
 * Method used to remove all previously added obsfuscation elements. The method
 * will loop through the values of a given list and it will filter the orignal's
 * message values into their respective char arrays, one holding the code and the
 * othe holding the case related data.
 */
 private final static EncryptedMessage removeRandom(List<String> cypher_List) {
 StringBuilder string_Builder = new StringBuilder();
 char[] case_message = new char[cypher_List.get(cypher_List.size()- 2];1).length()-5];
 char[] code_message = new char[cypher_List.size()-1];
 for (int index = 0; index < cypher_List.size() - 1; index++) {
 if (index >= 1){
 try{
 string_Builder.append(String.valueOf(cypher_List.get(index).toCharArray()[insertion_index]));
 }catch(ArrayIndexOutOfBoundsException e){ /*TODO NOTHING*/}
 }
 if (index < case_message.length){
 case_message[index] = cypher_List.get(cypher_List.size() - 1).toCharArray()[index];
 }
 }

 code_message = string_Builder.toString().toCharArray();
 return new EncryptedMessage(code_message, case_message);
 }
 /*
 * Method used to further encrypt the message by replacing the
 * first first digit of every value on every index of the byte array
 * except for indexes that hold a negative value. This method converts
 * the byte value to stringString which is than formated and casted back to
 * a byte. A modification can be perform that may allow each index to
 * be replace using a numerical value check!
 */
 private final static Byte[] replaceBytes(Byte[] bytes) {
 Byte[] temp_Bytes = Arrays.copyOf(bytes, bytes.length);
 for (int i = 0; i < temp_Bytes.length; i++) {
 if (Integer.toString(temp_Bytes[i]).charAt(0) != '-') {
 String temp_String = String.valueOf(temp_Bytes[i]);
 String new_Value = plain_Byte_Map.get(Integer.toString(temp_Bytes[i]).substring(0, 1))+ temp_String.substring(1);
 temp_Bytes[i] = Byte.valueOf(new_Value);
 }
 }
 return temp_Bytes;
 }
 /*
 * Method used to revert the previously replaced bytes back to
 * to normal. The byte array will go throug an identical procedure
 * as the one performed in the replace bytes method in order to
 * give each byte index the original value of the first index.
 */
 private final static Byte[] revertByteReplacement(Byte[] bytes) {
 Byte[] temp_Bytes = Arrays.copyOf(bytes, bytes.length);
 for (int i = 0; i < temp_Bytes.length; i++) {
 if (Integer.toString(temp_Bytes[i]).charAt(0) != '-') {
 String temp_String = String.valueOf(temp_Bytes[i]);
 String new_Value = key_Byte_Map.get(Integer.toString(temp_Bytes[i]).substring(0, 1))+ temp_String.substring(1);
 temp_Bytes[i] = Byte.valueOf(new_Value);
 }
 }
 return temp_Bytes;
 }
 /*
 * Method used to swapp the elements of the input array.
 * The elements will be swapped using 3 nested loops with
 * different swap indexes. The elements are swapped around
 * millions of times.
 */
 private final static byte[] swapBytes(byte[] bytes){
 for(int i1 = 0; i1<bytes.length-swap_index_1; i1++){
 byte temp = bytes[i1];
 bytes[i1] = bytes[i1+swap_index_1];
 bytes[i1+swap_index_1] = temp;
 for(int i2 = 0; i2<bytes.length-swap_index_2; i2++){
 byte temp2 = bytes[i2];
 bytes[i2] = bytes[i2+swap_index_2];
 bytes[i2+swap_index_2] = temp2;
 for(int i3 = swap_index_4; i3<bytes.length; i3++){
 byte temp3 = bytes[i3];
 bytes[i3] = bytes[i3-swap_index_4];
 bytes[i3-swap_index_4] = temp3;
 }
 }
 }
 return bytes;
 }
 /*
 * Method used to swapp the elements which were previously swapped
 * by the swapBytes method back to their original index. The swap
 */
 private final static byte[] unSwapBytes(byte[] bytes){
 for (int i1 = bytes.length - (swap_index_1+1); i1 >= 0; i1--) {
 for (int i2 = bytes.length - (swap_index_2+1); i2 >= 0; i2--) {
 for (int i3 = bytes.length - 1; i3 >= (swap_index_4); i3--) {
 byte temp3 = bytes[i3];
 bytes[i3] = bytes[i3 - swap_index_4];
 bytes[i3 - swap_index_4] = temp3;
 }
 byte temp2 = bytes[i2];
 bytes[i2] = bytes[i2 + swap_index_2];
 bytes[i2 + swap_index_2] = temp2;
 }
 byte temp = bytes[i1];
 bytes[i1] = bytes[i1 + swap_index_1];
 bytes[i1 + swap_index_1] = temp;
 }
 return bytes;
 }
 /**
 * Reverses the byte array for further increase obfuscation.
 */
 private final static byte[] revertBytes(Byte[] encryption){
 Byte[] byte_Array = encryption;
 List<Byte> byte_List = Arrays.asList(byte_Array);
 Collections.reverse(byte_List);
 return EncryptionUtils.toPrimitives(replaceBytes(byte_Array));
 }
 /**
 * Reverses the byte array to its original state
 */
 private final static byte[] revertBytesBack(Byte[] encryption){
 Byte[] byte_Array = encryption;
 List<Byte> byte_List = Arrays.asList(byte_Array);
 Collections.reverse(byte_List);
 return EncryptionUtils.toPrimitives(revertByteReplacement(byte_Array));
 }
 /*
 * Method which checks the security level required by the user
 * and base on the specifications it will adjust the amount of characters per character
 * which are to be added to the encrypted message. The higher the security level the
 * higher the number of added characters and vice versa.
 */
 private final static void setSecurityLevel(String password, SecurityLevel security){
 if(security!=null){
// SecureRandom rand = new SecureRandom();
// rand.setSeed(password.getBytes(format));
 switch(security){
 case LOW:
 max_additions = 1;
 insertion_index = 0;
 break;
 case MEDIUM:
 max_additions = 4;
 insertion_index = 3;
 break;
 case HIGH:
 max_additions = 6;
 insertion_index = 2;
 break;
 case VERY_HIGH:
 max_additions = 10;
 insertion_index = 7;
 break;
 default:
 break;
 }
 }
 }
 /**
 * <h1>Encrypted Message</h1>
 *
 * This class is used as a wrapper containing both
 * the code of the actual stringString and case data of
 * said stringString.
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
 private static class EncryptedMessage{
 private final String code_message;
 private final String case_message;
 public EncryptedMessage(char[] codeX, char[] caseX){
 this.code_message = String.valueOf(codeX);
 this.case_message = String.valueOf(caseX);
 }
 public final String getMessage(){
 return code_message;
 }
 public final String getCase(){
 return case_message;
 }
 public final char[] getCharMessage(){
 return code_message.toCharArray();
 }
 public final char[] getCharCase(){
 return case_message.toCharArray();
 }
 }
 /**
 * <h1>Encryption Utility</h1>
 *
 * This class contains various functions used by the program.
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
 privatepublic static class EncryptionUtils{
 /*
 * Method which converts an Object byte array to a primitive type.
 */
 private static byte[] toPrimitives(Byte[] byte_Object){
 byte[] bytes = new byte[byte_Object.length];
 int i = 0;
 for(Byte byte_Objects : byte_Object)bytes[i++] = byte_Objects;
 return bytes;
 }
 /*
 * Method which converts a primitive byte array to an object byte array.
 */
 private static Byte[] toByteObject(byte[] byte_prime) {
 Byte[] bytes = new Byte[byte_prime.length];
 int i = 0;
 for (byte byte_Primes : byte_prime) bytes[i++] = byte_Primes;
 return bytes;
 }
 /*
 * Method which converts an Object byte array to a primitive type.
 */
 @SuppressWarnings("unused")
 private static char[] toCharPrimitive(Character[] char_Object){
 char[] chars = new char[char_Object.length];
 int i = 0;
 for(Character char_Objects : char_Object)chars[i++] = char_Objects;
 return chars;
 }
 /*
 * Method which converts a primitive byte array to an object byte array.
 */
 @SuppressWarnings("unused")
 private static Character[] toCharObject(char[] char_prime) {
 Character[] chars = new Character[char_prime.length];
 int i = 0;
 for (char chars_Primes : char_prime) chars[i++] = chars_Primes;
 return chars;
 }
 /*
 * Method which prints the content of a byte array.
 */
 privatepublic static String printBytes(byte[] binaryEncription){
  if(binaryEncription!=null){
 return new String(binaryEncription, format);
 }
 else
 return "";
 }
 /*
 * Method which splits a stringString at a given character sequence
 * and returns List made out of all the sections.
 */
 private static List<String> fromStringToList(String list, String sequence) {
 return Arrays.asList(list.split(sequence));
 }
 /*
 * Method which generates a secure random within a
 * given range.
 */
 private static int getRandom(int value){
 SecureRandom rand = new SecureRandom();
 return rand.nextInt(value);
 }
 /*
 * Method which generates a secure random within a
 * given interval.
 */
 private static int getRandomInterval(int minValue, int maxValue) {
 SecureRandom rand = new SecureRandom();
 return rand.nextInt(maxValue + 1 - minValue) + minValue;
 }
 /*
 * Method which returns a random stringString of the specified
 * lenght containing a non random element located at the given index.
 */
 private static String getRandomString(int length, char code, int index){
 char[] randomString = new char[length];
 for(int i = 0;i<length; i++){
 randomString[i] =added[getRandom(added.length)];
 if(i==index){
 randomString[i] = code;
 }
 }
 return String.valueOf(randomString);
 }
 /*
 * Method which returns a radom stringString of the specified
 * lenght.
 */
 @SuppressWarnings("unused")
 private static String getRandomString(int length){
 char[] randomString = new char[length];
 for(int i = 0;i<length; i++){
 randomString[i] =added[getRandom(added.length)];
 }
 return String.valueOf(randomString);
 }

 /*
 * Method which checks if a char array contains any duplicate values
 */
 public static boolean containsDuplicates(final char[] chars) {
 final int max_size = 99999;
 BitSet bitset = new BitSet(max_size + 1);
 bitset.set(0, max_size, false);
 for (int item : chars) {
 if (!bitset.get(item)) {
 bitset.set(item, true);
 } else
 return true;
 }
 return false;
 }
 }
 /**
 * Class which is in charge of generating new unique keys based on the
 * the given password and character set if any. Each
 * @author Eudy Contreras
 *
 */
 private static class KeyGenerator {
 private char[] char_key_set;
 private char[] char_base_set;
 private String[] byte_key_set;
 private String[] byte_base_set;
 private SecureRandom charRandom = new SecureRandom();
 private SecureRandom byteRandom = new SecureRandom();
 public KeyGenerator(String password, char[] charSet, String[] byteSet) {
 this.generateKey(password,charRandom,charSet);
 this.generateKey(password,byteRandom,byteSet);
 this.shuffle(char_key_set,charRandom,ShuffelMethod.RICHARD_DURSTENFELD_SHUFFLE);
 this.shuffle(byte_key_set,byteRandom);
 }
 /*
 * Creates a new key based on a given password. The password given will
 * always reproduce the same key if combined with the same set of
 * characters.
 */
 private void generateKey(String password,SecureRandom charRandom, char[] baseChars) {
 charRandom.setSeed(password.getBytes(format));
 char_base_set = new char[baseChars.length];
 char_base_set = Arrays.copyOf(baseChars, baseChars.length);
 char_key_set = new char[char_base_set.length];
 char_key_set = Arrays.copyOf(char_base_set, baseChars.length);
 }
 private void generateKey(String password, SecureRandom byteRandom, String[] baseBytes) {
 byteRandom.setSeed(password.getBytes(format));
 byte_base_set = new String[baseBytes.length];
 byte_base_set = Arrays.copyOf(baseBytes, baseBytes.length);
 byte_key_set = new String[byte_base_set.length];
 byte_key_set = Arrays.copyOf(byte_base_set, baseBytes.length);
 }
 /*
 * Method which securely shuffles an array using different conventional
 * methods
 */
 private void shuffle(char[] char_key,SecureRandom charRandom, ShuffelMethod method) {
 switch (method) {
 case FISHER_YATES_SHUFFLE:
 int index;
 for (int i = char_key.length - 1; i > 0; i--) {
 index = charRandom.nextInt(i + 1);
 if (index != i) {
 char_key[index] ^= char_key[i];
 char_key[i] ^= char_key[index];
 char_key[index] ^= char_key[i];
 }
 }
 break;
 case RICHARD_DURSTENFELD_SHUFFLE:
 for (int i = char_key.length - 1; i > 0; i--) {
 index = charRandom.nextInt(i + 1);
 char temp = char_key[index];
 char_key[index] = char_key[i];
 char_key[i] = temp;
 }
 break;
 default:
 break;
 }
 }
 /*
 * Method which securely shuffles an array using different conventional
 * methods
 */
 private void shuffle(String[] byte_key, SecureRandom byteRandom) {
 int index;
 for (int i = byte_key.length - 1; i > 0; i--) {
 index = byteRandom.nextInt(i + 1);
 String temp = byte_key[index];
 byte_key[index] = byte_key[i];
 byte_key[i] = temp;
 }
 }
 public enum ShuffelMethod {
 FISHER_YATES_SHUFFLE, RICHARD_DURSTENFELD_SHUFFLE,
 }
 public char[] getBase_key() {
 return char_base_set;
 }
 public String[] getBase_Byte() {
 return byte_base_set;
 }
 public char[] getNew_Key() {
 return char_key_set;
 }
 public String[] getNew_Byte() {
 return byte_key_set;
 }
 }
 /**
 * Password class used by the String Encryption Utility
 * the pass word must contain at least 6 character.
 * @author Eudy Contreras
 *
 */
 public static class Password{
 private String password;
 public Password(String password){
 this.password = password;
 }
 private String getPassword(){
 return password;
 }
 private boolean isPasswordOk(){
 return password.length()>=6 && password!=null;
 }
 }
 public enum SecurityLevel{
 LOW,MEDIUM,HIGH,VERY_HIGH
 }
 private static class InvalidPasswordException extends Exception {
 private static final long serialVersionUID = 1L;
 public InvalidPasswordException(String message) {
 super(message);
 System.err.println(this.getMessage());
 System.err.println("Please look at the documentation for more information");
 }
 }
 private static class InvalidCharacterSetException extends Exception {
 private static final long serialVersionUID = 1L;
 public InvalidCharacterSetException(String message) {
 super(message);
 System.err.println(this.getMessage());
 System.err.println("Please look at the documentation for more information");
 }
 }
 public static void main(String[] args) {
// EncryptionUtils.getRandomString(10 char[] new_char_set =
 {'D',' ','F','G','H','Ä','U','J',
 'A','L','Z','Å','N',',','P','Q',
 'W','S','T','Ö',1)'.','V','R','X',
 'Y','M','!','B','O','4','6','1',
 '8','3','2','9','0','5','7','E',
 'C','?','I','K','$','/','@','*'};
 long encrypt_start_time = System.currentTimeMillis();
 byte[] encryption = StringEncrypter.encrypt("What"Your message is upnow secure!!", Notnew muchPassword("password"),new_char_set, why??"SecurityLevel.MEDIUM);
 long encrypt_end_time = System.currentTimeMillis();
 System.out.println("Encryption speed: "+(encrypt_end_time - encrypt_start_time)+ " Milliseconds");

 System.out.println("Actual encrypted message:");
 System.out.println("////////////////////////////////////////////////////////////////////////////////");
 System.out.println("");
 System.out.println(EncryptionUtils.printBytes(encryption));
 System.out.println("");
 System.out.println("////////////////////////////////////////////////////////////////////////////////");

// System.out.println(Arrays.toString(encryption));
 long decrypt_start_time = System.currentTimeMillis();
 System.out.println(StringEncrypter.decrypt(encryption,new Password("password"),new_char_set,SecurityLevel.MEDIUM));
 long decrypt_end_time = System.currentTimeMillis();
 System.out.println("Decryption speed: "+(decrypt_end_time - decrypt_start_time)+ " Milliseconds");
 }
}

I know the code is long but I tried to documented well and structure it to make easy to read. I sincerely appreciate all your time and I hope my question is well formulated and on topic.

import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
 * <h1>String Encrypter</h1>
 *
 * This programs allows you encrypt a string and store as a byte array.
 * the program provides a simple encryption set of methods which make use of
 * scrambling/adding/replacing/swapping/ the core structure of the string.
 * The encrypted message is the store as byte array object which can be sent through sockets
 * or stored locally. In order to be able to view the content of the string the object
 * must be passed through the decrypt method of this program which will format and reconstruc the
 * string to it's original state.
 *
 * If the message is infiltrated while stored as an encrypted byte array whether if it is traveling
 * through a socket or store locally on a system. the thief wont be able to see
 * the content of the message without the key used by this class
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
public class StringEncrypter {
 private final static Charset format = Charset.forName("UTF-8");
 private final static char[] plain =
  {'A','B','C','D','E','F','G','H',
 'I','J','K','L','M','N','O','P',
 'Q','R','S','T','U','V','W','X',
 'Y','Z','Ö','Ä','Å','0','1','2',
 '3','4','5','6','7','8','9',' ',
 ',','?','.','!'};

 private final static char[] key =
 {'D',' ','F','G','H','Ä','U','J',
  'A','L','Z','Å','N',',','P','Q',
 'W','S','T','Ö','.','V','R','X',
 'Y','M','!','B','O','4','6','1',
 '8','3','2','9','0','5','7','E',
 'C','?','I','K'};
 private final static char[] added =
 {'L','3','5','G','0','Ä','1','0',
 'A','D','9','Å','N','C','0','Y',
 'W','S','8','Ö','4','V','4','1',
 'Q','7','K','6','O','3','6','X',
 '8','3','2','9','0','5','7'};
 private final static String[] byte_Plain =
 {"1","2","3","4","5","6","7","8","9","0"};
 private final static String[] byte_Key =
 {"8","0","5","4","9","6","1","3","7","2"};

 private final static Map<Character, Character> plain_Map;
 static
 {
  plain_Map = new HashMap<Character, Character>();
 for(int i = 0; i<plain.length; i++){
 plain_Map.put(plain[i],key[i]);
 }
 }

 private final static Map<Character, Character> key_Map;
 static
 {
  key_Map = new HashMap<Character, Character>();
 for(int i = 0; i<plain.length; i++){
 key_Map.put(key[i],plain[i]);
 }
 }
 private static Map<String, String> plain_Byte_Map;
 static
 {
  plain_Byte_Map = new HashMap<String, String>();
 for(int i = 0; i<byte_Plain.length; i++){
  plain_Byte_Map.put(byte_Plain[i],byte_Key[i]);
 }
 }
 private final static Map<String, String> key_Byte_Map;
 static
 {
 key_Byte_Map = new HashMap<String, String>();
 for(int i = 0; i<byte_Plain.length; i++){
 key_Byte_Map.put(byte_Key[i],byte_Plain[i]);
 }
 }
 /**
 * This values determined the swap indexes at which the swapping methods
 * will operate.
 */
 private final static int swap_index_1 = 2;
 private final static int swap_index_2 = 6;
 private final static int swap_index_3 = 4;
 private final static int swap_index_4 = 3;

 /*
 * The higher the number the more random characters will be added to the encryption.
 * The number set here will affect the performace of the application. The higher the
 * number the lower the performance will be but the more populated with random characters
 * he encryption will be.
 */
 private final static int max_additions = 6;

 /*
 * The index in which the actually code character will be added too
 * the index must be a number between 0 and max_additions-1.
 */
 private final static int insertion_index = 2;
 /**
 * Method used for encrypting a string. The String passed through
 * this method will be encrypted and returned as byte array.
 * The string will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the string are kept
 * private static and secure.
 *
 * @param message String message which you wish to encrypt.
 * @return Returns the string given string as an encrypted byte array.
 */
 public static byte[] encrypt(String message){
 return encrypt(message,null,null,null);
 }
 /**
 * Method used for encrypting a string. The String passed through
 * this method will be encrypted and returned as byte array.
 * The string will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the string are kept
 * private and secure.
 * This method allows the input of a custom key set to be used
 * by this program in replacement of the originals. The key must contain all letters of the
 * swedish dictionary as well as a space character represented as
  * a character with a space in between and the standard comma sign.
 *
 * <h1>Knowing the key used by this program is not enough in order
 * to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param message String message which you wish to encrypt.
 * @param new_Key :The key to be passed as a new replacement key. The key set must * be 44 characters long and cannot contain duplicates. If the key is
 * not 44 characters long it will simply be ignore and not used. The key
  * must contain the standard comma, period, question mark, exclamation mark
 * as well as the space chararcter ' '.
 * @return Returns the string given string as an encrypted byte array.
 */
 public static byte[] encrypt(String message,char[]new_Key){
 return encrypt(message,null,new_Key,null);
 }
 /**
 * Method used for encrypting a string. The String passed through
 * this method will be encrypted and returned as byte array.
 * The string will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the string are kept
 * private and secure.
 * This method allows the input of a custom character set and a key set to be used
 * by this program in replacement of the originals. The character sets passed through
 * this constructor cannot contain any duplicates.
 * <p>
 * <h1>The character set and the key set must be
  * of equal lenghts and neither the character set nor the key may have repeating elements.
 * Every element found in the character set must be present in the key set and most preferably
 * at a different index<h1>
  * <p>
  * <h1>Knowing either the chararcter set or the key used by this program doest not garantee
 * the ability to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param message String message which you wish to encrypt.
 * @param new_CharSet :The new character set to be passed as a new chararcter set. The character
  * set cannot contain duplicates.
 * @param new_Key :The key to be passed as a new replacement key. The key set must contain
 * all the characters present in the character set and cannot contain duplicates
 * @return Returns the string given string as an encrypted byte array.
 */
 public static byte[] encrypt(String message, char[] new_CharSet, char[]new_Key){
 return encrypt(message,new_CharSet,new_Key,null);
 }
 /**
 * Method used for encrypting a string. The String passed through
 * this method will be encrypted and returned as byte array.
 * The string will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the string are kept
 * private and secure.
 * This method allows the input of a custom character set, key set and Byte key to be used
 * by this program in replacement of the originals. The character sets passed through
 * this constructor cannot contain any duplicates.
 * <p>
 * <h1>The character set and the key set must be * of equal lenghts and neither the character set nor the key may have repeating elements.
 * Every element found in the character set must be present in the key set and most preferably
 * at a different index<h1>
 * <p>
 * <h1>Knowing either the chararcter set or the key used by this program doest not garantee
 * the ability to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * The byte key must contain 10 unique digits with numbers
 * from 0 to 9 in any desired order.
 *
 * <h1>Knowing the byte key used by this program is not enough in order
 * to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param message String message which you wish to encrypt.
 * @param new_CharSet :The new character set to be passed as a new chararcter set. The character
 * set cannot contain duplicates.
 * @param new_Key :The key to be passed as a new replacement key. The key set must contain
 * all the characters present in the character set and cannot contain duplicates
 * @param new_byte_Key :The key to be passed as a new replacement key.
 * The key set mus be 10 characters long and cannot contain duplicates.
 * @return Returns the string given string as an encrypted byte array.
 */
 public static byte[] encrypt(String message, char[] new_CharSet, char[]new_Key, String[] new_byte_Key){
 setCharset_setKey_setByteKey(new_CharSet,new_Key,new_byte_Key);
 String cypher = addRandom(message).toString();
 byte[] encryption = cypher.getBytes(format);
 byte[] swapped_Bytes = revertBytes(EncryptionUtils.toByteObject(encryption));
 return swapBytes(swapped_Bytes);
 }
 /**
 * Method used for decrypting a string in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content
 *
 * @param encryption :byte array containing the encrypted string.
 * @return :Returns a decypted string.
 */
 public static String decrypt(byte[] encryption){
 return decrypt(encryption,null,null,null);
 }

 /**
 * Method used for decrypting a string in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 * This method allows the input of a custom key set to be used
 * by this program in replacement of the originals. The key must contain all letters of the
 * swedish dictionary as well as a space character represented as
  * a character with a space in between and the standard comma sign.
 *
 * <h1>Knowing the key used by this program is not enough in order * to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param encryption :byte array containing the encrypted string.
 * @param new_Key :The key to be passed as a new replacement key. The key set must
 * be 44 characters long and cannot contain duplicates. If the key is
 * not 44 characters long it will simply be ignore and not used. The key
 * must contain the standard comma, period, question mark, exclamation mark
 * as well as the space chararcter ' '.
 * @return Returns a decypted string.
 */
 public static String decrypt(byte[] encryption, char[] new_Key){
 return decrypt(encryption,null,new_Key,null);
 }
 /**
 * Method used for decrypting a string in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 *
 * This method allows the input of a custom character set and a key set to be used
 * by this program in replacement of the originals. The character sets passed through
 * this constructor cannot contain any duplicates.
  * <p>
 * <h1>The character set and the key set must be
 * of equal lenghts and neither the character set nor the key may have repeating elements. * Every element found in the character set must be present in the key set and most preferably
 * at a different index<h1>
 * <p>
  * <h1>Knowing either the chararcter set or the key used by this program doest not garantee
 * the ability to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param encryption :byte array containing the encrypted string.
 * @param new_CharSet :The new character set to be passed as a new chararcter set. The character
 * set cannot contain duplicates.
 * @param new_Key :The key to be passed as a new replacement key. The key set must contain
 * all the characters present in the character set and cannot contain duplicates
 * @return Returns a decypted string.
 */
 public static String decrypt(byte[] encryption, char[] new_CharSet, char[]new_Key){
 return decrypt(encryption,new_CharSet,new_Key,null);
 }
 /**
 * Method used for decrypting a string in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 *
 * This method allows the input of a custom character set, key set and Byte key to be used
 * by this program in replacement of the originals. The character sets passed through
 * this constructor cannot contain any duplicates.
 * <p>
 * <h1>The character set and the key set must be
 * of equal lenghts and neither the character set nor the key may have repeating elements.
 * Every element found in the character set must be present in the key set and most preferably
 * at a different index<h1>
 * <p>
 * <h1>Knowing either the chararcter set or the key used by this program doest not garantee
 * the ability to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * The byte key must contain 10 unique digits with numbers
 * from 0 to 9 in any desired order.
 *
 * <h1>Knowing the byte key used by this program is not enough in order
 * to decode the content of the strings encrypted by this program!</h1>
 * <p>
 * @param encryption :byte array containing the encrypted string.
 * @param new_CharSet :The new character set to be passed as a new chararcter set. The character
 * set cannot contain duplicates.
 * @param new_Key :The key to be passed as a new replacement key. The key set must contain
 * all the characters present in the character set and cannot contain duplicates
 * @param new_byte_Key :The key to be passed as a new replacement key.
 * The key set mus be 10 characters long and cannot contain duplicates.
 * @return Returns a decypted string.
 */
 public static String decrypt(byte[] encryption, char[] new_CharSet, char[]new_Key, String[] new_byte_Key){
 setCharset_setKey_setByteKey(new_CharSet,new_Key,new_byte_Key);
 byte[] unswapped_Bytes = revertBytesBack(EncryptionUtils.toByteObject(unSwapBytes(encryption)));
 List<String> list = EncryptionUtils.fromStringToList(new String(unswapped_Bytes, format),", ");
 EncryptedMessage unScrambled = removeRandom(list);
 String decyphered = revertSubstitution(unScrambled);
 return decyphered;
 }
 private static void setCharset_setKey_setByteKey(char[] new_CharSet, char[]new_Key, String[] new_byte_Key){
 if(new_Key!=null && new_CharSet!=null && new_Key.length == new_CharSet.length){
 key_Map.clear();
 plain_Map.clear();
 for(int i = 0; i<new_CharSet.length; i++){
 key_Map.put(new_Key[i],new_CharSet[i]);
 plain_Map.put(new_CharSet[i], new_Key[i]);
 }
 }
  else if(new_Key!=null && new_CharSet==null && new_Key.length==plain.length){
 key_Map.clear();
 for(int i = 0; i<key.length; i++){
 key_Map.put(new_Key[i],plain[i]);
 }
 }
 if(new_byte_Key!=null && new_byte_Key.length==byte_Plain.length){
 key_Byte_Map.clear();
 for(int i = 0; i<byte_Plain.length; i++){
 key_Byte_Map.put(new_byte_Key[i],byte_Plain[i]);
 }
 }
 }
 /*
 * Method used to swapp the elements of the input array.
 * The elements will be swapped using 4 nested loops with
 * different swap indexes. The elements are swapped around
 * millions of times
 */
 private static char[] swapCharacters(char[] chars){
 for(int i1 = 0; i1<chars.length-swap_index_1; i1++){
 char temp = chars[i1];
 chars[i1] = chars[i1+swap_index_1];
 chars[i1+swap_index_1] = temp;
 for(int i2 = 0; i2<chars.length-swap_index_2; i2++){
 char temp2 = chars[i2];
 chars[i2] = chars[i2+swap_index_2];
 chars[i2+swap_index_2] = temp2;
 for(int i3 = 0; i3<chars.length-swap_index_3; i3++){
 char temp3 = chars[i3];
 chars[i3] = chars[i3+swap_index_3];
 chars[i3+swap_index_3] = temp3;
 for(int i4 = swap_index_4; i4<chars.length; i4++){
 char temp4 = chars[i4];
 chars[i4] = chars[i4-swap_index_4];
 chars[i4-swap_index_4] = temp4;
 }
 }
 }
 }
 return chars;
 }
 /*
 * Method used to swapp the elements which were previously swapped
 * by the swapCharacters method back to their original index. The swap
 */
 private static char[] revertCharacterSwap(char[] chars) {
 for (int i1 = chars.length - (swap_index_1+1); i1 >= 0; i1--) {
 for (int i2 = chars.length - (swap_index_2+1); i2 >= 0; i2--) {
 for (int i3 = chars.length - (swap_index_3+1); i3 >= 0; i3--) {
 for (int i4 = chars.length - 1; i4 >= (swap_index_4); i4--) {
 char temp4 = chars[i4];
 chars[i4] = chars[i4 - swap_index_4];
 chars[i4 - swap_index_4] = temp4;
 }
 char temp3 = chars[i3];
 chars[i3] = chars[i3 + swap_index_3];
 chars[i3 + swap_index_3] = temp3;
 }
 char temp2 = chars[i2];
 chars[i2] = chars[i2 + swap_index_2];
 chars[i2 + swap_index_2] = temp2;
 }
 char temp = chars[i1];
 chars[i1] = chars[i1 + swap_index_1];
 chars[i1 + swap_index_1] = temp;
 }
 return chars;
 }
 /*
 * Method which swaps the elements match to the character set
 * whith the correspondnt key element. The method will also create
 * an array holing information about the case of each character. The method
 * will also perform a character swap with a call to the swapCharacters method. After
 * the process is completed this method will return a set of characters holding the
 * coded message along with a set of characters holding case information. The
 * two are divided by a special sequence of symbols in order to distinguish the
 * the two. The return message will then be passed further for further encryption.
 */
 private final static EncryptedMessage applySubstitution(char[] message) {
 char[] case_Binary = new char[message.length];
 char[] code_Message = new char[message.length];
 for(int i = 0; i < message.length; i++) {
 if (Character.isUpperCase(message[i])) {
 case_Binary[i] = '1';
 }
 if (Character.isLowerCase(message[i])) {
 case_Binary[i] = '0';
 }
 code_Message[i] = Character.toUpperCase(message[i]);
 if(plain_Map.containsKey(code_Message[i])){
 code_Message[i] = plain_Map.get(code_Message[i]);
 }
 }
 return new EncryptedMessage(swapCharacters(code_Message),case_Binary);
 }
 /*
 * Method which reverts the character substitution performed by the
 * applySubstitution. It does this by reverting the pattern in which the substitution
 * was made. This will separate and analyze the message along with the case data
 * and once this is done it will also peform a call to the revertCharacterSwap method
 * in order to also unswap the order of the characters to their original state.
 * Once the substitution and the character swap has been reversed it wil further
 * analyze case data determine the case of each character. Upon completion it
 * will return the decrypted message.
 */
 private final static String revertSubstitution(EncryptedMessage message) {
 char[] code_Message = revertCharacterSwap(message.getCharMessage());
 char[] case_Message = message.getCharCase();
 for (int i = 0; i < code_Message.length; i++) {
 if(key_Map.containsKey(code_Message[i])){
 code_Message[i] = key_Map.get(code_Message[i]);
 }
 if (case_Message[i] == '1') {
 code_Message[i] = Character.toUpperCase(code_Message[i]);
 }
 if (case_Message[i] == '0') {
 code_Message[i] = Character.toLowerCase(code_Message[i]);
 }
 }
 return String.valueOf(code_Message);
 }
 /*
 * Method used to further increases the obsfuscation level of the message by adding
 * random numbers and characters to the body of the already encrypted message. This
 * is done at key places of the message in order to allow the substraction of the oginal
 * version of the encryption witout having to deal with the extrac characters and numbers
 * added by this function. The function a
 * the process can then be reversed with an additional key.
 */
 private final static LinkedList<String> addRandom(String code) {
 LinkedList<String> cypherList = new LinkedList<>();
 EncryptedMessage case_and_code = applySubstitution(code.toCharArray());
 String code_message = case_and_code.getMessage();
 String code_case = case_and_code.getCase();
 for (int index = 0; index < code_message.length(); index++) {
 cypherList.add(EncryptionUtils.getRandomString(max_additions,code_message.charAt(index),insertion_index));
 }

 cypherList.addFirst("" + (EncryptionUtils.getRandomInterval(100,999)));
 cypherList.add(String.valueOf(code_case) + EncryptionUtils.getRandom(10));
 return cypherList;
 }
 /*
 * Method used to remove all previously added obsfuscation elements. The method
 * will loop through the values of a given list and it will filter the orignal's
 * message values into their respective char arrays, one holding the code and the
 * othe holding the case related data.
 */
 private final static EncryptedMessage removeRandom(List<String> cypher_List) {
 StringBuilder string_Builder = new StringBuilder();
 char[] case_message = new char[cypher_List.size()- 2];
 char[] code_message = new char[cypher_List.size()-1];
 for (int index = 0; index < cypher_List.size() - 1; index++) {
 if (index >= 1)
 string_Builder.append(String.valueOf(cypher_List.get(index).toCharArray()[insertion_index]));
 if (index < case_message.length)
 case_message[index] = cypher_List.get(cypher_List.size() - 1).toCharArray()[index];
 }

 code_message = string_Builder.toString().toCharArray();
 return new EncryptedMessage(code_message, case_message);
 }
 /*
 * Method used to further encrypt the message by replacing the
 * first first digit of every value on every index of the byte array
 * except for indexes that hold a negative value. This method converts
 * the byte value to string which is than formated and casted back to
 * a byte. A modification can be perform that may allow each index to
 * be replace using a numerical value check!
 */
 private final static Byte[] replaceBytes(Byte[] bytes) {
 Byte[] temp_Bytes = Arrays.copyOf(bytes, bytes.length);
 for (int i = 0; i < temp_Bytes.length; i++) {
 if (Integer.toString(temp_Bytes[i]).charAt(0) != '-') {
 String temp_String = String.valueOf(temp_Bytes[i]);
 String new_Value = plain_Byte_Map.get(Integer.toString(temp_Bytes[i]).substring(0, 1))+ temp_String.substring(1);
 temp_Bytes[i] = Byte.valueOf(new_Value);
 }
 }
 return temp_Bytes;
 }
 /*
 * Method used to revert the previously replaced bytes back to
 * to normal. The byte array will go throug an identical procedure
 * as the one performed in the replace bytes method in order to
 * give each byte index the original value of the first index.
 */
 private final static Byte[] revertByteReplacement(Byte[] bytes) {
 Byte[] temp_Bytes = Arrays.copyOf(bytes, bytes.length);
 for (int i = 0; i < temp_Bytes.length; i++) {
 if (Integer.toString(temp_Bytes[i]).charAt(0) != '-') {
 String temp_String = String.valueOf(temp_Bytes[i]);
 String new_Value = key_Byte_Map.get(Integer.toString(temp_Bytes[i]).substring(0, 1))+ temp_String.substring(1);
 temp_Bytes[i] = Byte.valueOf(new_Value);
 }
 }
 return temp_Bytes;
 }
 /*
 * Method used to swapp the elements of the input array.
 * The elements will be swapped using 3 nested loops with
 * different swap indexes. The elements are swapped around
 * millions of times.
 */
 private final static byte[] swapBytes(byte[] bytes){
 for(int i1 = 0; i1<bytes.length-swap_index_1; i1++){
 byte temp = bytes[i1];
 bytes[i1] = bytes[i1+swap_index_1];
 bytes[i1+swap_index_1] = temp;
 for(int i2 = 0; i2<bytes.length-swap_index_2; i2++){
 byte temp2 = bytes[i2];
 bytes[i2] = bytes[i2+swap_index_2];
 bytes[i2+swap_index_2] = temp2;
 for(int i3 = swap_index_4; i3<bytes.length; i3++){
 byte temp3 = bytes[i3];
 bytes[i3] = bytes[i3-swap_index_4];
 bytes[i3-swap_index_4] = temp3;
 }
 }
 }
 return bytes;
 }
 /*
 * Method used to swapp the elements which were previously swapped
 * by the swapBytes method back to their original index. The swap
 */
 private final static byte[] unSwapBytes(byte[] bytes){
 for (int i1 = bytes.length - (swap_index_1+1); i1 >= 0; i1--) {
 for (int i2 = bytes.length - (swap_index_2+1); i2 >= 0; i2--) {
 for (int i3 = bytes.length - 1; i3 >= (swap_index_4); i3--) {
 byte temp3 = bytes[i3];
 bytes[i3] = bytes[i3 - swap_index_4];
 bytes[i3 - swap_index_4] = temp3;
 }
 byte temp2 = bytes[i2];
 bytes[i2] = bytes[i2 + swap_index_2];
 bytes[i2 + swap_index_2] = temp2;
 }
 byte temp = bytes[i1];
 bytes[i1] = bytes[i1 + swap_index_1];
 bytes[i1 + swap_index_1] = temp;
 }
 return bytes;
 }
 /**
 * Reverses the byte array for further increase obfuscation.
 */
 private final static byte[] revertBytes(Byte[] encryption){
 Byte[] byte_Array = encryption;
 List<Byte> byte_List = Arrays.asList(byte_Array);
 Collections.reverse(byte_List);
 return EncryptionUtils.toPrimitives(replaceBytes(byte_Array));
 }
 /**
 * Reverses the byte array to its original state
 */
 private final static byte[] revertBytesBack(Byte[] encryption){
 Byte[] byte_Array = encryption;
 List<Byte> byte_List = Arrays.asList(byte_Array);
 Collections.reverse(byte_List);
 return EncryptionUtils.toPrimitives(revertByteReplacement(byte_Array));
 }
 /**
 * <h1>Encrypted Message</h1>
 *
 * This class is used as a wrapper containing both
 * the code of the actual string and case data of
 * said string.
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
 private static class EncryptedMessage{
 private final String code_message;
 private final String case_message;
 public EncryptedMessage(char[] codeX, char[] caseX){
 this.code_message = String.valueOf(codeX);
 this.case_message = String.valueOf(caseX);
 }
 public final String getMessage(){
 return code_message;
 }
 public final String getCase(){
 return case_message;
 }
 public final char[] getCharMessage(){
 return code_message.toCharArray();
 }
 public final char[] getCharCase(){
 return case_message.toCharArray();
 }
 }
 /**
 * <h1>Encryption Utility</h1>
 *
 * This class contains various functions used by the program.
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
 private static class EncryptionUtils{
 /*
 * Method which converts an Object byte array to a primitive type.
 */
 private static byte[] toPrimitives(Byte[] byte_Object){
 byte[] bytes = new byte[byte_Object.length];
 int i = 0;
 for(Byte byte_Objects : byte_Object)bytes[i++] = byte_Objects;
 return bytes;
 }
 /*
 * Method which converts a primitive byte array to an object byte array.
 */
 private static Byte[] toByteObject(byte[] byte_prime) {
 Byte[] bytes = new Byte[byte_prime.length];
 int i = 0;
 for (byte byte_Primes : byte_prime) bytes[i++] = byte_Primes;
 return bytes;
 }
 /*
 * Method which prints the content of a byte array.
 */
 private static String printBytes(byte[] binaryEncription){
 return new String(binaryEncription, format);
 }
 /*
 * Method which splits a string at a given character sequence
 * and returns List made out of all the sections.
 */
 private static List<String> fromStringToList(String list, String sequence) {
 return Arrays.asList(list.split(sequence));
 }
 /*
 * Method which generates a secure random within a
 * given range.
 */
 private static int getRandom(int value){
 SecureRandom rand = new SecureRandom();
 return rand.nextInt(value);
 }
 /*
 * Method which generates a secure random within a
 * given interval.
 */
 private static int getRandomInterval(int minValue, int maxValue) {
 SecureRandom rand = new SecureRandom();
 return rand.nextInt(maxValue + 1 - minValue) + minValue;
 }
 /*
 * Method which returns a random string of the specified
 * lenght containing a non random element located at the given index.
 */
 private static String getRandomString(int length, char code, int index){
 char[] randomString = new char[length];
 for(int i = 0;i<length; i++){
 randomString[i] =added[getRandom(added.length)];
 if(i==index){
 randomString[i] = code;
 }
 }
 return String.valueOf(randomString);
 }
 /*
 * Method which returns a radom string of the specified
 * lenght.
 */
 @SuppressWarnings("unused")
 private static String getRandomString(int length){
 char[] randomString = new char[length];
 for(int i = 0;i<length; i++){
 randomString[i] =added[getRandom(added.length)];
 }
 return String.valueOf(randomString);
 }
 }
 public static void main(String[] args) {
// EncryptionUtils.getRandomString(10,'Ö',1);
 long encrypt_start_time = System.currentTimeMillis();
 byte[] encryption = StringEncrypter.encrypt("What is up!!, Not much why??");
 long encrypt_end_time = System.currentTimeMillis();
 System.out.println("Encryption speed: "+(encrypt_end_time - encrypt_start_time)+ " Milliseconds");
 System.out.println("Actual encrypted message:");
 System.out.println("////////////////////////////////////////////////////////////////////////////////");
 System.out.println("");
 System.out.println(EncryptionUtils.printBytes(encryption));
 System.out.println("");
 System.out.println("////////////////////////////////////////////////////////////////////////////////");
// System.out.println(Arrays.toString(encryption));
 long decrypt_start_time = System.currentTimeMillis();
 System.out.println(StringEncrypter.decrypt(encryption));
 long decrypt_end_time = System.currentTimeMillis();
 System.out.println("Decryption speed: "+(decrypt_end_time - decrypt_start_time)+ " Milliseconds");
 }
}

I know the code is long but I tried to documented well and structure it to make easy to read. I sincerely appreciate all your time and I hope my question is well formulated and on topic.

import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
 * <h1>String Encrypter</h1>
 *
 * This programs allows you encrypt a String and store as a byte array.
 * the program provides a simple encryption set of methods which make use of
 * scrambling/adding/replacing/swapping/ the core structure of the String.
 * The encrypted message is the store as byte array object which can be sent through sockets
 * or stored locally. In order to be able to view the content of the String the object
 * must be passed through the decrypt method of this program which will format and reconstruc the
 * String to it's original state.
 *
 * If the message is infiltrated while stored as an encrypted byte array whether if it is traveling
 * through a socket or store locally on a system. the thief wont be able to see
 * the content of the message without the key used by this class
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
public class StringEncrypter {
 private final static Charset format = Charset.forName("UTF-8");
 private static char[] added = {'L','3','5','G','0','Ä','1','0',
 'A','D','9','Å','N','C','0','Y',
 'W','S','8','Ö','4','V','4','1',
 'Q','7','K','6','O','3','6','X',
 '8','3','2','9','0','5','7'};
 /*
 * Meps which hold the encryption base and key data structures.
 */
 private static final Map<Character, Character> plain_Map = new HashMap<Character, Character>();
 private static final Map<Character, Character> key_Map = new HashMap<Character, Character>();
 private static final Map<String, String> plain_Byte_Map = new HashMap<String, String>();
 private static final Map<String, String> key_Byte_Map = new HashMap<String, String>();
 /**
 * This values determined the swap indexes at which the swapping methods
 * will operate. More swapp indexes may be added for increase security.
 */
 private final static int swap_index_1 = 2;
 private final static int swap_index_2 = 6;
 private final static int swap_index_3 = 4;
 private final static int swap_index_4 = 3;
 /*
 * The higher the number the more random characters will be added to the encryption.
 * The number set here will affect the performace of the application. The higher the
 * number the lower the performance will be but the more populated with random characters
 * he encryption will be.
 * HIgher = more secure but slower.
 * Lower = less secure but faster.
 * recommended: 6
 */
 private static int max_additions = 5;
 /*
 * The index in which the actually code character will be inserted.
 * the index must be a number between 0 and the max_additions value-1.
 */
 private static int insertion_index = 2;
 /**
 * Method used for encrypting a String. The String passed through
 * this method will be encrypted and returned as byte array.
 * The String will go through a series of encryption and obsfuscation
 * methods in order to assure that the contents of the String are kept
 * private and secure.
 * This method allows the input of a custom password to be associated with the
 * generated key. The password will be needed for decryption of Strings
 * which were encrypted using the submitted password.
 * <p>
 * @param message String message which you wish to encrypt.
 * @param password :The password to be associated with the encryption. The password must be at least 6 characters long.
 * The password must be at least 6 characters long.
 * @return Returns the String given String as an encrypted byte array.
 */
 public static byte[] encrypt(String message,Password password){
 return encrypt(message,password,null,null);
 }
 /**
 * Method used for encrypting a String. The String passed through
 * this method will be encrypted and returned as byte array.
 * The String will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the String are kept
 * private and secure.
 * This method allows the input of a custom character set and a password
 * which are to be associated with the generated key. both the password and
 * the submitted character set will be needed for decryption of Strings which were encrypted using the
 * submitted password and character set.
 * <p>
 * @param message String message which you wish to encrypt.
 * @param password :The password to be associated with the encryption. The password must be at least 6 characters long.
 * @param new_CharSet :The character set used by the encrypted String. The character
 * set cannot contain any duplicates and must be at least 40 characters long.
 * @return Returns the String given String as an encrypted byte array.
 */
 public static byte[] encrypt(String message, Password password, char[] new_CharSet){
 return encrypt(message,password,new_CharSet,null);
 }
 /**
 * Method used for encrypting a String. The String passed through
 * this method will be encrypted and returned as byte array.
 * The String will go through a series of encryption and obsfuscation
 * method in order to assure that the contents of the String are kept
 * private and secure.
 * This method allows the input of a custom character set, a password and the security level
 * which is to be associated with the generated key. The password, the security level and
 * the submitted character set will be needed for decryption of Strings which were encrypted using the
 * submitted password, character set and security level.
 * <p>
 * @param message String message which you wish to encrypt.
 * @param password :The password to be associated with the encryption. The password must be at least 6 characters long.
 * @param new_CharSet :The character set used by the encrypted String. The character
 * set cannot contain any duplicates and must be at least 40 characters long.
 * @param security :The level of security which is to be assign to the encrypted message. The higher the security level
 * the higher the level of encryption but also the slower the encryption process will be. The lower the security level
 * the lower the encryption but the faster the encryption will be.
 * @return Returns the String given String as an encrypted byte array.
 */
 public static byte[] encrypt(String message, Password password, char[] new_CharSet, SecurityLevel security){
 if(prepareEncryption(new_CharSet, password, security)){
 String cypher = addRandom(message).toString();
 byte[] encryption = cypher.getBytes(format);
 byte[] swapped_Bytes = revertBytes(EncryptionUtils.toByteObject(encryption));
 return swapBytes(swapped_Bytes);
 }else{
 return null;
 }
 }
 /**
 * Method used for decrypting a String in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 * This method allows the input of the password associated with
 * the encrypted file which is needed in order to be able to view the file.
 * <p>
 * @param encryption :byte array containing the encrypted String.
 * @param password :The password associated to the file. Needed in order
 * to view the file! The password must match the password used to encrypt the file
 * @return :Returns a decypted String.
 */
 public static String decrypt(byte[] encryption, Password password){
 return decrypt(encryption,password,null,null);
 }
 /**
 * Method used for decrypting a String in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 *
 * This method allows the input of the character set and the password
 * associated with the encrypted file. Both the character set and the password
 * are needed in order to view the original String content
 * <p>
 * @param encryption :byte array containing the encrypted String.
 * @param password :The password associated to the file. Needed in order
 * to view the file! The password must match the password used to encrypt the file
 * @param new_CharSet :The character set associated with the encrypted file. * needed in order to view the file! Must match the character set used to encrypt the String
 * @return Returns a decypted String.
 */
 public static String decrypt(byte[] encryption, Password password, char[] new_CharSet){
 return decrypt(encryption,password,new_CharSet,null);
 }
 /**
 * Method used for decrypting a String in the form
 * of a encrypted byte array. The array will go through a series
 * of decryption methods in order to uncover the orignal content.
 *
 * This method allows the input of the character set, the password and the security level
 * associated with the encrypted file. All of the inputs are needed in order to view the original
 * content of the file.
 * <p>
 * @param encryption :byte array containing the encrypted String.
 * @param password :The password associated to the file. Needed in order
  * to view the file! The password must match the password used to encrypt the String.
 * @param new_CharSet :The character set associated with the encrypted file.Must match the character
 * set used to encrypt the String.
 * @param security :The security level which is associated with the encrypted String.Muse match
 * the security level used to encrypt the String.
 * @return Returns a decypted String.
 */
 public static String decrypt(byte[] encryption, Password password, char[] new_CharSet, SecurityLevel security){
 if(prepareEncryption(new_CharSet, password, security)){
 byte[] unswapped_Bytes = revertBytesBack(EncryptionUtils.toByteObject(unSwapBytes(encryption)));
 List<String> list = EncryptionUtils.fromStringToList(new String(unswapped_Bytes, format),", ");
 EncryptedMessage unScrambled = removeRandom(list);
 String decyphered = revertSubstitution(unScrambled);
 return decyphered;
 }
 else{
 return "";
 }
 }
 /*
 * Method incharged of processing the encryption and decryption request made
 * by the user. This method will perform checks on the validity of the password and the character
 * set if any. If both the password and the character set are valid the method will then generate a key
 * and allow the encryption to proceed further.
 */
 private static boolean prepareEncryption(char[] new_CharSet, Password password, SecurityLevel security){
 boolean duplicates = false;
 String[] byte_Plain =
 {"1","2","3","4","5","6","7","8","9","0"};

 char[] plain_char_set =
 {'A','B','C','D','E','F','G','H',  'I','J','K','L','M','N','O','P',
  'Q','R','S','T','U','V','W','X',
 'Y','Z','Ö','Ä','Å','0','1','2',
 '3','4','5','6','7','8','9',' ',
 ',','?','.','!'};
 if(password.isPasswordOk() && new_CharSet!= null) {
 duplicates = EncryptionUtils.containsDuplicates(new_CharSet) ;
  if(!duplicates && new_CharSet.length>=40){
 KeyGenerator keyGen = new KeyGenerator(password.getPassword(),new_CharSet, byte_Plain);
 setSecurityLevel(password.getPassword(), security);
 key_Map.clear();
 plain_Map.clear();
 key_Byte_Map.clear();
 plain_Byte_Map.clear();
 for(int i = 0; i < new_CharSet.length; i++){
 plain_Map.put(keyGen.getBase_key()[i], keyGen.getNew_Key()[i]);
 key_Map.put(keyGen.getNew_Key()[i], keyGen.getBase_key()[i]);
 }
 for (int i = 0; i < byte_Plain.length; i++) {
 plain_Byte_Map.put(keyGen.getBase_Byte()[i], keyGen.getNew_Byte()[i]);
 key_Byte_Map.put(keyGen.getNew_Byte()[i], keyGen.getBase_Byte()[i]);
 }
 return true;
 }
 else if(duplicates && new_CharSet.length>=40){
 new InvalidCharacterSetException("The submitted character set contains duplicates!");

 return false;
 }
 else if(!duplicates && new_CharSet.length<40){
 new InvalidCharacterSetException("The submitted character set does not meet the character amount specification!");
 return false;
 }
 else{
 new InvalidCharacterSetException("The submitted character set contains less than then minimum allow amount of characters!");
 return false;
 }
 }
 else if(password.isPasswordOk() && new_CharSet == null) {
 KeyGenerator keyGen = new KeyGenerator(password.getPassword(),plain_char_set, byte_Plain);
 setSecurityLevel(password.getPassword(), security);
 key_Map.clear();
 plain_Map.clear();
 key_Byte_Map.clear();
 plain_Byte_Map.clear();
 for(int i = 0; i < plain_char_set.length; i++){
 plain_Map.put(keyGen.getBase_key()[i], keyGen.getNew_Key()[i]);
  key_Map.put(keyGen.getNew_Key()[i], keyGen.getBase_key()[i]);
 }
  for (int i = 0; i < byte_Plain.length; i++) {
 plain_Byte_Map.put(keyGen.getBase_Byte()[i], keyGen.getNew_Byte()[i]);
 key_Byte_Map.put(keyGen.getNew_Byte()[i], keyGen.getBase_Byte()[i]);
 }
 return true;
 } else {
 new InvalidPasswordException("The submitted password is not valid");
 return false;
 }
 }
 /*
 * Method used to swapp the elements of the input array.
 * The elements will be swapped using 4 nested loops with
 * different swap indexes. The elements are swapped around
 * millions of times
 */
 private static char[] swapCharacters(char[] chars){
 for(int i1 = 0; i1<chars.length-swap_index_1; i1++){
 char temp = chars[i1];
 chars[i1] = chars[i1+swap_index_1];
 chars[i1+swap_index_1] = temp;
 for(int i2 = 0; i2<chars.length-swap_index_2; i2++){
 char temp2 = chars[i2];
 chars[i2] = chars[i2+swap_index_2];
 chars[i2+swap_index_2] = temp2;
 for(int i3 = 0; i3<chars.length-swap_index_3; i3++){
 char temp3 = chars[i3];
 chars[i3] = chars[i3+swap_index_3];
 chars[i3+swap_index_3] = temp3;
 for(int i4 = swap_index_4; i4<chars.length; i4++){
 char temp4 = chars[i4];
 chars[i4] = chars[i4-swap_index_4];
 chars[i4-swap_index_4] = temp4;
 }
 }
 }
 }
 return chars;
 }
 /*
 * Method used to swapp the elements which were previously swapped
 * by the swapCharacters method back to their original index. The swap
 */
 private static char[] revertCharacterSwap(char[] chars) {
 for (int i1 = chars.length - (swap_index_1+1); i1 >= 0; i1--) {
 for (int i2 = chars.length - (swap_index_2+1); i2 >= 0; i2--) {
 for (int i3 = chars.length - (swap_index_3+1); i3 >= 0; i3--) {
 for (int i4 = chars.length - 1; i4 >= (swap_index_4); i4--) {
 char temp4 = chars[i4];
 chars[i4] = chars[i4 - swap_index_4];
 chars[i4 - swap_index_4] = temp4;
 }
 char temp3 = chars[i3];
 chars[i3] = chars[i3 + swap_index_3];
 chars[i3 + swap_index_3] = temp3;
 }
 char temp2 = chars[i2];
 chars[i2] = chars[i2 + swap_index_2];
 chars[i2 + swap_index_2] = temp2;
 }
 char temp = chars[i1];
 chars[i1] = chars[i1 + swap_index_1];
 chars[i1 + swap_index_1] = temp;
 }
 return chars;
 }
 /*
 * Method which swaps the elements match to the character set
 * whith the correspondnt key element. The method will also create
 * an array holing information about the case of each character. The method
 * will also perform a character swap with a call to the swapCharacters method. After
 * the process is completed this method will return a set of characters holding the
 * coded message along with a set of characters holding case information. The
 * two are divided by a special sequence of symbols in order to distinguish the
 * the two. The return message will then be passed further for further encryption.
 */
 private final static EncryptedMessage applySubstitution(char[] message) {
 char[] case_Binary = new char[message.length];
 char[] code_Message = new char[message.length];
 for(int i = 0; i < message.length; i++) {
 if (Character.isUpperCase(message[i])) {
 case_Binary[i] = '1';
 }
 if (Character.isLowerCase(message[i])) {
 case_Binary[i] = '0';
 }
 code_Message[i] = Character.toUpperCase(message[i]);
 if(plain_Map.containsKey(code_Message[i])){
 code_Message[i] = plain_Map.get(code_Message[i]);
 }
 }
 return new EncryptedMessage(swapCharacters(code_Message),case_Binary);
 }
 /*
 * Method which reverts the character substitution performed by the
 * applySubstitution. It does this by reverting the pattern in which the substitution
 * was made. This will separate and analyze the message along with the case data
 * and once this is done it will also peform a call to the revertCharacterSwap method
 * in order to also unswap the order of the characters to their original state.
 * Once the substitution and the character swap has been reversed it wil further
 * analyze case data determine the case of each character. Upon completion it
 * will return the decrypted message.
 */
 private final static String revertSubstitution(EncryptedMessage message) {
 char[] code_Message = revertCharacterSwap(message.getCharMessage());
 char[] case_Message = message.getCharCase();
 for (int i = 0; i < code_Message.length; i++) {
 if(key_Map.containsKey(code_Message[i])){
 code_Message[i] = key_Map.get(code_Message[i]);
 }
 if (case_Message[i] == '1') {
 code_Message[i] = Character.toUpperCase(code_Message[i]);
 }
 if (case_Message[i] == '0') {
 code_Message[i] = Character.toLowerCase(code_Message[i]);
 }
 }
 return String.valueOf(code_Message);
 }
 /*
 * Method used to further increases the obsfuscation level of the message by adding
 * random numbers and characters to the body of the already encrypted message. This
 * is done at key places of the message in order to allow the substraction of the oginal
 * version of the encryption witout having to deal with the extrac characters and numbers
 * added by this function. The function a
 * the process can then be reversed with an additional key.
 */
 private final static LinkedList<String> addRandom(String code) {
 LinkedList<String> cypherList = new LinkedList<>();
 EncryptedMessage case_and_code = applySubstitution(code.toCharArray());
 String code_message = case_and_code.getMessage();
 String code_case = case_and_code.getCase();
 for (int index = 0; index < code_message.length(); index++) {
 cypherList.add(EncryptionUtils.getRandomString(max_additions,code_message.charAt(index),insertion_index));
 }
 cypherList.addFirst("" + (EncryptionUtils.getRandomInterval(100,999)));
 cypherList.addLast(code_case + EncryptionUtils.getRandomInterval(100,999)+EncryptionUtils.getRandomString(2));
 return cypherList;
 }
 /*
 * Method used to remove all previously added obsfuscation elements. The method
 * will loop through the values of a given list and it will filter the orignal's
 * message values into their respective char arrays, one holding the code and the
 * othe holding the case related data.
 */
 private final static EncryptedMessage removeRandom(List<String> cypher_List) {
 StringBuilder string_Builder = new StringBuilder();
 char[] case_message = new char[cypher_List.get(cypher_List.size()-1).length()-5];
 char[] code_message = new char[cypher_List.size()-1];
 for (int index = 0; index < cypher_List.size() - 1; index++) {
 if (index >= 1){
 try{
 string_Builder.append(String.valueOf(cypher_List.get(index).toCharArray()[insertion_index]));
 }catch(ArrayIndexOutOfBoundsException e){ /*TODO NOTHING*/}
 }
 if (index < case_message.length){
 case_message[index] = cypher_List.get(cypher_List.size() - 1).toCharArray()[index];
 }
 }
 code_message = string_Builder.toString().toCharArray();
 return new EncryptedMessage(code_message, case_message);
 }
 /*
 * Method used to further encrypt the message by replacing the
 * first first digit of every value on every index of the byte array
 * except for indexes that hold a negative value. This method converts
 * the byte value to String which is than formated and casted back to
 * a byte. A modification can be perform that may allow each index to
 * be replace using a numerical value check!
 */
 private final static Byte[] replaceBytes(Byte[] bytes) {
 Byte[] temp_Bytes = Arrays.copyOf(bytes, bytes.length);
 for (int i = 0; i < temp_Bytes.length; i++) {
 if (Integer.toString(temp_Bytes[i]).charAt(0) != '-') {
 String temp_String = String.valueOf(temp_Bytes[i]);
 String new_Value = plain_Byte_Map.get(Integer.toString(temp_Bytes[i]).substring(0, 1))+ temp_String.substring(1);
 temp_Bytes[i] = Byte.valueOf(new_Value);
 }
 }
 return temp_Bytes;
 }
 /*
 * Method used to revert the previously replaced bytes back to
 * to normal. The byte array will go throug an identical procedure
 * as the one performed in the replace bytes method in order to
 * give each byte index the original value of the first index.
 */
 private final static Byte[] revertByteReplacement(Byte[] bytes) {
 Byte[] temp_Bytes = Arrays.copyOf(bytes, bytes.length);
 for (int i = 0; i < temp_Bytes.length; i++) {
 if (Integer.toString(temp_Bytes[i]).charAt(0) != '-') {
 String temp_String = String.valueOf(temp_Bytes[i]);
 String new_Value = key_Byte_Map.get(Integer.toString(temp_Bytes[i]).substring(0, 1))+ temp_String.substring(1);
 temp_Bytes[i] = Byte.valueOf(new_Value);
 }
 }
 return temp_Bytes;
 }
 /*
 * Method used to swapp the elements of the input array.
 * The elements will be swapped using 3 nested loops with
 * different swap indexes. The elements are swapped around
 * millions of times.
 */
 private final static byte[] swapBytes(byte[] bytes){
 for(int i1 = 0; i1<bytes.length-swap_index_1; i1++){
 byte temp = bytes[i1];
 bytes[i1] = bytes[i1+swap_index_1];
 bytes[i1+swap_index_1] = temp;
 for(int i2 = 0; i2<bytes.length-swap_index_2; i2++){
 byte temp2 = bytes[i2];
 bytes[i2] = bytes[i2+swap_index_2];
 bytes[i2+swap_index_2] = temp2;
 for(int i3 = swap_index_4; i3<bytes.length; i3++){
 byte temp3 = bytes[i3];
 bytes[i3] = bytes[i3-swap_index_4];
 bytes[i3-swap_index_4] = temp3;
 }
 }
 }
 return bytes;
 }
 /*
 * Method used to swapp the elements which were previously swapped
 * by the swapBytes method back to their original index. The swap
 */
 private final static byte[] unSwapBytes(byte[] bytes){
 for (int i1 = bytes.length - (swap_index_1+1); i1 >= 0; i1--) {
 for (int i2 = bytes.length - (swap_index_2+1); i2 >= 0; i2--) {
 for (int i3 = bytes.length - 1; i3 >= (swap_index_4); i3--) {
 byte temp3 = bytes[i3];
 bytes[i3] = bytes[i3 - swap_index_4];
 bytes[i3 - swap_index_4] = temp3;
 }
 byte temp2 = bytes[i2];
 bytes[i2] = bytes[i2 + swap_index_2];
 bytes[i2 + swap_index_2] = temp2;
 }
 byte temp = bytes[i1];
 bytes[i1] = bytes[i1 + swap_index_1];
 bytes[i1 + swap_index_1] = temp;
 }
 return bytes;
 }
 /**
 * Reverses the byte array for further increase obfuscation.
 */
 private final static byte[] revertBytes(Byte[] encryption){
 Byte[] byte_Array = encryption;
 List<Byte> byte_List = Arrays.asList(byte_Array);
 Collections.reverse(byte_List);
 return EncryptionUtils.toPrimitives(replaceBytes(byte_Array));
 }
 /**
 * Reverses the byte array to its original state
 */
 private final static byte[] revertBytesBack(Byte[] encryption){
 Byte[] byte_Array = encryption;
 List<Byte> byte_List = Arrays.asList(byte_Array);
 Collections.reverse(byte_List);
 return EncryptionUtils.toPrimitives(revertByteReplacement(byte_Array));
 }
 /*
 * Method which checks the security level required by the user
 * and base on the specifications it will adjust the amount of characters per character
 * which are to be added to the encrypted message. The higher the security level the
 * higher the number of added characters and vice versa.
 */
 private final static void setSecurityLevel(String password, SecurityLevel security){
 if(security!=null){
// SecureRandom rand = new SecureRandom();
// rand.setSeed(password.getBytes(format));
 switch(security){
 case LOW:
 max_additions = 1;
 insertion_index = 0;
 break;
 case MEDIUM:
 max_additions = 4;
 insertion_index = 3;
 break;
 case HIGH:
 max_additions = 6;
 insertion_index = 2;
 break;
 case VERY_HIGH:
 max_additions = 10;
 insertion_index = 7;
 break;
 default:
 break;
 }
 }
 }
 /**
 * <h1>Encrypted Message</h1>
 *
 * This class is used as a wrapper containing both
 * the code of the actual String and case data of
 * said String.
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
 private static class EncryptedMessage{
 private final String code_message;
 private final String case_message;
 public EncryptedMessage(char[] codeX, char[] caseX){
 this.code_message = String.valueOf(codeX);
 this.case_message = String.valueOf(caseX);
 }
 public final String getMessage(){
 return code_message;
 }
 public final String getCase(){
 return case_message;
 }
 public final char[] getCharMessage(){
 return code_message.toCharArray();
 }
 public final char[] getCharCase(){
 return case_message.toCharArray();
 }
 }
 /**
 * <h1>Encryption Utility</h1>
 *
 * This class contains various functions used by the program.
 *
 * @author Eudy Contreras
 * @version 1.1
 * @since 2016年08月16日
 */
 public static class EncryptionUtils{
 /*
 * Method which converts an Object byte array to a primitive type.
 */
 private static byte[] toPrimitives(Byte[] byte_Object){
 byte[] bytes = new byte[byte_Object.length];
 int i = 0;
 for(Byte byte_Objects : byte_Object)bytes[i++] = byte_Objects;
 return bytes;
 }
 /*
 * Method which converts a primitive byte array to an object byte array.
 */
 private static Byte[] toByteObject(byte[] byte_prime) {
 Byte[] bytes = new Byte[byte_prime.length];
 int i = 0;
 for (byte byte_Primes : byte_prime) bytes[i++] = byte_Primes;
 return bytes;
 }
 /*
 * Method which converts an Object byte array to a primitive type.
 */
 @SuppressWarnings("unused")
 private static char[] toCharPrimitive(Character[] char_Object){
 char[] chars = new char[char_Object.length];
 int i = 0;
 for(Character char_Objects : char_Object)chars[i++] = char_Objects;
 return chars;
 }
 /*
 * Method which converts a primitive byte array to an object byte array.
 */
 @SuppressWarnings("unused")
 private static Character[] toCharObject(char[] char_prime) {
 Character[] chars = new Character[char_prime.length];
 int i = 0;
 for (char chars_Primes : char_prime) chars[i++] = chars_Primes;
 return chars;
 }
 /*
 * Method which prints the content of a byte array.
 */
 public static String printBytes(byte[] binaryEncription){
  if(binaryEncription!=null){
 return new String(binaryEncription, format);
 }
 else
 return "";
 }
 /*
 * Method which splits a String at a given character sequence
 * and returns List made out of all the sections.
 */
 private static List<String> fromStringToList(String list, String sequence) {
 return Arrays.asList(list.split(sequence));
 }
 /*
 * Method which generates a secure random within a
 * given range.
 */
 private static int getRandom(int value){
 SecureRandom rand = new SecureRandom();
 return rand.nextInt(value);
 }
 /*
 * Method which generates a secure random within a
 * given interval.
 */
 private static int getRandomInterval(int minValue, int maxValue) {
 SecureRandom rand = new SecureRandom();
 return rand.nextInt(maxValue + 1 - minValue) + minValue;
 }
 /*
 * Method which returns a random String of the specified
 * lenght containing a non random element located at the given index.
 */
 private static String getRandomString(int length, char code, int index){
 char[] randomString = new char[length];
 for(int i = 0;i<length; i++){
 randomString[i] =added[getRandom(added.length)];
 if(i==index){
 randomString[i] = code;
 }
 }
 return String.valueOf(randomString);
 }
 /*
 * Method which returns a radom String of the specified
 * lenght.
 */
 private static String getRandomString(int length){
 char[] randomString = new char[length];
 for(int i = 0;i<length; i++){
 randomString[i] =added[getRandom(added.length)];
 }
 return String.valueOf(randomString);
 }

 /*
 * Method which checks if a char array contains any duplicate values
 */
 public static boolean containsDuplicates(final char[] chars) {
 final int max_size = 99999;
 BitSet bitset = new BitSet(max_size + 1);
 bitset.set(0, max_size, false);
 for (int item : chars) {
 if (!bitset.get(item)) {
 bitset.set(item, true);
 } else
 return true;
 }
 return false;
 }
 }
 /**
 * Class which is in charge of generating new unique keys based on the
 * the given password and character set if any. Each
 * @author Eudy Contreras
 *
 */
 private static class KeyGenerator {
 private char[] char_key_set;
 private char[] char_base_set;
 private String[] byte_key_set;
 private String[] byte_base_set;
 private SecureRandom charRandom = new SecureRandom();
 private SecureRandom byteRandom = new SecureRandom();
 public KeyGenerator(String password, char[] charSet, String[] byteSet) {
 this.generateKey(password,charRandom,charSet);
 this.generateKey(password,byteRandom,byteSet);
 this.shuffle(char_key_set,charRandom,ShuffelMethod.RICHARD_DURSTENFELD_SHUFFLE);
 this.shuffle(byte_key_set,byteRandom);
 }
 /*
 * Creates a new key based on a given password. The password given will
 * always reproduce the same key if combined with the same set of
 * characters.
 */
 private void generateKey(String password,SecureRandom charRandom, char[] baseChars) {
 charRandom.setSeed(password.getBytes(format));
 char_base_set = new char[baseChars.length];
 char_base_set = Arrays.copyOf(baseChars, baseChars.length);
 char_key_set = new char[char_base_set.length];
 char_key_set = Arrays.copyOf(char_base_set, baseChars.length);
 }
 private void generateKey(String password, SecureRandom byteRandom, String[] baseBytes) {
 byteRandom.setSeed(password.getBytes(format));
 byte_base_set = new String[baseBytes.length];
 byte_base_set = Arrays.copyOf(baseBytes, baseBytes.length);
 byte_key_set = new String[byte_base_set.length];
 byte_key_set = Arrays.copyOf(byte_base_set, baseBytes.length);
 }
 /*
 * Method which securely shuffles an array using different conventional
 * methods
 */
 private void shuffle(char[] char_key,SecureRandom charRandom, ShuffelMethod method) {
 switch (method) {
 case FISHER_YATES_SHUFFLE:
 int index;
 for (int i = char_key.length - 1; i > 0; i--) {
 index = charRandom.nextInt(i + 1);
 if (index != i) {
 char_key[index] ^= char_key[i];
 char_key[i] ^= char_key[index];
 char_key[index] ^= char_key[i];
 }
 }
 break;
 case RICHARD_DURSTENFELD_SHUFFLE:
 for (int i = char_key.length - 1; i > 0; i--) {
 index = charRandom.nextInt(i + 1);
 char temp = char_key[index];
 char_key[index] = char_key[i];
 char_key[i] = temp;
 }
 break;
 default:
 break;
 }
 }
 /*
 * Method which securely shuffles an array using different conventional
 * methods
 */
 private void shuffle(String[] byte_key, SecureRandom byteRandom) {
 int index;
 for (int i = byte_key.length - 1; i > 0; i--) {
 index = byteRandom.nextInt(i + 1);
 String temp = byte_key[index];
 byte_key[index] = byte_key[i];
 byte_key[i] = temp;
 }
 }
 public enum ShuffelMethod {
 FISHER_YATES_SHUFFLE, RICHARD_DURSTENFELD_SHUFFLE,
 }
 public char[] getBase_key() {
 return char_base_set;
 }
 public String[] getBase_Byte() {
 return byte_base_set;
 }
 public char[] getNew_Key() {
 return char_key_set;
 }
 public String[] getNew_Byte() {
 return byte_key_set;
 }
 }
 /**
 * Password class used by the String Encryption Utility
 * the pass word must contain at least 6 character.
 * @author Eudy Contreras
 *
 */
 public static class Password{
 private String password;
 public Password(String password){
 this.password = password;
 }
 private String getPassword(){
 return password;
 }
 private boolean isPasswordOk(){
 return password.length()>=6 && password!=null;
 }
 }
 public enum SecurityLevel{
 LOW,MEDIUM,HIGH,VERY_HIGH
 }
 private static class InvalidPasswordException extends Exception {
 private static final long serialVersionUID = 1L;
 public InvalidPasswordException(String message) {
 super(message);
 System.err.println(this.getMessage());
 System.err.println("Please look at the documentation for more information");
 }
 }
 private static class InvalidCharacterSetException extends Exception {
 private static final long serialVersionUID = 1L;
 public InvalidCharacterSetException(String message) {
 super(message);
 System.err.println(this.getMessage());
 System.err.println("Please look at the documentation for more information");
 }
 }
 public static void main(String[] args) {
  char[] new_char_set =
 {'D',' ','F','G','H','Ä','U','J',
 'A','L','Z','Å','N',',','P','Q',
 'W','S','T','Ö','.','V','R','X',
 'Y','M','!','B','O','4','6','1',
 '8','3','2','9','0','5','7','E',
 'C','?','I','K','$','/','@','*'};
 long encrypt_start_time = System.currentTimeMillis();
 byte[] encryption = StringEncrypter.encrypt("Your message is now secure!!", new Password("password"),new_char_set, SecurityLevel.MEDIUM);
 long encrypt_end_time = System.currentTimeMillis();
 System.out.println("Encryption speed: "+(encrypt_end_time - encrypt_start_time)+ " Milliseconds");

 System.out.println("Actual encrypted message:");
 System.out.println("////////////////////////////////////////////////////////////////////////////////");
 System.out.println("");
 System.out.println(EncryptionUtils.printBytes(encryption));
 System.out.println("");
 System.out.println("////////////////////////////////////////////////////////////////////////////////");

// System.out.println(Arrays.toString(encryption));
 long decrypt_start_time = System.currentTimeMillis();
 System.out.println(StringEncrypter.decrypt(encryption,new Password("password"),new_char_set,SecurityLevel.MEDIUM));
 long decrypt_end_time = System.currentTimeMillis();
 System.out.println("Decryption speed: "+(decrypt_end_time - decrypt_start_time)+ " Milliseconds");
 }
}
adjusted the ability to manipulate insertion point
Source Link
Loading
Edited the static access
Source Link
Loading
added 5685 characters in body
Source Link
Loading
edited title
Link
Loading
Source Link
Loading
lang-java

AltStyle によって変換されたページ (->オリジナル) /