summaryrefslogtreecommitdiff
path: root/A5.1/C#/A5/A5Engine.cs
diff options
context:
space:
mode:
Diffstat (limited to 'A5.1/C#/A5/A5Engine.cs')
-rw-r--r--A5.1/C#/A5/A5Engine.cs443
1 files changed, 443 insertions, 0 deletions
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
personal git repositories of Harald Welte. Your mileage may vary