2021-09-26 17:26:59 +08:00
|
|
|
package Ciphers;
|
|
|
|
|
|
|
|
import java.util.Objects;
|
2018-04-14 11:39:16 +08:00
|
|
|
|
|
|
|
/**
|
2017-10-06 05:37:13 +08:00
|
|
|
* Columnar Transposition Cipher Encryption and Decryption.
|
2018-04-14 11:39:16 +08:00
|
|
|
*
|
2017-10-06 05:37:13 +08:00
|
|
|
* @author <a href="https://github.com/freitzzz">freitzzz</a>
|
|
|
|
*/
|
|
|
|
public class ColumnarTranspositionCipher {
|
2018-04-14 11:39:16 +08:00
|
|
|
|
2020-10-24 18:23:28 +08:00
|
|
|
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 = '≈';
|
2018-04-14 11:39:16 +08:00
|
|
|
|
2020-10-24 18:23:28 +08:00
|
|
|
/**
|
|
|
|
* 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);
|
2021-09-26 17:26:59 +08:00
|
|
|
StringBuilder wordEncrypted = new StringBuilder();
|
2020-10-24 18:23:28 +08:00
|
|
|
for (int i = 0; i < sortedTable[i].length; i++) {
|
|
|
|
for (int j = 1; j < sortedTable.length; j++) {
|
2021-09-26 17:26:59 +08:00
|
|
|
wordEncrypted.append(sortedTable[j][i]);
|
2020-10-24 18:23:28 +08:00
|
|
|
}
|
2017-10-06 05:37:13 +08:00
|
|
|
}
|
2021-09-26 17:26:59 +08:00
|
|
|
return wordEncrypted.toString();
|
2020-10-24 18:23:28 +08:00
|
|
|
}
|
2017-10-06 05:37:13 +08:00
|
|
|
|
2020-10-24 18:23:28 +08:00
|
|
|
/**
|
|
|
|
* 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;
|
2021-09-26 17:26:59 +08:00
|
|
|
ColumnarTranspositionCipher.abecedarium = Objects.requireNonNullElse(abecedarium, ABECEDARIUM);
|
2020-10-24 18:23:28 +08:00
|
|
|
table = tableBuilder(word);
|
|
|
|
Object[][] sortedTable = sortTable(table);
|
2021-09-26 17:26:59 +08:00
|
|
|
StringBuilder wordEncrypted = new StringBuilder();
|
2020-10-24 18:23:28 +08:00
|
|
|
for (int i = 0; i < sortedTable[0].length; i++) {
|
|
|
|
for (int j = 1; j < sortedTable.length; j++) {
|
2021-09-26 17:26:59 +08:00
|
|
|
wordEncrypted.append(sortedTable[j][i]);
|
2020-10-24 18:23:28 +08:00
|
|
|
}
|
2017-10-06 05:37:13 +08:00
|
|
|
}
|
2021-09-26 17:26:59 +08:00
|
|
|
return wordEncrypted.toString();
|
2020-10-24 18:23:28 +08:00
|
|
|
}
|
2018-04-14 11:39:16 +08:00
|
|
|
|
2020-10-24 18:23:28 +08:00
|
|
|
/**
|
|
|
|
* 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() {
|
2021-09-26 17:26:59 +08:00
|
|
|
StringBuilder wordDecrypted = new StringBuilder();
|
2020-10-24 18:23:28 +08:00
|
|
|
for (int i = 1; i < table.length; i++) {
|
|
|
|
for (Object item : table[i]) {
|
2021-09-26 17:26:59 +08:00
|
|
|
wordDecrypted.append(item);
|
2020-10-24 18:23:28 +08:00
|
|
|
}
|
2017-10-06 05:37:13 +08:00
|
|
|
}
|
2021-09-26 17:26:59 +08:00
|
|
|
return wordDecrypted.toString().replaceAll(ENCRYPTION_FIELD, "");
|
2020-10-24 18:23:28 +08:00
|
|
|
}
|
2018-04-14 11:39:16 +08:00
|
|
|
|
2020-10-24 18:23:28 +08:00
|
|
|
/**
|
|
|
|
* 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++;
|
2018-04-14 11:39:16 +08:00
|
|
|
} else {
|
2020-10-24 18:23:28 +08:00
|
|
|
table[i][j] = ENCRYPTION_FIELD_CHAR;
|
2017-10-06 05:37:13 +08:00
|
|
|
}
|
2020-10-24 18:23:28 +08:00
|
|
|
}
|
2017-10-06 05:37:13 +08:00
|
|
|
}
|
2020-10-24 18:23:28 +08:00
|
|
|
return table;
|
|
|
|
}
|
2018-04-14 11:39:16 +08:00
|
|
|
|
2020-10-24 18:23:28 +08:00
|
|
|
/**
|
|
|
|
* 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();
|
2017-10-06 05:37:13 +08:00
|
|
|
}
|
2020-10-24 18:23:28 +08:00
|
|
|
}
|
2018-04-14 11:39:16 +08:00
|
|
|
|
2020-10-24 18:23:28 +08:00
|
|
|
/** @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;
|
2017-10-06 05:37:13 +08:00
|
|
|
}
|
2020-10-24 18:23:28 +08:00
|
|
|
return charValues;
|
|
|
|
}
|
2018-04-14 11:39:16 +08:00
|
|
|
|
2020-10-24 18:23:28 +08:00
|
|
|
/**
|
|
|
|
* @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);
|
2017-10-06 05:37:13 +08:00
|
|
|
}
|
2020-10-24 18:23:28 +08:00
|
|
|
}
|
2017-10-06 05:37:13 +08:00
|
|
|
}
|
2020-10-24 18:23:28 +08:00
|
|
|
return tableSorted;
|
|
|
|
}
|
2018-04-14 11:39:16 +08:00
|
|
|
|
2020-10-24 18:23:28 +08:00
|
|
|
/**
|
|
|
|
* @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];
|
2017-10-06 05:37:13 +08:00
|
|
|
}
|
2020-10-24 18:23:28 +08:00
|
|
|
return columnArray;
|
|
|
|
}
|
2018-04-14 11:39:16 +08:00
|
|
|
|
2020-10-24 18:23:28 +08:00
|
|
|
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];
|
2017-10-06 05:37:13 +08:00
|
|
|
}
|
2020-10-24 18:23:28 +08:00
|
|
|
}
|
2018-04-14 11:39:16 +08:00
|
|
|
|
2020-10-24 18:23:28 +08:00
|
|
|
/**
|
|
|
|
* 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) {
|
2021-09-26 17:26:59 +08:00
|
|
|
StringBuilder t = new StringBuilder();
|
2020-10-24 18:23:28 +08:00
|
|
|
for (int i = 0; i < value; i++) {
|
2021-09-26 17:26:59 +08:00
|
|
|
t.append((char) i);
|
2017-10-06 05:37:13 +08:00
|
|
|
}
|
2021-09-26 17:26:59 +08:00
|
|
|
abecedarium = t.toString();
|
2020-10-24 18:23:28 +08:00
|
|
|
}
|
2018-04-14 11:39:16 +08:00
|
|
|
|
2020-10-24 18:23:28 +08:00
|
|
|
private static void showTable() {
|
|
|
|
for (Object[] table1 : table) {
|
|
|
|
for (Object item : table1) {
|
|
|
|
System.out.print(item + " ");
|
|
|
|
}
|
|
|
|
System.out.println();
|
2017-10-06 05:37:13 +08:00
|
|
|
}
|
2020-10-24 18:23:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
2017-10-06 05:37:13 +08:00
|
|
|
}
|