commit 65dbd8cae2ecfbed099cf2196522ee8dd7ac0015 Author: cxford Date: Thu Aug 4 12:10:50 2016 -0500 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. 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); + + } + + } +}