Transposition Cipher
In cryptography, a transposition cipher, also known as columnar transposition cipher, is a simple and easy to implement cipher. This cipher follows a simple rule for mixing up the characters in the plaintext to form the ciphertext. Although this cipher is weak on its own, but it can be combined with other ciphers, such as a substitution cipher, the combination of which can be more difficult to break than either cipher on it's own.
Example:
The key for the transposition cipher is a keyword e.g. 'pangram'. To encrypt a piece of text, e.g. 'The quick brown fox jumps over the lazy dog', we write it out in a special way in a number of rows:
p | a | n | g | r | a | m |
T | h | e | q | u | i | |
c | k | b | r | o | w | |
n | f | o | x | j | ||
u | m | p | s | o | v | |
e | r | t | h | e | ||
l | a | z | y | d | o | |
g | - | - | - | - | - | - |
The columns are now reordered such that the letters in the key word are ordered alphabetically.
a | a | g | m | n | p | r |
h | u | i | e | T | q | |
k | o | b | w | c | r | |
o | j | f | n | x | ||
m | o | s | v | p | u | |
r | e | t | e | h | ||
a | d | y | o | z | l | |
- | - | - | - | - | g | - |
The ciphertext is read off along the columns: 'hk mra-uo oed- bosty-iwjv o-e fp z-Tcnuelgqrx h -'
/*****Please include following header files*****/
// iostream
// list
/***********************************************/
/*****Please use following namespaces*****/
// std
/*****************************************/
typedef struct {
int Key;
char Value;
} KeyValuePair;
static bool compare(const KeyValuePair &first, const KeyValuePair &second) {
return first.Value < second.Value;
}
static char** Create2DArray(int rowCount, int colCount) {
char** arr = new char*[rowCount];
for (int i = 0; i < rowCount; ++i)
arr[i] = new char[colCount];
return arr;
}
static string PadRight(string str, int max, char padChar) {
int strLen = str.length();
if (strLen < max) {
int padLen = max - strLen;
for (int i = 0; i < padLen; ++i) str += padChar;
}
return str;
}
static int* GetShiftIndexes(string key)
{
int keyLength = key.length();
int* indexes = new int[keyLength];
list<KeyValuePair> sortedKey;
int i;
for (i = 0; i < keyLength; ++i)
sortedKey.push_back({ i, key[i] });
sortedKey.sort(compare);
i = 0;
for each (KeyValuePair pair in sortedKey) {
indexes[pair.Key] = i;
++i;
}
return indexes;
}
static string Encipher(string input, string key, char padChar)
{
string output = "";
int totalChars = input.length();
int keyLength = key.length();
input = (totalChars % keyLength == 0) ? input : PadRight(input, totalChars - (totalChars % keyLength) + keyLength, padChar);
totalChars = input.length();
int totalColumns = keyLength;
int totalRows = (int)ceil((double)totalChars / totalColumns);
char** rowChars = Create2DArray(totalRows, totalColumns);
char** colChars = Create2DArray(totalColumns, totalRows);
char** sortedColChars = Create2DArray(totalColumns, totalRows);
int currentRow, currentColumn, i, j;
int* shiftIndexes = GetShiftIndexes(key);
for (i = 0; i < totalChars; ++i)
{
currentRow = i / totalColumns;
currentColumn = i % totalColumns;
rowChars[currentRow][currentColumn] = input[i];
}
for (i = 0; i < totalRows; ++i)
for (j = 0; j < totalColumns; ++j)
colChars[j][i] = rowChars[i][j];
for (i = 0; i < totalColumns; ++i)
for (j = 0; j < totalRows; ++j)
sortedColChars[shiftIndexes[i]][j] = colChars[i][j];
for (i = 0; i < totalChars; ++i)
{
currentRow = i / totalRows;
currentColumn = i % totalRows;
output += sortedColChars[currentRow][currentColumn];
}
return output;
}
static string Decipher(string input, string key)
{
string output = "";
int keyLength = key.length();
int totalChars = input.length();
int totalColumns = (int)ceil((double)totalChars / keyLength);
int totalRows = keyLength;
char** rowChars = Create2DArray(totalRows, totalColumns);
char** colChars = Create2DArray(totalColumns, totalRows);
char** unsortedColChars = Create2DArray(totalColumns, totalRows);
int currentRow, currentColumn, i, j;
int* shiftIndexes = GetShiftIndexes(key);
for (i = 0; i < totalChars; ++i)
{
currentRow = i / totalColumns;
currentColumn = i % totalColumns;
rowChars[currentRow][currentColumn] = input[i];
}
for (i = 0; i < totalRows; ++i)
for (j = 0; j < totalColumns; ++j)
colChars[j][i] = rowChars[i][j];
for (i = 0; i < totalColumns; ++i)
for (j = 0; j < totalRows; ++j)
unsortedColChars[i][j] = colChars[i][shiftIndexes[j]];
for (i = 0; i < totalChars; ++i)
{
currentRow = i / totalRows;
currentColumn = i % totalRows;
output += unsortedColChars[currentRow][currentColumn];
}
return output;
}
Example
string text = "The quick brown fox jumps over the lazy dog";
string key = "pangram";
string cipherText = Encipher(text, key, '-');
string plainText = Decipher(cipherText, key);
Output
cipherText: "hk mra-uo oed- bosty-iwjv o-e fp z-Tcnuelgqrx h -"
plainText: "The quick brown fox jumps over the lazy dog------"