package Ciphers; import java.util.Objects; /** * Columnar Transposition Cipher Encryption and Decryption. * * @author freitzzz */ public class ColumnarTranspositionCipher { private static String keyword; private static Object[][] table; private static String abecedarium; public static final String ABECEDARIUM = "abcdefghijklmnopqrstuvwxyzABCDEFG" + "HIJKLMNOPQRSTUVWXYZ0123456789,.;:-@"; private static final String ENCRYPTION_FIELD = "≈"; private static final char ENCRYPTION_FIELD_CHAR = '≈'; /** * Encrypts a certain String with the Columnar Transposition Cipher Rule * * @param word Word being encrypted * @param keyword String with keyword being used * @return a String with the word encrypted by the Columnar Transposition Cipher Rule */ public static String encrpyter(String word, String keyword) { ColumnarTranspositionCipher.keyword = keyword; abecedariumBuilder(500); table = tableBuilder(word); Object[][] sortedTable = sortTable(table); StringBuilder wordEncrypted = new StringBuilder(); for (int i = 0; i < sortedTable[i].length; i++) { for (int j = 1; j < sortedTable.length; j++) { wordEncrypted.append(sortedTable[j][i]); } } return wordEncrypted.toString(); } /** * Encrypts a certain String with the Columnar Transposition Cipher Rule * * @param word Word being encrypted * @param keyword String with keyword being used * @param abecedarium String with the abecedarium being used. null for default one * @return a String with the word encrypted by the Columnar Transposition Cipher Rule */ public static String encrpyter(String word, String keyword, String abecedarium) { ColumnarTranspositionCipher.keyword = keyword; ColumnarTranspositionCipher.abecedarium = Objects.requireNonNullElse(abecedarium, ABECEDARIUM); table = tableBuilder(word); Object[][] sortedTable = sortTable(table); StringBuilder wordEncrypted = new StringBuilder(); for (int i = 0; i < sortedTable[0].length; i++) { for (int j = 1; j < sortedTable.length; j++) { wordEncrypted.append(sortedTable[j][i]); } } return wordEncrypted.toString(); } /** * Decrypts a certain encrypted String with the Columnar Transposition Cipher Rule * * @return a String decrypted with the word encrypted by the Columnar Transposition Cipher Rule */ public static String decrypter() { StringBuilder wordDecrypted = new StringBuilder(); for (int i = 1; i < table.length; i++) { for (Object item : table[i]) { wordDecrypted.append(item); } } return wordDecrypted.toString().replaceAll(ENCRYPTION_FIELD, ""); } /** * Builds a table with the word to be encrypted in rows by the Columnar Transposition Cipher Rule * * @return An Object[][] with the word to be encrypted filled in rows and columns */ private static Object[][] tableBuilder(String word) { Object[][] table = new Object[numberOfRows(word) + 1][keyword.length()]; char[] wordInChards = word.toCharArray(); // Fils in the respective numbers table[0] = findElements(); int charElement = 0; for (int i = 1; i < table.length; i++) { for (int j = 0; j < table[i].length; j++) { if (charElement < wordInChards.length) { table[i][j] = wordInChards[charElement]; charElement++; } else { table[i][j] = ENCRYPTION_FIELD_CHAR; } } } return table; } /** * Determines the number of rows the table should have regarding the Columnar Transposition Cipher * Rule * * @return an int with the number of rows that the table should have in order to respect the * Columnar Transposition Cipher Rule. */ private static int numberOfRows(String word) { if (word.length() / keyword.length() > word.length() / keyword.length()) { return (word.length() / keyword.length()) + 1; } else { return word.length() / keyword.length(); } } /** * @return charValues */ private static Object[] findElements() { Object[] charValues = new Object[keyword.length()]; for (int i = 0; i < charValues.length; i++) { int charValueIndex = abecedarium.indexOf(keyword.charAt(i)); charValues[i] = charValueIndex > -1 ? charValueIndex : null; } return charValues; } /** * @return tableSorted */ private static Object[][] sortTable(Object[][] table) { Object[][] tableSorted = new Object[table.length][table[0].length]; for (int i = 0; i < tableSorted.length; i++) { System.arraycopy(table[i], 0, tableSorted[i], 0, tableSorted[i].length); } for (int i = 0; i < tableSorted[0].length; i++) { for (int j = i + 1; j < tableSorted[0].length; j++) { if ((int) tableSorted[0][i] > (int) table[0][j]) { Object[] column = getColumn(tableSorted, tableSorted.length, i); switchColumns(tableSorted, j, i, column); } } } return tableSorted; } /** * @return columnArray */ private static Object[] getColumn(Object[][] table, int rows, int column) { Object[] columnArray = new Object[rows]; for (int i = 0; i < rows; i++) { columnArray[i] = table[i][column]; } return columnArray; } private static void switchColumns( Object[][] table, int firstColumnIndex, int secondColumnIndex, Object[] columnToSwitch) { for (int i = 0; i < table.length; i++) { table[i][secondColumnIndex] = table[i][firstColumnIndex]; table[i][firstColumnIndex] = columnToSwitch[i]; } } /** * Creates an abecedarium with a specified ascii inded * * @param value Number of characters being used based on the ASCII Table */ private static void abecedariumBuilder(int value) { StringBuilder t = new StringBuilder(); for (int i = 0; i < value; i++) { t.append((char) i); } abecedarium = t.toString(); } private static void showTable() { for (Object[] table1 : table) { for (Object item : table1) { System.out.print(item + " "); } System.out.println(); } } public static void main(String[] args) { String keywordForExample = "asd215"; String wordBeingEncrypted = "This is a test of the Columnar Transposition Cipher"; System.out.println("### Example of Columnar Transposition Cipher ###\n"); System.out.println("Word being encryped ->>> " + wordBeingEncrypted); System.out.println( "Word encrypted ->>> " + ColumnarTranspositionCipher.encrpyter(wordBeingEncrypted, keywordForExample)); System.out.println("Word decryped ->>> " + ColumnarTranspositionCipher.decrypter()); System.out.println("\n### Encrypted Table ###"); showTable(); } }