/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace wasSharp { public static class Cryptography { /////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Encrypt or decrypt a message given a set of rotors, plugs and a reflector. /// /// the message to encyrpt or decrypt /// any combination of: 1, 2, 3, 4, 5, 6, 7, 8, b, g /// the letter representing the start character for the rotor /// any one of: B, b, C, c /// either a decrypted or encrypted string public static string ENIGMA(string message, char[] rotors, char[] plugs, char reflector) { var def_rotors = new Dictionary { { '1', new[] { 'e', 'k', 'm', 'f', 'l', 'g', 'd', 'q', 'v', 'z', 'n', 't', 'o', 'w', 'y', 'h', 'x', 'u', 's', 'p', 'a', 'i', 'b', 'r', 'c', 'j' } }, { '2', new[] { 'a', 'j', 'd', 'k', 's', 'i', 'r', 'u', 'x', 'b', 'l', 'h', 'w', 't', 'm', 'c', 'q', 'g', 'z', 'n', 'p', 'y', 'f', 'v', 'o', 'e' } }, { '3', new[] { 'b', 'd', 'f', 'h', 'j', 'l', 'c', 'p', 'r', 't', 'x', 'v', 'z', 'n', 'y', 'e', 'i', 'w', 'g', 'a', 'k', 'm', 'u', 's', 'q', 'o' } }, { '4', new[] { 'e', 's', 'o', 'v', 'p', 'z', 'j', 'a', 'y', 'q', 'u', 'i', 'r', 'h', 'x', 'l', 'n', 'f', 't', 'g', 'k', 'd', 'c', 'm', 'w', 'b' } }, { '5', new[] { 'v', 'z', 'b', 'r', 'g', 'i', 't', 'y', 'u', 'p', 's', 'd', 'n', 'h', 'l', 'x', 'a', 'w', 'm', 'j', 'q', 'o', 'f', 'e', 'c', 'k' } }, { '6', new[] { 'j', 'p', 'g', 'v', 'o', 'u', 'm', 'f', 'y', 'q', 'b', 'e', 'n', 'h', 'z', 'r', 'd', 'k', 'a', 's', 'x', 'l', 'i', 'c', 't', 'w' } }, { '7', new[] { 'n', 'z', 'j', 'h', 'g', 'r', 'c', 'x', 'm', 'y', 's', 'w', 'b', 'o', 'u', 'f', 'a', 'i', 'v', 'l', 'p', 'e', 'k', 'q', 'd', 't' } }, { '8', new[] { 'f', 'k', 'q', 'h', 't', 'l', 'x', 'o', 'c', 'b', 'j', 's', 'p', 'd', 'z', 'r', 'a', 'm', 'e', 'w', 'n', 'i', 'u', 'y', 'g', 'v' } }, { 'b', new[] { 'l', 'e', 'y', 'j', 'v', 'c', 'n', 'i', 'x', 'w', 'p', 'b', 'q', 'm', 'd', 'r', 't', 'a', 'k', 'z', 'g', 'f', 'u', 'h', 'o', 's' } }, { 'g', new[] { 'f', 's', 'o', 'k', 'a', 'n', 'u', 'e', 'r', 'h', 'm', 'b', 't', 'i', 'y', 'c', 'w', 'l', 'q', 'p', 'z', 'x', 'v', 'g', 'j', 'd' } } }; var def_reflectors = new Dictionary { { 'B', new[] { 'a', 'y', 'b', 'r', 'c', 'u', 'd', 'h', 'e', 'q', 'f', 's', 'g', 'l', 'i', 'p', 'j', 'x', 'k', 'n', 'm', 'o', 't', 'z', 'v', 'w' } }, { 'b', new[] { 'a', 'e', 'b', 'n', 'c', 'k', 'd', 'q', 'f', 'u', 'g', 'y', 'h', 'w', 'i', 'j', 'l', 'o', 'm', 'p', 'r', 'x', 's', 'z', 't', 'v' } }, { 'C', new[] { 'a', 'f', 'b', 'v', 'c', 'p', 'd', 'j', 'e', 'i', 'g', 'o', 'h', 'y', 'k', 'r', 'l', 'z', 'm', 'x', 'n', 'w', 't', 'q', 's', 'u' } }, { 'c', new[] { 'a', 'r', 'b', 'd', 'c', 'o', 'e', 'j', 'f', 'n', 'g', 't', 'h', 'k', 'i', 'v', 'l', 'm', 'p', 'w', 'q', 'z', 's', 'x', 'u', 'y' } } }; // Setup rotors from plugs. foreach (var rotor in rotors) { var plug = plugs[Array.IndexOf(rotors, rotor)]; var i = Array.IndexOf(def_rotors[rotor], plug); if (i.Equals(0)) continue; def_rotors[rotor] = Arrays.ConcatenateArrays(new[] { plug }, Arrays.GetSubArray(Arrays.DeleteSubArray(def_rotors[rotor], i, i), i, -1), Arrays.GetSubArray(Arrays.DeleteSubArray(def_rotors[rotor], i + 1, -1), 0, i - 1)); } var result = new StringBuilder(); foreach (var c in message) { if (!char.IsLetter(c)) { result.Append(c); continue; } // Normalize to lower. var l = char.ToLower(c); Action rotate = o => { var i = o.Length - 1; do { def_rotors[o[0]] = Arrays.ForwardPermuteArrayElements(def_rotors[o[0]], 1); if (i.Equals(0)) { rotors = Arrays.ReversePermuteArrayElements(o, 1); continue; } l = Arrays.GetElementAt(def_rotors[o[1]], Array.IndexOf(def_rotors[o[0]], l) - 1); o = Arrays.ReversePermuteArrayElements(o, 1); } while (--i > -1); }; // Forward pass through the Enigma's rotors. rotate.Invoke(rotors); // Reflect var x = Array.IndexOf(def_reflectors[reflector], l); l = (x + 1) % 2 == 0 ? def_reflectors[reflector][x - 1] : def_reflectors[reflector][x + 1]; // Reverse the order of the rotors. Array.Reverse(rotors); // Reverse pass through the Enigma's rotors. rotate.Invoke(rotors); if (char.IsUpper(c)) { l = char.ToUpper(l); } result.Append(l); } return result.ToString(); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Expand the VIGENRE key to the length of the input. /// /// the input to expand to /// the key to expand /// the expanded key public static string VIGENEREExpandKey(string input, string enc_key) { var exp_key = string.Empty; int i = 0, j = 0; do { var p = input[i]; if (!char.IsLetter(p)) { exp_key += p; ++i; continue; } var m = j % enc_key.Length; exp_key += enc_key[m]; ++j; ++i; } while (i < input.Length); return exp_key; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Encrypt using VIGENERE. /// /// the input to encrypt /// the key to encrypt with /// the encrypted input public static string EncryptVIGENERE(string input, string enc_key) { char[] a = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; enc_key = VIGENEREExpandKey(input, enc_key); var result = string.Empty; var i = 0; do { var p = input[i]; if (!char.IsLetter(p)) { result += p; ++i; continue; } var q = Arrays.ReversePermuteArrayElements(a, Array.IndexOf(a, enc_key[i]))[ Array.IndexOf(a, char.ToLowerInvariant(p))]; if (char.IsUpper(p)) { q = char.ToUpperInvariant(q); } result += q; ++i; } while (i < input.Length); return result; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Decrypt using VIGENERE. /// /// the input to decrypt /// the key to decrypt with /// the decrypted input public static string DecryptVIGENERE(string input, string enc_key) { char[] a = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; enc_key = VIGENEREExpandKey(input, enc_key); var result = string.Empty; var i = 0; do { var p = input[i]; if (!char.IsLetter(p)) { result += p; ++i; continue; } var q = a[ Array.IndexOf(Arrays.ReversePermuteArrayElements(a, Array.IndexOf(a, enc_key[i])), char.ToLowerInvariant(p))]; if (char.IsUpper(p)) { q = char.ToUpperInvariant(q); } result += q; ++i; } while (i < input.Length); return result; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// An implementation of the ATBASH cypher for latin alphabets. /// /// the data to encrypt or decrypt /// the encrypted or decrypted data public static string ATBASH(string data) { char[] a = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; var input = data.ToCharArray(); Parallel.ForEach(Enumerable.Range(0, data.Length), i => { var e = input[i]; if (!char.IsLetter(e)) return; var x = 25 - Array.BinarySearch(a, char.ToLowerInvariant(e)); if (!char.IsUpper(e)) { input[i] = a[x]; return; } input[i] = char.ToUpperInvariant(a[x]); }); return new string(input); } } }