From 65dbd8cae2ecfbed099cf2196522ee8dd7ac0015 Mon Sep 17 00:00:00 2001 From: cxford Date: Thu, 4 Aug 2016 12:10:50 -0500 Subject: [PATCH] Converting from Bazaar Old Log: ------------------------------------------------------------ revno: 16 committer: cxford branch nick: CryptoWorkbench timestamp: Sun 2016-07-10 20:22:37 -0500 message: Some fixes for regex, captive shells, analysis ------------------------------------------------------------ revno: 15 committer: dev branch nick: CryptoWorkbench timestamp: Thu 2016-07-07 13:54:04 -0500 message: Adding captivecrypto.bash shell to go with ForceCommand ------------------------------------------------------------ revno: 14 committer: dev branch nick: CryptoWorkbench timestamp: Thu 2016-07-07 13:38:21 -0500 message: Updating ------------------------------------------------------------ revno: 13 committer: cxford branch nick: CryptoWorkbench timestamp: Tue 2016-07-05 13:20:34 -0500 message: Adding inline regex lookup Updating ciphers to use standard constructor -- now ciphers can be added from new class, new private in WorkBench, and new instantiation in Workbench constructor ------------------------------------------------------------ revno: 12 committer: dev branch nick: CryptoWorkbench timestamp: Sat 2016-06-18 10:16:40 -0500 message: GUI enhancements for colorizing. General updates. ------------------------------------------------------------ revno: 11 committer: dev branch nick: CryptoWorkbench timestamp: Mon 2016-05-09 12:21:57 -0500 message: Updated letter frequency in analysis Added reverse function in Simple Updated bash script with small fixes Updated cryptoworkbench Links function with link to frequency analysis ------------------------------------------------------------ revno: 10 committer: dev branch nick: CryptoWorkbench timestamp: Fri 2016-04-15 13:03:41 -0500 message: Syncing with new ciphers for Affine, Ubchi, Vignere, and Columnar Transposition. Analytics updated and general fixes included. Paradigm shift for cipher inheritance. ------------------------------------------------------------ revno: 9 committer: cxford branch nick: CryptoWorkbench timestamp: Wed 2016-02-10 15:36:37 -0600 message: Added new class for simple operations, like string to upper/lower and removing spaces. Updated with file reading and writing. Added brute-force for Caesarian ciphers. Updated substition and analysis for better options. Improved CLI ------------------------------------------------------------ revno: 8 committer: root branch nick: CryptoWorkbench timestamp: Mon 2016-02-01 13:44:20 -0600 message: Modified analysis to display doubled letters and notify of which letter is repeated when One-to-one query fails to find a one-to-one relationship ------------------------------------------------------------ revno: 7 committer: root branch nick: CryptoWorkbench timestamp: Thu 2016-01-28 10:03:40 -0600 message: Lots of minor fixes. ------------------------------------------------------------ revno: 6 committer: root branch nick: CryptoWorkbench timestamp: Wed 2016-01-20 09:29:54 -0600 message: Makefile had a small typo but it prevented installs. Worth a commit. ------------------------------------------------------------ revno: 5 committer: root branch nick: CryptoWorkbench timestamp: Tue 2016-01-19 13:12:12 -0600 message: Added one-to-one query to Analysis for checking if a substitution or rotation remains one-to-one and to acquire the key Moved bash script to ease tab-completion ------------------------------------------------------------ revno: 4 committer: root branch nick: CryptoWorkbench timestamp: Thu 2016-01-14 10:24:02 -0600 message: Renamed README to be consistent with other branches in repo. Added Caesarian functions Added analysis and substitution functions for letter substitution. ------------------------------------------------------------ revno: 3 committer: cxford branch nick: CryptoWorkbench timestamp: Wed 2016-01-13 16:41:05 -0600 message: Added install files ------------------------------------------------------------ revno: 2 committer: cxford branch nick: CryptoWorkbench timestamp: Wed 2016-01-13 16:30:10 -0600 message: Adding Makefile and source files. ------------------------------------------------------------ revno: 1 committer: cxford branch nick: CryptoWorkbench timestamp: Wed 2016-01-13 10:29:31 -0600 message: Initializing project tree and adding Readme. --- .gitignore | 1 + ForceCommand.txt | 5 + Makefile | 36 ++++++ README.bzr | 9 ++ affine.csharp | 81 ++++++++++++ analysis.csharp | 248 ++++++++++++++++++++++++++++++++++++ bash.cryptoworkbench | 7 + caesarian.csharp | 88 +++++++++++++ captivecrypto.bash | 9 ++ chargrid.csharp | 117 +++++++++++++++++ cipher.csharp | 82 ++++++++++++ columntransposition.csharp | 90 +++++++++++++ cryptoworkbench.csharp | 254 +++++++++++++++++++++++++++++++++++++ newcipher.template | 23 ++++ ravenexecute.csharp | 58 +++++++++ regex-lookup.bash | 14 ++ sample.txt | 3 + simple.csharp | 90 +++++++++++++ substitution.csharp | 102 +++++++++++++++ ubchi.csharp | 39 ++++++ vigenere.csharp | 77 +++++++++++ 21 files changed, 1433 insertions(+) create mode 100644 .gitignore create mode 100644 ForceCommand.txt create mode 100644 Makefile create mode 100644 README.bzr create mode 100644 affine.csharp create mode 100644 analysis.csharp create mode 100644 bash.cryptoworkbench create mode 100644 caesarian.csharp create mode 100644 captivecrypto.bash create mode 100644 chargrid.csharp create mode 100644 cipher.csharp create mode 100644 columntransposition.csharp create mode 100644 cryptoworkbench.csharp create mode 100644 newcipher.template create mode 100644 ravenexecute.csharp create mode 100644 regex-lookup.bash create mode 100644 sample.txt create mode 100644 simple.csharp create mode 100644 substitution.csharp create mode 100644 ubchi.csharp create mode 100644 vigenere.csharp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..85cd24f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +CryptoApplet.java diff --git a/ForceCommand.txt b/ForceCommand.txt new file mode 100644 index 0000000..bea069c --- /dev/null +++ b/ForceCommand.txt @@ -0,0 +1,5 @@ +Match User crypto + ForceCommand /usr/local/bin/captivecrypto + X11Forwarding no + PermitTunnel no + AllowTcpForwarding no diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..608da4e --- /dev/null +++ b/Makefile @@ -0,0 +1,36 @@ +TMUXSetting != grep -c "cryptoworkbench" /etc/tmux.conf + +compile: clean /usr/bin/mcs analysis.csharp substitution.csharp caesarian.csharp cryptoworkbench.csharp + /usr/bin/mcs -out:cryptoworkbench.exe *.csharp + +test: /usr/bin/mono compile + /usr/bin/mono cryptoworkbench.exe ./sample.txt + +clean: + if [ -f cryptoworkbench.exe ]; then rm cryptoworkbench.exe; fi + +install: compile /bin/bash bash.cryptoworkbench + mv cryptoworkbench.exe /opt + chmod 0555 /opt/cryptoworkbench.exe + cp bash.cryptoworkbench /usr/local/bin/cryptoworkbench + chmod 0555 /usr/local/bin/cryptoworkbench + cp captivecrypto.bash /usr/local/bin/captivecrypto + chown root:root /usr/local/bin/captivecrypto + chmod 0755 /usr/local/bin/captivecrypto + +webapp: install + javac CryptoApplet.java + @echo TODO this is a work in progress. + @echo Install the CryptoApplet.class and crypto.phpsnip into a webpage for your site. + +sshuser: install ForceCommand.txt + grep captivecrypto /etc/shells || echo '/usr/local/bin/captivecrypto' /etc/shells + id crypto || useradd -k -d /home/crypto -s /usr/local/bin/captivecrypto crypto + cat ./ForceCommand.txt >> /etc/ssh/sshd_config + echo crypto | passwd --stdin crypto + +tmux: /usr/bin/tmux + @echo Making sure cryptoworkbench setting isn\'t already in /etc/tmux.conf... + [ "${TMUXSetting}" -eq 0 ] + echo "bind-key -T prefix x new-window cryptoworkbench" >> /etc/tmux.conf + echo 'bind-key -T prefix X confirm-before -p "kill-pane #P? (y/n)" kill-pane' >> /etc/tmux.conf diff --git a/README.bzr b/README.bzr new file mode 100644 index 0000000..6661a0f --- /dev/null +++ b/README.bzr @@ -0,0 +1,9 @@ +This project is to allow easy deciphering of text-based ciphers. We will start with basic functions and add new ones as possible. + +The format for this project should be as follows: + * cryptoworkbench.csharp contains CLI commands and command reference to each cipher's API. + * Analysis functions should be placed in the Analysis class, and simple character operations go in Simple. + * CharGrid offers a means to make horizontal and vertical arrays of characters from strings. + * Each cipher should implement the abstract AniNIX.Crypto.Cipher and may add unique functions. + +A sample.txt file is provided for test purposes, and a Makefile contains all your compilation rules. The bash script will allow invocation on UNIX machines. diff --git a/affine.csharp b/affine.csharp new file mode 100644 index 0000000..9590760 --- /dev/null +++ b/affine.csharp @@ -0,0 +1,81 @@ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections.Generic; + +namespace AniNIX.Crypto { + public class Affine : Cipher { + + public override String Description() { return "The Affine cipher\nKey format is two numbers, where the second number is coprime to the first."; } + public override String Command() {return "affine";} + public Affine(Workbench w) : base (w) {} + + public override String Encrypt(String workSpace,String inputText,String[] line) { + if (line == null || line.Length != 4) { + Console.Error.WriteLine("Malformed!"); + return workSpace; + } + char[] changed = workSpace.ToCharArray(); + try { + int a = Int32.Parse(line[2]); + try { + MultiplicativeInverse(a); + } catch (Exception e) { + Console.Error.WriteLine(String.Format("Value a <{0}> is not coprime to 26.\n{1}",a,e.Message)); + return workSpace; + } + int b = Int32.Parse(line[3]); + for (int i = 0; i < changed.Length; i++) { + if (Char.IsLetter(changed[i])) { + int baseC = (Char.IsUpper(changed[i])) ? (int)'A' : (int)'a'; + int modC = (int)changed[i] - baseC; + changed[i] = (char)(((a*modC+b)%26)+baseC); + } + } + } catch (Exception e) { + Console.Error.WriteLine(String.Format("Failed!\n{0}",e.Message)); + return workSpace; + } + return new String(changed); + } + + public int MultiplicativeInverse(int a) { + for (int x=1; x < 27; x++) { + if ((a*x)%26 == 1) { + Console.WriteLine(String.Format("Found Multiplicative Inverse of {0}",x)); + return x; + } + } + throw new Exception("A is not coprime."); + } + + public override String Decrypt(String workSpace,String inputText,String[] line) { + if (line == null || line.Length != 4) { + Console.Error.WriteLine("Malformed!"); + return workSpace; + } + char[] changed = workSpace.ToCharArray(); + try { + int a = Int32.Parse(line[2]); + int b = Int32.Parse(line[3]); + int multiinv = MultiplicativeInverse(a); + for (int i = 0; i < changed.Length; i++) { + if (Char.IsLetter(changed[i])) { + int baseC = (Char.IsUpper(changed[i])) ? (int)'A' : (int)'a'; + int modC = (int)changed[i] - baseC; + int modResult = (multiinv * (modC-b))%26; + modResult = (modResult < 0) ? modResult+26 : modResult; // In case modResult is negative, add 26 back + changed[i] = (char)(modResult+baseC); + } + } + } catch (Exception e) { + Console.Error.WriteLine(String.Format("Failed!\n{0}",e.Message)); + return workSpace; + } + return new String(changed); + + } + + } +} diff --git a/analysis.csharp b/analysis.csharp new file mode 100644 index 0000000..030e984 --- /dev/null +++ b/analysis.csharp @@ -0,0 +1,248 @@ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Collections.Generic; + +namespace AniNIX.Crypto { + public class Analysis : Cipher { + + public override String Description() { return "Analysis tools"; } + public override String Command() { return "analysis"; } + + public Analysis(Workbench w) : base (w) {} + + public override String RunCommand(String workSpace, String inputText, String[] line) { + if (workSpace == null || inputText == null || line == null || line.Length < 2) { + Console.Error.WriteLine("Malformed!"); + return workSpace; + } + switch (line[1]) { + case "freq": + Frequency(workSpace); + break; + case "freqinfo": + FrequencyInfo(); + break; + case "one-to-one": + OneToOneQuery(workSpace,inputText); + break; + case "diff": + Diff(line); + break; + case "charinfo": + CharInfo(line); + break; + default: + GetHelp(); + break; + } + return workSpace; + } + + public override void GetHelp() { + Console.WriteLine("Analysis tools help:\nfreq -- Get frequency of characters.\nfreqinfo -- Return the most common English frequencies.\none-to-one -- See if there is a direct correspondence of characters between cipher and workspace.\ndiff a b -- get the difference between two characters\ncharinfo -- get the info about a character"); + } + + + public static Dictionary FindFrequencies(String workSpace) { + Dictionary frequencies = new Dictionary(); + for (int i = 0; i < workSpace.Length; i++) { + if (!Char.IsLetter(workSpace[i])) { continue; } + String charStr = String.Format("{0}",workSpace[i]); + if (frequencies.ContainsKey(charStr)) { + frequencies[charStr] = frequencies[charStr] + 1; + } else { + frequencies.Add(charStr,1); + } + } + return frequencies; + } + + public static List GetMostCommonLetters(String workSpace) { + List> freqList = FindFrequencies(workSpace).ToList(); + freqList.Sort((firstPair,nextPair)=>nextPair.Value.CompareTo(firstPair.Value)); + List returnL = new List(); + foreach (var item in freqList) { + returnL.Add(item.Key); + } + return returnL; + } + + public static List GetDoubles(String workSpace) { + List theList = new List(); + for (int i=1; i GetSubstrings(String workSpace, int length) { + Dictionary theList = new Dictionary(); + for (int i=1; i FindWordsOfLength(int length,String[] bySpace) { + Dictionary wordsFreq = new Dictionary(); + for (int i = 0; i < bySpace.Length; i++) { + if (bySpace[i].Length == length || (bySpace[i].Length == length+1 && Char.IsPunctuation(bySpace[i][length]))) { + if (Char.IsPunctuation(bySpace[i][bySpace[i].Length-1])) { + bySpace[i] = bySpace[i].Substring(0,bySpace[i].Length-1); + } + if (wordsFreq.ContainsKey(bySpace[i])) { + wordsFreq[bySpace[i]] += 1; + } else { + wordsFreq.Add(bySpace[i],1); + } + } + } + return wordsFreq; + } + + public static List Top(Dictionary theList) { + List> freqList = theList.ToList(); + List returnL = new List(); + freqList.Sort((firstPair,nextPair)=>nextPair.Value.CompareTo(firstPair.Value)); + for (int i = 0; i < 5 && i < freqList.Count; i++) { + returnL.Add(freqList[i].Key); + } + return returnL; + } + + + public static void PrintOrdered(Dictionary theList,String header) { + List> freqList = theList.ToList(); + freqList.Sort((firstPair,nextPair)=>nextPair.Value.CompareTo(firstPair.Value)); + Console.Write(header); + for (int i = 0; i < 5 && i < freqList.Count; i++) { + Console.Write(String.Format("({0}){1} ",freqList[i].Key,freqList[i].Value)); + } + Console.WriteLine(""); + } + + public static void PrintOrdered(List theList,String header) { + Console.Write(header); + foreach (String str in theList) { + Console.Write(str); + Console.Write(" "); + } + Console.WriteLine(); + } + + public void Frequency(String workSpace) { + //Show the individual letter frequeuncy. + Console.ForegroundColor = ConsoleColor.Cyan; + PrintOrdered(FindFrequencies(workSpace),"Top letters by frequency: "); + //Show the doubled letters + Console.ForegroundColor = ConsoleColor.Green; + PrintOrdered(GetDoubles(workSpace),"The following letters are doubled in the workspace: "); + Console.ForegroundColor = ConsoleColor.Yellow; + PrintOrdered(GetSubstrings(workSpace,2),"Top substrings of length 2: "); + Console.ForegroundColor = ConsoleColor.Magenta; + PrintOrdered(GetSubstrings(workSpace,3),"Top substrings of length 3: "); + String[] bySpace = workSpace.Split(' '); + //Find the words of a given length + Console.ForegroundColor = ConsoleColor.White; + PrintOrdered(FindWordsOfLength(1,bySpace),"Words of length 1: "); + Console.ForegroundColor = ConsoleColor.Yellow; + PrintOrdered(FindWordsOfLength(2,bySpace),"Words of length 2: "); + Console.ForegroundColor = ConsoleColor.Magenta; + PrintOrdered(FindWordsOfLength(3,bySpace),"Words of length 3: "); + Console.ResetColor(); + } + + public void FrequencyInfo() { + // Thanks to http://norvig.com/mayzner.html for this info. + // By letter + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine("Letters by frequency:"); + Console.WriteLine("E T A O I N S R H L D C U M F P G W Y B V K X J Q Z"); + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine("Possible doubles: LL EE SS OO TT FF RR NN PP CC BB MM GG UU ZZ AA"); + // By Substring 2,3 characters in length + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("Top sequences of N characters where N=..."); + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine("2: th he in er an re on at en nd"); + Console.ForegroundColor = ConsoleColor.Magenta; + Console.WriteLine("3: the and ing ion tio end ati for her ter"); + // By word 1,2,3 chars in length + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("Top words of length..."); + Console.ForegroundColor = ConsoleColor.White; + Console.WriteLine("1: I a"); + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine("2: of to in is it as be by on he"); + Console.ForegroundColor = ConsoleColor.Magenta; + Console.WriteLine("3: the and for was not are his but had you"); + Console.ResetColor(); + } + + public static void OneToOneQuery(String workSpace, String inputText) { + Dictionary relation = new Dictionary(); + StringBuilder subKey = new StringBuilder(); + StringBuilder encKey = new StringBuilder(); + subKey.Append("True. These are one-to-one.\n"); + subKey.Append("\nFinal-to-input key:\n"); + subKey.Append("sub decrypt "); + encKey.Append("sub encrypt "); + for (int i = 0; i < workSpace.Length; i++) { + if (!Char.IsWhiteSpace(workSpace[i])) { + if (relation.ContainsKey(workSpace[i])) { + if (relation[workSpace[i]] != inputText[i]) { + Console.Error.WriteLine(String.Format("Character {0} repeated. These are not one-to-one.",workSpace[i])); + return; + } + } else { + relation.Add(workSpace[i],inputText[i]); + encKey.Append(String.Format("{0}={1} ",inputText[i],workSpace[i])); + subKey.Append(String.Format("{0}={1} ",workSpace[i],inputText[i])); + } + } + } + subKey.Append("\nInput-to-final key:"); + Console.WriteLine(subKey.ToString()); + Console.WriteLine(encKey.ToString()); + } + + public void Diff(String[] line) { + if (line.Length != 4 || line[2].Length != 1 || line[3].Length != 1) { + Console.Error.WriteLine("Bad formatting"); + return; + } + char first = line[2][0]; + char second = line[3][0]; + Console.WriteLine(String.Format("These are different by {0}.",first-second)); + } + + public void CharInfo(String[] line) { + if (line == null || line.Length != 3 || line[2].Length != 1) { + Console.Error.WriteLine("Malformed"); + return; + } + Console.WriteLine(String.Format("Character: {0}\nASCII Value: {1}",line[2][0],(int)line[2][0])); + if (Char.IsLetter(line[2][0])) { + Console.WriteLine(String.Format("Alphabet index: {0}",(Char.IsUpper(line[2][0])) ? (int)line[2][0] - (int)'A' : (int)line[2][0] - (int)'a')); + } + } + + //Analysis doesn't handle encryption or decryption, but we want to use the same code for subscribing. + public override String Encrypt(string workSpace,String ciphetText,String[] line) { return workSpace; } + public override String Decrypt(string workSpace,String ciphetText,String[] line) { return workSpace; } + } +} + + diff --git a/bash.cryptoworkbench b/bash.cryptoworkbench new file mode 100644 index 0000000..a0e1bbb --- /dev/null +++ b/bash.cryptoworkbench @@ -0,0 +1,7 @@ +#!/bin/bash +if [ "$1" != "" ]; then + time mono /opt/cryptoworkbench.exe "$1"; +else + time mono /opt/cryptoworkbench.exe +fi +read diff --git a/caesarian.csharp b/caesarian.csharp new file mode 100644 index 0000000..403bd98 --- /dev/null +++ b/caesarian.csharp @@ -0,0 +1,88 @@ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections.Generic; + +namespace AniNIX.Crypto { + public class Caesarian : Cipher { + + public override String Description() { return "Caesarian cipher suite\nKey format is a numeric shift."; } + public override String Command() { return "caesar"; } + + public Caesarian(Workbench w) : base (w) {} + + public override String RunCommand(String workSpace,String inputText,String[] line) { + if (workSpace == null || line == null || line.Length < 2) { + Console.Error.WriteLine("Malformed request."); + return workSpace; + } + switch (line[1]) { + case "encrypt": + return Encrypt(workSpace,inputText,line); + case "decrypt": + return Decrypt(workSpace,inputText,line); + case "brute": + BruteForce(workSpace); + return workSpace; + default: + GetHelp(); + return workSpace; + } + } + + public override void GetHelp() { + Console.WriteLine(String.Format("Help for the {0} cipher suite.\n{1}\n",Command(),Description())); + Console.WriteLine("encrypt key -- encrypt with the key\ndecrypt key -- decrypt with the key\nbrute -- brute-force for keys\nhelp -- show this helptext."); + } + + public override String Encrypt(String workSpace,String inputText,String[] line) { + if (line.Length != 3) { + Console.Error.WriteLine("Bad formatting"); + return workSpace; + } + int rotation = 0; + try { + rotation = Int32.Parse(line[2]); + } catch (Exception e) { + Console.Error.WriteLine("Error in parsing rotation value -- should be numeric."); + Console.Error.WriteLine(e.Message); + return workSpace; + } + char[] modified = workSpace.ToCharArray(); + for (int i = 0; i < modified.Length; i++) { + if (Char.IsLetter(modified[i])) { + int baseC; + int modC; + if (modified[i] < 'a') { + baseC = (int)'A'; + modC = (int)modified[i] - (int)'A'; + } else { + baseC = (int)'a'; + modC = (int)modified[i] - (int)'a'; + } + modC = (modC + rotation)%26; + //Debugging + //Console.Write(String.Format("Updating index {0} <{5}> val {1} base {2} mod {3} rotation {4} --to-- ",i,(int)modified[i],baseC,modC,rotation,modified[i])); + modified[i] = (char)(baseC+modC); + //Console.WriteLine(String.Format("<{0}> val {1}",modified[i],baseC+modC)); + } + } + return new String(modified); + } + + public override String Decrypt(String workSpace,String inputText,String[] line) { + return Encrypt(workSpace,inputText,line); + } + + public void BruteForce(String workSpace) { + String[] line = new String[3]; + line[0] = "rot"; + line[1] = "encrypt"; + for (int i=0; i<26; i++) { + line[2]=i.ToString(); + Console.Write(String.Format("{0,2}: {1}",i,Encrypt(workSpace,null,line))); + } + } + } +} diff --git a/captivecrypto.bash b/captivecrypto.bash new file mode 100644 index 0000000..fe7c597 --- /dev/null +++ b/captivecrypto.bash @@ -0,0 +1,9 @@ +#!/bin/bash + +if [ $(pgrep -afc cryptoworkbench.exe) -gt 10 ]; then + echo All slots used -- you\'ll have to wait. + sleep 5 + exit; +fi + +exec bash -c "time mono /opt/cryptoworkbench.exe --blind; read" diff --git a/chargrid.csharp b/chargrid.csharp new file mode 100644 index 0000000..6b74a8d --- /dev/null +++ b/chargrid.csharp @@ -0,0 +1,117 @@ +using System; +using System.Text; + +namespace AniNIX.Crypto { + + public class CharGrid { + + protected char[][] theGrid; + + /// + ///Use this to even out grids so that columnar transpositions can be regular. + /// + ///The String to pad + ///How wide the grid should be + ///A paddded string + public static String RandPad(String input, int width) { + Random sRand = new Random(); + int mod = input.Length%width; + if (mod == 0) return input; + char[] pad = new char[width-mod]; + for (int i=0; i width) ? width : remainingLength]; + remainingLength -= width; + for (int j=0; j < newGrid[i].Length; j++) { + newGrid[i][j] = input[k++]; + } + } + return newGrid; + } + + private char[][] MakeVGrid(int length, int width) { + int y = (length%width == 0) ? length/width : length/width+1; + char[][] newGrid = new char[y][]; + for (int i = 0; i < y; i++) { + newGrid[i] = new char[(length > width) ? width : length]; + length -= width; + } + return newGrid; + } + + /// + /// Make a horizontal grid from the input of certain width. Make regular if wanted. + /// + /// String to make from + /// How wide a grid to make + /// Should random padding be added to make this not a jagged array + public CharGrid(String input,int width,bool isRegular=false) { + if (isRegular) input = RandPad(input,width); + theGrid = MakeGrid(input,width); + } + + /// + /// Make a vertical grid from the input of certain width. Make regular if wanted. + /// + /// String to make from + /// How wide a grid to make + /// What order should the columns be populated in? + public CharGrid(String input,int width,int[] order) { + // Make a grid first. + theGrid = MakeVGrid(input.Length,width); + //Populate + int k = 0; + for (int j = 0; j < theGrid[0].Length; j++) { + for (int i = 0; i < theGrid.Length; i++) { + if (i != theGrid.Length-1 || order[j] < theGrid[i].Length) { + theGrid[i][order[j]] = input[k]; + k++; + } + } + } + + } + + public override String ToString() { + StringBuilder sb = new StringBuilder(); + sb.Append(String.Format("{0} {1} ------------->\n",theGrid.Length,theGrid[0].Length)); + for (int j=0; j + /// Create a new Cipher + /// + /// Cipher + public Cipher (Workbench w) { + string helpString = String.Format("{0} -- {1}\n",this.Command().PadRight(16),this.Description().Split('\n')[0]); + if (!w.HelpText.ToString().Contains(helpString)) { + w.HelpText.Append(helpString); + } + if (!w.SwitchCases.ContainsKey(this.Command())) { + w.SwitchCases.Add(this.Command(),this); + } + } + public Cipher() { + } + + /// + /// We should be able to act on a workspace and command line. Most ciphers will sue the same syntax. Those that don't can override. + /// + /// The current version of the text being worked on. + /// The command sequence. + /// The updated version of the workSpace + public virtual String RunCommand(String workSpace,String inputText,String[] line) { + if (workSpace == null || line == null || line.Length < 2) { + Console.Error.WriteLine("Malformed request."); + return workSpace; + } + switch (line[1]) { + case "encrypt": + return Encrypt(workSpace,inputText,line); + case "decrypt": + return Decrypt(workSpace,inputText,line); + case "help": + GetHelp(); + return workSpace; + default: + Console.Error.WriteLine("Invalid command. Type help for more."); + return workSpace; + } + } + + /// + /// Show the helptext for this cipher. By default, most ciphers will only have encrypt, decrypt, and help functions. + /// + /// This is the incoming line and we use it to get the cipher name + public virtual void GetHelp() { + Console.WriteLine(String.Format("Help for the {0} cipher suite.\n{1}\n",Command(),Description())); + Console.WriteLine("encrypt key -- encrypt with the key\ndecrypt key -- decrypt with the key\nhelp -- show this helptext."); + } + + /// + /// All ciphers must be able to encrypt a string. + /// + /// The current version of the text being worked on. + /// The command sequence. + /// The updated version of the workSpace + public abstract String Encrypt(string workSpace,String ciphetText,String[] line); + + /// + /// All ciphers must be able to decrypt a string. + /// + /// The current version of the text being worked on. + /// The command sequence. + /// The updated version of the workSpace + public abstract String Decrypt(String workSpace,String inputText,String[] line); + + } +} diff --git a/columntransposition.csharp b/columntransposition.csharp new file mode 100644 index 0000000..9872beb --- /dev/null +++ b/columntransposition.csharp @@ -0,0 +1,90 @@ +using System; +using System.IO; +using System.Text; +using System.Collections.Generic; + +namespace AniNIX.Crypto { + public class ColumnTransposition : Cipher { + + public override String Description() { return "Column Transposition cipher suite\nFormat is col key1 [key2...]\nThe key format is any word to use for the transposition.\nThis cipher will use an irregular columnar transposition, without padding the input string.\n"; } + public override String Command() { return "col"; } + + public ColumnTransposition(Workbench w) : base (w) {} + public ColumnTransposition() {} + + private int[] GetColumnOrder(String key) { + List orderList = new List(); + for (int i = 0; i < key.Length; i++) { + orderList.Add(key[i]); + } + orderList.Sort(); + char[] charArr = orderList.ToArray(); + int[] returnOrderIndexes = new int[key.Length]; + Console.Write("Found key order: "); + for (int i = 0; i < key.Length; i++) { + for (int j = 0; j < charArr.Length; j++) { + if (key[i] == charArr[j]) { + Console.Write(String.Format("{0} ",j+1)); + returnOrderIndexes[j] = i; + break; + } + } + } + Console.WriteLine(""); + return returnOrderIndexes; + } + + public override String Encrypt(String workSpace, String cipher, String[] line) { + if (line.Length < 3) { + Console.Error.WriteLine("Bad formatting."); + return workSpace; + } + String workSpaceNoNewline = workSpace.Replace("\n",""); + char[] changed = workSpaceNoNewline.ToCharArray(); + CharGrid cg = new CharGrid(workSpaceNoNewline,line[2].Length,false); + char[][] encryptionGrid = cg.ToArray(); + int[] keyOrder = GetColumnOrder(line[2]); + Console.Write(cg.ToString()); + int k = 0; + for (int j = 0; j < encryptionGrid[0].Length; j++) { + for (int i = 0; i < encryptionGrid.Length; i++) { + if (i != (encryptionGrid.Length-1) || keyOrder[j] < encryptionGrid[i].Length) { + changed[k] = encryptionGrid[i][keyOrder[j]]; + k++; + } + } + } + String toReturn = new String(changed); + for (k = 0; k < workSpace.Length; k++) { + if (workSpace[k] == '\n') { + toReturn = toReturn.Insert(k,"\n"); + } + } + return toReturn; + } + + // TODO + public override String Decrypt(String workSpace, String cipher, String[] line) { + if (line.Length < 3) { + Console.Error.WriteLine("Bad formatting."); + return workSpace; + } + String workSpaceNoNewline = workSpace.Replace("\n",""); + int[] keyOrder = GetColumnOrder(line[2]); + CharGrid cg = new CharGrid(workSpaceNoNewline,line[2].Length,keyOrder); + Console.Write(cg.ToString()); + char[][] cgArray = cg.ToArray(); + StringBuilder sb = new StringBuilder(); + for (int i=0; i < cgArray.Length; i++) { + sb.Append(new String(cgArray[i])); + } + String toReturn = sb.ToString(); + for (int i=0; i < workSpace.Length; i++) { + if (workSpace[i] == '\n') { + toReturn = toReturn.Insert(i,"\n"); + } + } + return toReturn; + } + } +} diff --git a/cryptoworkbench.csharp b/cryptoworkbench.csharp new file mode 100644 index 0000000..0b7f3d0 --- /dev/null +++ b/cryptoworkbench.csharp @@ -0,0 +1,254 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using System.Collections.Generic; +using AniNIX.TheRaven; + +namespace AniNIX.Crypto { + public class Workbench { + public string inputText { get; private set; } + public string workSpace { get; private set; } + public StringBuilder HelpText = new StringBuilder(); + public Dictionary SwitchCases = new Dictionary(); + private Substitution _sub; + private Analysis _analysis; + private Simple _simple; + private Caesarian _caesar; + private Affine _affine; + private Vigenere _vig; + private ColumnTransposition _col; + private Ubchi _ubchi; + private bool _isBlind = false; + + private void ReadCipher(String[] line) { + if (line == null || line.Length !=2) { + Console.WriteLine("Please paste your ciphertext."); + string readLn = Console.ReadLine(); + StringBuilder sb = new StringBuilder(); + while (readLn != null && !String.IsNullOrWhiteSpace((readLn))) { + sb.AppendLine(readLn); + readLn=Console.ReadLine(); + } + inputText = sb.ToString().Trim(); + } else { + try { + StringBuilder sb = new StringBuilder(); + StreamReader fileReader = new StreamReader(line[1]); + String lineR = fileReader.ReadLine(); + while (lineR != null) { + sb.AppendLine(lineR); + lineR = fileReader.ReadLine(); + } + fileReader.Dispose(); + fileReader = null; + inputText = sb.ToString().Trim(); + Console.WriteLine(String.Format("Read {0}",line[1])); + } + catch (Exception e) { + Console.Error.WriteLine(e.Message); + inputText = null; + } + + } + workSpace = inputText; + + } + + public Workbench(string[] args) { + if (args.Length == 0) { + ReadCipher(null); + } else if (args.Length == 1) { + if (args[0].Equals("--blind")) { + this._isBlind = true; + ReadCipher(null); + } else { + String[] line = new String[2]; + line[0] = "reread"; + line[1] = args[0]; + ReadCipher(line); + } + } else { + Console.Error.WriteLine("The only argument allowed is a filename containing the ciphertext or --blind to block filesystem access."); + System.Environment.Exit(1); + } + HelpText.Append("You can get help on any command by running \" help\".\nSuppress printing the cipher with a trailing ;.\nAvailable commands:\n"); + if (!_isBlind) { + HelpText.Append("reread -- Read in a new cipher\n"); + HelpText.Append("write -- write the workspace to a file\n"); + } + HelpText.Append("regex -- Check for strings with the two regex arguments: [search] [filter]\n"); + HelpText.Append("reset -- reset workspace to the ciphertext.\n"); + HelpText.Append("links -- show some helpful links\n"); + HelpText.Append("help -- show this HelpText\n"); + HelpText.Append("exit -- exit and show the result.\n"); + HelpText.Append("quit -- alias of exit.\n"); + _sub = new Substitution(this); + _analysis = new Analysis(this); + _simple = new Simple(this); + _caesar = new Caesarian(this); + _affine = new Affine(this); + _vig = new Vigenere(this); + _col = new ColumnTransposition(this); + _ubchi = new Ubchi(this); + + } + + public override String ToString() { + StringBuilder currentStatus = new StringBuilder(); + currentStatus.Append("Input:\n"); + currentStatus.Append(this.inputText); + currentStatus.Append("\n"); + currentStatus.Append("Workspace:\n"); + currentStatus.Append(this.workSpace); + return currentStatus.ToString(); + } + + public void Print() { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("Input:"); + Console.ResetColor(); + Console.WriteLine(this.inputText); + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("Workspace:"); + Console.ResetColor(); + List topletters = Analysis.GetMostCommonLetters(workSpace).Take(5).ToList();//cyan + List bigrams = Analysis.Top(Analysis.GetSubstrings(workSpace,2)); //yellow + List trigrams = Analysis.Top(Analysis.GetSubstrings(workSpace,3));//magenta + for (int i = 0; i < workSpace.Length; i++) { + if (i < workSpace.Length-1 && workSpace[i] == workSpace[i+1]) { + Console.ForegroundColor = ConsoleColor.Green; + Console.Write(workSpace[i++]); + + } else if (i < workSpace.Length-2 && trigrams.Contains(workSpace.Substring(i,3))) { + Console.ForegroundColor = ConsoleColor.Magenta; + Console.Write(workSpace[i++]); + Console.Write(workSpace[i++]); + } else if (i < workSpace.Length-1 && bigrams.Contains(workSpace.Substring(i,2))) { + Console.ForegroundColor = ConsoleColor.Yellow; + Console.Write(workSpace[i++]); + } else if (topletters.Contains(workSpace[i].ToString())) { + Console.ForegroundColor = ConsoleColor.Cyan; + } + Console.Write(workSpace[i]); + Console.ResetColor(); + } + Console.WriteLine(); + } + + public static void HelpfulLinks() { + StringBuilder linksText = new StringBuilder(); + linksText.Append("http://www.visca.com/regexdict/ -- RegEx word dictionary\n"); + linksText.Append("http://rumkin.com/tools/cipher/ -- Cipher tools\n"); + linksText.Append("http://norvig.com/mayzner.html -- Frequency analysis\n"); + Console.Write(linksText.ToString()); + } + + public void WriteWorkspace(String workSpace, String[] line) { + if (line == null || line.Length != 2) { + Console.Error.WriteLine("Need a file."); + return; + } + try { + StreamWriter fileWriter = new StreamWriter(line[1],false); + fileWriter.WriteLine(workSpace); + fileWriter.Dispose(); + fileWriter = null; + Console.WriteLine(String.Format("Wrote file {0}",line[1])); + } catch (Exception e) { + Console.WriteLine(String.Format("Couldn't write file.\n{0}",e.Message)); + } + } + + public void Run() { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("### Welcome to the AniNIX::CryptoWorkbench ###"); + Console.ResetColor(); + try { + string command = "help"; + string read = "help"; + string[] line; + bool showCipher=true; + + while (command != "exit" && command != "quit") { + foreach (String executable in read.Split(';')) { + if (String.IsNullOrWhiteSpace(executable)) { + showCipher = false; + continue; + } + + showCipher = true; + line = executable.Trim().Split(' '); + command = line[0]; + switch (command) { + case "reread": + if (!_isBlind) ReadCipher(line); + break; + case "write": + if (!_isBlind) WriteWorkspace(workSpace,line); + break; + case "reset": + this.workSpace = this.inputText; + Console.Clear(); + Console.WriteLine("Reset."); + break; + case "links": + HelpfulLinks(); + break; + case "regex": + try { + if (line.Length == 3) { + Console.Write(RavenExecute.Command(String.Format("bash /usr/local/src/CryptoWorkbench/regex-lookup.bash \"{0}\" \"{1}\"",line[1].Replace("\\","\\\\").Replace("$","\\$"),line[2].Replace("\\","\\\\").Replace("$","\\$")))); + } else if (line.Length == 2) { + Console.Write(RavenExecute.Command(String.Format("bash /usr/local/src/CryptoWorkbench/regex-lookup.bash \"{0}\"",line[1].Replace("\\","\\\\").Replace("$","\\$")))); + } else { + Console.Error.WriteLine("Need at least one search term."); + } + } catch (Exception e) { + Console.Error.WriteLine(e.ToString()); + } + break; + case "help": + Console.WriteLine(HelpText.ToString()); + break; + case "exit": + case "quit": + throw new Exception(""); + default: + try { + workSpace = SwitchCases[command].RunCommand(this.workSpace,this.inputText,line); + } catch (Exception e) { + Console.Error.WriteLine("Command not found."); + } + break; + } + } + if (showCipher) Print(); + Console.Write("\nWhat command would you like to execute?\n"); + Console.ForegroundColor = ConsoleColor.Red; + Console.Write("|"); + Console.ResetColor(); + Console.Write("> "); + read = Console.ReadLine().Trim(); + } + } catch (Exception e) { + Console.Error.WriteLine(e.Message); + } + + finally { + Console.WriteLine("\nFinal result:"); + this.Print(); + } + } + + public static void Main(string[] args) { + Workbench cw = new Workbench(args); + try { + cw.Run(); + } catch (NullReferenceException e) { + Console.Error.WriteLine(String.Format("Caught {0}",e.GetType().ToString())); + } + } + } +} + diff --git a/newcipher.template b/newcipher.template new file mode 100644 index 0000000..cba9edc --- /dev/null +++ b/newcipher.template @@ -0,0 +1,23 @@ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections.Generic; + +namespace AniNIX.Crypto { + public class Template : Cipher { + + public override String Description() { return ; } + public override String Command() {return ;} + public Template(Workbench w) : base (w) {} + + public override String Encrypt(String workSpace,String inputText,String[] line) { + return new String(changed); + } + + public override String Decrypt(String workSpace,String inputText,String[] line) { + return new String(changed); + } + + } +} diff --git a/ravenexecute.csharp b/ravenexecute.csharp new file mode 100644 index 0000000..ad24027 --- /dev/null +++ b/ravenexecute.csharp @@ -0,0 +1,58 @@ +using System; +using System.IO; +using System.Text; +using System.Diagnostics; +using System.Collections.Generic; + +namespace AniNIX.TheRaven { + + public static class RavenExecute { + + /// + /// This method allows TheRaven to execute a command on the OS. + /// + /// The command string to run as the string argument to "bash -c 'command'" + /// The effective replacement for the command's stdinThe stdout of the command + /// + public static String Command(String command, String input) { + //Sanitize inputs. + if (command.Contains("\'")) { + throw new Exception("Command strings cannot include \'."); + } + + //Create process. + Process proc = new Process(); + proc.StartInfo.CreateNoWindow = true; + proc.StartInfo.FileName = "/bin/bash"; + proc.StartInfo.Arguments = String.Format("-c \'{0}\'",command); + proc.StartInfo.UseShellExecute=false; + + //Redirect input + proc.StartInfo.RedirectStandardOutput=true; + proc.StartInfo.RedirectStandardInput=true; + + //Start process + proc.Start(); + + //Add input and read output. + proc.StandardInput.Write(input); + proc.StandardInput.Close(); + proc.WaitForExit(); + if (proc.ExitCode != 0) { + throw new Exception(String.Format("Failed to exit command with return code {0}",proc.ExitCode)); + } + String stdoutString = proc.StandardOutput.ReadToEnd(); + + //Close up and return + proc.Close(); + return stdoutString; + } + + //Add polymorphism to allow no stdin + public static String Command(String command) { + return Command(command,null); + } + + } +} diff --git a/regex-lookup.bash b/regex-lookup.bash new file mode 100644 index 0000000..573ce8a --- /dev/null +++ b/regex-lookup.bash @@ -0,0 +1,14 @@ +#!/bin/bash + +if [ ! -x /usr/bin/curl ]; then + echo No curl installed! + exit 1 +fi + +if [ "$1" == "" ]; then + echo "Usage: $0 [search] [optional filter]" + exit 1 +fi +export bashstr="$(printf "curl -s --data 'str=%s&fstr=%s&ifun=if&ccg=all&search=Search' http://www.visca.com/regexdict/" "$1" "$2")" +bash -c "$bashstr" | egrep 'any matches|yourdictionary' | cut -f 2 -d '>' | cut -f 1 -d '<' + diff --git a/sample.txt b/sample.txt new file mode 100644 index 0000000..56adc7c --- /dev/null +++ b/sample.txt @@ -0,0 +1,3 @@ +ABCDEFGHIJKLMNOPQRSTUVWXYZ +abcdefghijklmnopqrstuvwxyz +. ;:-_+=!@#$%^&*)({}[]\/?<> diff --git a/simple.csharp b/simple.csharp new file mode 100644 index 0000000..df33959 --- /dev/null +++ b/simple.csharp @@ -0,0 +1,90 @@ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections.Generic; + +namespace AniNIX.Crypto { + public class Simple : Cipher { + //Cipher description to be set by each cipher. + public override String Description() { return "This is a suite of simple text ops."; } + public override String Command() { return "simple"; } + + public Simple(Workbench w) : base (w) {} + + /// + /// We should be able to act on a workspace and command line. Most ciphers will sue the same syntax. Those that don't can override. + /// + /// The current version of the text being worked on. + /// The command sequence. + /// The updated version of the workSpace + public override String RunCommand(String workSpace,String inputText,String[] line) { + if (workSpace == null || line == null || line.Length < 2) { + Console.Error.WriteLine("Malformed request."); + return workSpace; + } + switch (line[1]) { + case "shiftup": + return ShiftUpper(workSpace); + case "shiftdown": + return ShiftLower(workSpace); + case "stripspace": + return StripSpaces(workSpace); + case "reverse": + return ReverseString(workSpace); + case "help": + GetHelp(); + return workSpace; + default: + Console.Error.WriteLine("Invalid command. Type help for more."); + return workSpace; + } + } + + /// + /// Show the helptext for this cipher. By default, most ciphers will only have encrypt, decrypt, and help functions. + /// + /// This is the incoming line and we use it to get the cipher name + public override void GetHelp() { + Console.WriteLine(String.Format("Help for the {0} cipher suite.\n{1}\n",Command(),Description())); + Console.WriteLine("shiftup -- Make all uppercase\nshiftdown -- make all lowercase\nstripspace -- strip spaces from String\nreverse -- reverse the string\nhelp -- show this helptext."); + } + + + public String ShiftUpper(String workSpace) { + char[] changed = workSpace.ToCharArray(); + for (int i = 0; i < changed.Length; i++) { + if (Char.IsLower(changed[i])) { + changed[i] = Char.ToUpper(changed[i]); + } + } + return new String(changed); + } + + public String ShiftLower(String workSpace) { + char[] changed = workSpace.ToCharArray(); + for (int i = 0; i < changed.Length; i++) { + if (Char.IsUpper(changed[i])) { + changed[i] = Char.ToLower(changed[i]); + } + } + return new String(changed); + } + + public String StripSpaces(String workSpace) { + String changed = workSpace.Replace(" ",""); + return changed; + } + + public String ReverseString(String workSpace) { + char[] charArray = workSpace.ToCharArray(); + Array.Reverse(charArray); + return new String(charArray); + } + + + //Simple doesn't handle encryption or decryption, but we want to use the same code for subscribing. + public override String Encrypt(string workSpace,String ciphetText,String[] line) { return workSpace; } + public override String Decrypt(string workSpace,String ciphetText,String[] line) { return workSpace; } + } +} diff --git a/substitution.csharp b/substitution.csharp new file mode 100644 index 0000000..c3a1681 --- /dev/null +++ b/substitution.csharp @@ -0,0 +1,102 @@ +using System; +using System.IO; +using System.Text; +using System.Collections.Generic; + +namespace AniNIX.Crypto { + public class Substitution : Cipher { + + public char[] EngCommon = {'e','t','a','o','i','n','s','h','r','d','l','u','c','m','w','f','y','g','p','b','v','k','x','j','q','z'}; + + public override String Description() { return "Subsitution cipher suite\nKey format is \"E[EEE]=d[ddd]\", where E is the character in the cipher and d is the intended character in the workspace."; } + public override String Command() { return "sub"; } + + public Substitution(Workbench w) : base (w) {} + + /// + /// We should be able to act on a workspace and command line. Most ciphers will sue the same syntax. Those that don't can override. + /// + /// The current version of the text being worked on. + /// The command sequence. + /// The updated version of the workSpace + public override String RunCommand(String workSpace,String inputText,String[] line) { + if (workSpace == null || line == null || line.Length < 2) { + Console.Error.WriteLine("Malformed request."); + return workSpace; + } + switch (line[1]) { + case "encrypt": + return Encrypt(workSpace,inputText,line); + case "decrypt": + return Decrypt(workSpace,inputText,line); + case "try-common": + return TryCommon(inputText); + case "help": + GetHelp(); + return workSpace; + default: + Console.Error.WriteLine("Invalid command. Type help for more."); + return workSpace; + } + } + + /// + /// Show the helptext for this cipher. By default, most ciphers will only have encrypt, decrypt, and help functions. + /// + /// This is the incoming line and we use it to get the cipher name + public override void GetHelp() { + Console.WriteLine(String.Format("Help for the {0} cipher suite.\n{1}\n",Command(),Description())); + Console.WriteLine("encrypt key[s] -- encrypt with the key[s]\ndecrypt key[s] -- decrypt with the key[s]\ntry-common -- try common sub keys\nhelp -- show this helptext."); + } + + public override String Encrypt(String workSpace, String cipher, String[] line) { + if (line.Length < 3) { + Console.Error.WriteLine("Bad formatting."); + return workSpace; + } + char[] changed = workSpace.ToCharArray(); + for (int i=2; i sortedChars = Analysis.GetMostCommonLetters(workSpace.ToLower()); + char[] modified = workSpace.ToLower().ToCharArray(); + char replaceChar; + for (int i = 0; i < modified.Length; i++) { + if (!Char.IsLetter(modified[i])) { continue; } + Console.WriteLine(String.Format("Character <{0}> occurs {1}st in frequency, corresponding with <{2}> -- replacing...", + modified[i], + sortedChars.IndexOf(modified[i].ToString()), + EngCommon[sortedChars.IndexOf(modified[i].ToString())])); + replaceChar = EngCommon[sortedChars.IndexOf(modified[i].ToString())]; + replaceChar = (workSpace[i] == Char.ToLower(workSpace[i])) ? replaceChar : Char.ToUpper(replaceChar); + modified[i] = replaceChar; + } + return new String(modified); + } + } +} diff --git a/ubchi.csharp b/ubchi.csharp new file mode 100644 index 0000000..491ea43 --- /dev/null +++ b/ubchi.csharp @@ -0,0 +1,39 @@ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections.Generic; + +namespace AniNIX.Crypto { + public class Ubchi : Cipher { + + public override String Description() { return "The Ubchi cipher\nThis is a regular double-transposition cipher -- it will add some garbage to the end of your string.\nKey format is any word to use for the transposition.\nNOTE: This does not completely match Rumkin, whose implementation is a little flawed."; } + public override String Command() { return "ubchi"; } + + public Ubchi(Workbench w) : base (w) {} + + private ColumnTransposition col = new ColumnTransposition(); + + public override String Encrypt(String workSpace,String inputText,String[] line) { + if (line == null || line.Length != 3) { + Console.Error.WriteLine("Malformed!"); + return workSpace; + } + String changed = CharGrid.RandPad(workSpace,line[2].Length); + changed = col.Encrypt(changed,inputText,line); + changed = col.Encrypt(changed,inputText,line); + return changed; + } + + public override String Decrypt(String workSpace,String inputText,String[] line) { + if (line == null || line.Length != 3) { + Console.Error.WriteLine("Malformed!"); + return workSpace; + } + String changed = col.Decrypt(workSpace,inputText,line); + changed = col.Decrypt(changed,inputText,line); + return changed; // TODO Remove padding + } + + } +} diff --git a/vigenere.csharp b/vigenere.csharp new file mode 100644 index 0000000..8ca0de4 --- /dev/null +++ b/vigenere.csharp @@ -0,0 +1,77 @@ +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections.Generic; + +namespace AniNIX.Crypto { + public class Vigenere : Cipher { + + public override String Description() { return "The basic Vigenere cipher\nKey format is any word to use for the passphrase"; } + public override String Command() { return "vig"; } + + public Vigenere(Workbench w) : base (w) {} + + public override String Encrypt(String workSpace,String inputText,String[] line) { + if (line == null || line.Length != 3) { + Console.Error.WriteLine("Malformed!"); + return workSpace; + } + char[] changed = workSpace.ToCharArray(); + try { + // line[2] is the key + int index = 0; + for (int i =0; i < line[2].Length; i++) { + if (!Char.IsLetter(line[2][i])) { + Console.Error.WriteLine("Keys must be only letters."); + return workSpace; + } + } + for (int i = 0; i < changed.Length; i++) { + if (Char.IsLetter(changed[i])) { + int baseC = (Char.IsUpper(changed[i])) ? (int)'A' : (int)'a'; + int modC = (int)changed[i] - baseC; + int baseK = (Char.IsUpper(line[2][index])) ? (int)'A' : (int)'a'; + int modK = (int)line[2][index] - baseK; + changed[i] = (char)(((modC+modK)%26)+baseC); + index = (index+1)%(line[2].Length); + } + } + } catch (Exception e) { + Console.Error.WriteLine(String.Format("Failed!\n{0}",e.Message)); + return workSpace; + } + return new String(changed); + } + + public override String Decrypt(String workSpace,String inputText,String[] line) { + if (line == null || line.Length != 3) { + Console.Error.WriteLine("Malformed!"); + return workSpace; + } + char[] changed = workSpace.ToCharArray(); + try { + // line[2] is the key + int index=0; + for (int i = 0; i < changed.Length; i++) { + if (Char.IsLetter(changed[i])) { + int baseC = (Char.IsUpper(changed[i])) ? (int)'A' : (int)'a'; + int modC = (int)changed[i] - baseC; + int baseK = (Char.IsUpper(line[2][index])) ? (int)'A' : (int)'a'; + int modK = (int)line[2][index] - baseK; + int modResult = (modC - modK)%26; + modResult = (modResult < 0) ? modResult+26 : modResult; // In case modResult is negative, add 26 back + changed[i] = (char)(modResult+baseC); + index = (index+1)%(line[2].Length); + } + } + } catch (Exception e) { + Console.Error.WriteLine(String.Format("Failed!\n{0}",e.Message)); + return workSpace; + } + return new String(changed); + + } + + } +}