Skip to content

Instantly share code, notes, and snippets.

@GregaMohorko
Last active November 3, 2020 10:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GregaMohorko/eab0004d7bc942585e6038ceb46eb718 to your computer and use it in GitHub Desktop.
Save GregaMohorko/eab0004d7bc942585e6038ceb46eb718 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
namespace GM.Security.Cryptography
{
public class SimpleRectangleCipher
{
private const string ALPHABET = "ABCDEFGHIJKLMNOPRSTUVZ";
private const char SPACE_REPLACEMENT = 'Q';
public static void Main()
{
string textToEncipher = "This tekst vvill be enciphered.";
string textToDecipher = "Ufzfr.iljQijtmfftumosQQQdfuzcje";
CheckAlphabetAndSpaceReplacement();
// encipher
if(!string.IsNullOrWhiteSpace(textToEncipher)) {
List<string> cipher = Encipher(textToEncipher);
Console.WriteLine("Cipher:");
foreach(string line in cipher) {
Console.WriteLine(line);
}
if(textToEncipher != Decipher(cipher)) {
throw new Exception($"Something is wrong. '{textToEncipher}' should equal '{Decipher(cipher)}'.");
}
}
// decipher
if(!string.IsNullOrWhiteSpace(textToDecipher)) {
string secret = Decipher(textToDecipher);
Console.WriteLine("Secret:");
Console.WriteLine(secret);
if(RemoveNewLines(textToDecipher) != string.Join("", Encipher(secret))) {
throw new Exception($"Something is wrong. '{RemoveNewLines(textToDecipher)}' should equal '{string.Join("", Encipher(secret))}'.");
}
}
}
private static List<string> Encipher(string text)
{
string shiftedText = ShiftLeftRight(text, true);
int lines = (int)Math.Ceiling(Math.Sqrt(text.Length));
var result = new List<string>();
for(int i = 0; i < lines; ++i) {
string line = "";
for(int j = 0; j < lines + 1; ++j) {
int pos = j * lines + i;
if(shiftedText.Length <= pos) {
continue;
}
line += shiftedText[pos];
}
result.Add(line);
}
return result;
}
private static string Decipher(List<string> cipher)
{
return Decipher(string.Join("", cipher));
}
private static string Decipher(string cipher)
{
var shiftedCipher = ShiftLeftRight(RemoveNewLines(cipher), false);
int lines = (int)Math.Ceiling(Math.Sqrt(shiftedCipher.Length));
int lineLength = (int)Math.Ceiling(shiftedCipher.Length / (double)lines);
int fullLengthLines = lines - (lines * lineLength - shiftedCipher.Length);
string result = "";
for(int i = 0; i < lineLength; ++i) {
for(int j = 0; j < lines; ++j) {
if(i == lineLength - 1 && j == fullLengthLines) {
break;
}
int pos = 0;
for(int k = 1; k <= j; ++k) {
pos += lineLength - (k > fullLengthLines ? 1 : 0);
}
pos += i;
if(shiftedCipher.Length <= pos) {
continue;
}
result += shiftedCipher[pos];
}
}
return result;
}
private static string ShiftLeftRight(string text, bool directionRight)
{
string shiftedText = "";
for(int i = 0; i < text.Length; ++i) {
char c = text[i];
char shiftedC;
if(char.IsDigit(c)) {
shiftedC = c;
} else {
int pos = ALPHABET.IndexOf(char.ToUpperInvariant(c));
if(pos == -1 || char.ToUpper(c) == SPACE_REPLACEMENT) {
if(!char.IsLetter(c) || char.ToUpper(c) == SPACE_REPLACEMENT) {
switch(char.ToUpper(c)) {
case ' ':
shiftedC = SPACE_REPLACEMENT;
break;
case SPACE_REPLACEMENT:
shiftedC = ' ';
break;
case '.':
case ',':
case '-':
shiftedC = c;
break;
default:
throw new Exception($"A character that is not allowed: '{c}'.");
}
} else {
throw new Exception($"A letter that is not in the alphabet: '{c}'.");
}
} else {
int shiftedPos = (pos + (directionRight ? 1 : -1) + ALPHABET.Length) % ALPHABET.Length;
shiftedC = ALPHABET[shiftedPos];
if(char.IsLower(c)) {
shiftedC = char.ToLower(shiftedC);
}
}
}
shiftedText += shiftedC;
}
return shiftedText;
}
private static string RemoveNewLines(string text)
{
return text.Replace("\r", "").Replace("\n", "");
}
private static void CheckAlphabetAndSpaceReplacement()
{
if(ALPHABET.Any(c => !char.IsLetter(c) || !char.IsUpper(c))) {
throw new Exception("All characters in the alphabet must be uppercase letters.");
}
if(!char.IsUpper(SPACE_REPLACEMENT)) {
throw new Exception("The space replacement character must be upper case.");
}
if(ALPHABET.Any(c => c == char.ToUpper(SPACE_REPLACEMENT))) {
throw new Exception("The space replacement character must not be in the alphabet.");
}
if(SPACE_REPLACEMENT == ',' || SPACE_REPLACEMENT == '.' || SPACE_REPLACEMENT == '-') {
throw new Exception("The space replacement character must not be ',', '.' or '-'.");
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment