/Cryptography/Cryptography.cs |
@@ -0,0 +1,395 @@ |
/////////////////////////////////////////////////////////////////////////// |
// 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 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Encrypt or decrypt a message given a set of rotors, plugs and a reflector. |
/// </summary> |
/// <param name="message">the message to encyrpt or decrypt</param> |
/// <param name="rotors">any combination of: 1, 2, 3, 4, 5, 6, 7, 8, b, g</param> |
/// <param name="plugs">the letter representing the start character for the rotor</param> |
/// <param name="reflector">any one of: B, b, C, c</param> |
/// <returns>either a decrypted or encrypted string</returns> |
public static string ENIGMA(string message, char[] rotors, char[] plugs, char reflector) |
{ |
var def_rotors = new Dictionary<char, char[]> |
{ |
{ |
'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<char, char[]> |
{ |
{ |
'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<char[]> 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 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Expand the VIGENRE key to the length of the input. |
/// </summary> |
/// <param name="input">the input to expand to</param> |
/// <param name="enc_key">the key to expand</param> |
/// <returns>the expanded key</returns> |
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 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Encrypt using VIGENERE. |
/// </summary> |
/// <param name="input">the input to encrypt</param> |
/// <param name="enc_key">the key to encrypt with</param> |
/// <returns>the encrypted input</returns> |
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 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Decrypt using VIGENERE. |
/// </summary> |
/// <param name="input">the input to decrypt</param> |
/// <param name="enc_key">the key to decrypt with</param> |
/// <returns>the decrypted input</returns> |
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 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// An implementation of the ATBASH cypher for latin alphabets. |
/// </summary> |
/// <param name="data">the data to encrypt or decrypt</param> |
/// <returns>the encrypted or decrypted data</returns> |
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); |
} |
} |
} |