From 239963273242004426adcaf902459a9e1531ab1a Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Thu, 15 Jan 2009 17:19:59 +0100 Subject: C# implementation of A5/1. --- A5.1/C#/A5/A5Engine.cs | 443 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 443 insertions(+) create mode 100644 A5.1/C#/A5/A5Engine.cs (limited to 'A5.1/C#/A5/A5Engine.cs') diff --git a/A5.1/C#/A5/A5Engine.cs b/A5.1/C#/A5/A5Engine.cs new file mode 100644 index 0000000..040c245 --- /dev/null +++ b/A5.1/C#/A5/A5Engine.cs @@ -0,0 +1,443 @@ +/* + * A5/1 Implementation + * + * Information: http://en.wikipedia.org/wiki/A5/1 + * Released : 24/10/2008 + * App Options: -d (Debugging mode) + * + * Written by : Brett Gervasoni (brett.gervasoni [at] gmail.com) + * Thanks to : Angus McMahon (angusmcmahon [at] gmail.com) + * + * Notes: + * - Debugging mode will show step by step processes + * - The code has been designed to be easily expandable, so that more secure + * versions of the A5 family can be introduced. + * - Various properties of the A5Engine class can be modified + * - If order matters then put things in order to begin with! + * Polynomials, clocking bits, and maximum register lengths. + * - If data is not in order the application will try its best to make + * the cipher work. + * - Polynomials for each register are chosen based on their largest exponent + * being less than register length. + * + * Instructions: + * numRegisters = The number of registers to use + * maxRegLens = The max register length for each register + * regIndexes = The clocking bits for each register + * polynomialsArray = The polynomials to use for each register + * sourceArray = Random binary bits + * */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace A5 +{ + class A5Engine + { + public bool dbMode; //Debug mode + + private int nRegisters; //number of registers + private int[] mRegLens; //max register lengths + private int[] sArray; //source array + private int[] rIndexes; //register indexes (clocking bits) + private string[] pArray; //polynomials + private int[][] registers; //registers + + private int[][] uExponents; //exponents being used + + /* --- Setting properties --- */ + public int numRegisters + { + get + { return nRegisters; } + set + { nRegisters = value; } + } + + public int[] maxRegLens + { + get + { return mRegLens; } + set + { mRegLens = value; } + } + + public int[] sourceArray + { + get + { return sArray; } + set + { sArray = value; } + } + + public int[] regIndexes + { + get + { return rIndexes; } + set + { rIndexes = value; } + } + + public string[] polynomialsArray + { + get + { return pArray; } + set + { pArray = value; } + } + + public int[][] Registers + { + get + { return registers; } + set + { registers = value; } + } + + /* --- Begin methods ---*/ + private void slowText(string message) + { + foreach (char c in message.ToCharArray()) + { + Console.Write(c); + System.Threading.Thread.Sleep(60); + } + + Console.WriteLine(); + } + + public void Intro() + { + string message = "#################################################################\n"; + message += "# A5/1 Implementation #\n"; + message += "# #\n"; + message += "# Information: http://en.wikipedia.org/wiki/A5/1 #\n"; + message += "# Released: 24th October 2008 #\n"; + message += "# App Options: -d [NumOfLoops] (Debugging mode) #\n"; + message += "# #\n"; + message += "# Written By: Brett Gervasoni (brett.gervasoni [at] gmail.com) #\n"; + message += "#################################################################\n"; + + Console.WriteLine(message); + + string matrix = "Now you will see how deep the rabit hole really goes..."; + slowText(matrix); + + System.Threading.Thread.Sleep(2500); + } + + public int GetMaxRegLensTotal() + { + int total = 0; + + foreach (int len in mRegLens) + total += len; + + return total; + } + + private int XorValues(int val1, int val2) + { + int res = 0; + + if (val1 != val2) + res = 1; + + return res; + } + + private int XorRegValues(int[] vToXor) + { + int final = 0; + + for (int i = 0; i < vToXor.Length; i++) + final = XorValues(final, vToXor[i]); + + return final; + } + + private int[][] RemoveIntArrElement(int[][] oArray, int index) + { + int[][] nArray = new int[oArray.Length-1][]; + + for (int i = 0; i < oArray.Length; i++) + { + if (i != index) + { + nArray[i-1] = new int[oArray[i].Length]; + for (int x = 0; x < oArray[i].Length; x++) + { + nArray[i-1][x] = oArray[i][x]; + } + } + } + + return nArray; + } + + private int[][] ExtractPolyExponents(string[] polynomialsArray) + { + int[][] exponents = new int[polynomialsArray.Length][]; + + for (int i = 0; i < polynomialsArray.Length; i++) + { + Regex expression = new Regex(@"x\^(\d+)"); + MatchCollection polyMatches = expression.Matches(polynomialsArray[i]); + + exponents[i] = new int[polyMatches.Count]; + + for (int x = 0; x < polyMatches.Count; x++) + { + //Console.WriteLine(polyMatches[x].Groups[1].ToString()); + exponents[i][x] = int.Parse(polyMatches[x].Groups[1].ToString()); + } + } + + return exponents; + } + + private int FindLargestInt(int[] intArray) + { + int largest = 0; + + foreach (int num in intArray) + { + if (num > largest) + largest = num; + } + + return largest; + } + + private int[][] PolySelection() + { + int[][] exponents = ExtractPolyExponents(pArray); + int[][] usingPolynomials = new int[nRegisters][]; + + int counter = 0; + int j = 0; //since i variable is reset + for (int i = 0; i < exponents.Length; i++) + { + if (counter == nRegisters) + break; + + int largest = FindLargestInt(exponents[i]); + + if (largest < mRegLens[j]) + { + usingPolynomials[counter] = new int[exponents[i].Length]; + + for (int x = 0; x < exponents[i].Length; x++) + usingPolynomials[counter][x] = exponents[i][x]; + + exponents = RemoveIntArrElement(exponents, i); + + i = -1; //reset loop + counter++; + } + + j++; + } + + return usingPolynomials; + } + + private int[] RegisterFill(int offset, int regNum) + { + int[] outArray = new int[regNum]; + + for (int i = 0; i < regNum; i++) + { + outArray[i] = sArray[offset + i]; + } + + return outArray; + } + + private int[] GetIndexValues() + { + int[] indexValues = new int[registers.Length]; + + for (int i = 0; i < registers.Length; i++) + { + indexValues[i] = registers[i][rIndexes[i]]; + } + + return indexValues; + } + + private int[] FindFrequency(int[] indexValues) + { + int[] tally = new int[2]; //size of 2 since its just binary + + foreach (int val in indexValues) + { + if (val == 0) + tally[0]++; + else if (val == 1) + tally[1]++; + } + + return tally; + } + + public int[][] CreateRegisters() + { + int[][] filledRegisters = new int[nRegisters][]; + int offset = 0; + + //Does source array have enough data to fill? + if (GetMaxRegLensTotal() <= sArray.Length) + { + for (int i = 0; i < nRegisters; i++) + { + filledRegisters[i] = RegisterFill(offset, mRegLens[i]); + offset += mRegLens[i]; + } + } + + uExponents = PolySelection(); + + if (dbMode) + { + //Exponents in use + int counter = 0; + + Console.WriteLine("[exponents]"); + foreach (int[] set in uExponents) + { + Console.WriteLine("set: {0}", counter.ToString()); + + foreach (int exp in set) + Console.Write(exp.ToString() + " "); + + Console.WriteLine(); + counter++; + } + + Console.WriteLine("[/exponents]"); + } + + return filledRegisters; + } + + public int GetOutValue() + { + int[] vToXor = new int[registers.Length]; + int outValue = 0; + + for (int i = 0; i < registers.Length; i++) + vToXor[i] = registers[i][0]; + + outValue = XorRegValues(vToXor); + + return outValue; + } + + public int[] RegistersToShift() + { + int[] indexValues = GetIndexValues(); + int[] tally = FindFrequency(indexValues); + + int highest = 0; + int movVal = 0; + + if (dbMode) + { + Console.WriteLine("[indexValues]:"); + foreach (int v in indexValues) + Console.Write(v.ToString() + " "); + Console.WriteLine("\n[/indexValues]:"); + + Console.WriteLine("[tally]:"); + foreach (int v in tally) + Console.Write(v.ToString() + " "); + Console.WriteLine("\n[/tally]:"); + } + + foreach (int count in tally) + { + if (count > highest) + highest = count; + } + + for (int i = 0; i < tally.Length; i++) + { + if (tally[i] == highest) + movVal = i; + } + + ArrayList regTS = new ArrayList(); + + for (int i = 0; i < indexValues.Length; i++) + { + if (indexValues[i] == movVal) + regTS.Add(i); + } + + return (int[])regTS.ToArray(typeof(int)); + } + + private int[] GetFeedbackValues(int[] regTS) + { + int[] regTSFBV = new int[regTS.Length]; //Reg To Shift Feed Back Values (regTSFBV) + + for (int i = 0; i < regTS.Length; i++) + { + int[] feedbackSet = new int[uExponents[regTS[i]].Length]; + + for (int x = 0; x < uExponents[regTS[i]].Length; x++) + { + feedbackSet[x] = registers[regTS[i]][uExponents[regTS[i]][x]]; + } + + regTSFBV[i] = XorRegValues(feedbackSet); + } + + return regTSFBV; + } + + public void RegisterShift(int[] regTS) + { + int[] shiftedElements = new int[regTS.Length]; + int[] regTSFBV = GetFeedbackValues(regTS); + + if (dbMode) + { + Console.WriteLine("[regTS]:"); + foreach (int v in regTS) + Console.Write(v.ToString() + " "); + Console.WriteLine("\n[/regTS]:"); + + Console.WriteLine("[regTSFBV]:"); + foreach (int v in regTSFBV) + Console.Write(v.ToString() + " "); + Console.WriteLine("\n[/regTSFBV]:"); + } + + for (int i = 0; i < regTS.Length; i++) + { + int[] regShifting = registers[regTS[i]]; //Alias the register to shift + + shiftedElements[i] = registers[regTS[i]][0]; //Copy position zero value in registers to shift + + //Creates new register with appropriate max reg length + int[] nRegister = new int[regShifting.Length]; //Could also use mRegLens[regTS[i]].Length + + //Fill values to length -1 + for (int x = 0; x < (regShifting.Length - 1); x++) + nRegister[x] = regShifting[x + 1]; //+1 Grabbing everything after position zero + + //Now put feedback values on the end (former RegisterPush method) + nRegister[nRegister.Length - 1] = regTSFBV[i]; + + registers[regTS[i]] = nRegister; //assign to register (update) + } + } + } +} \ No newline at end of file -- cgit v1.2.3