Ignore:
Timestamp:
Jul 28, 2009, 12:23:14 PM (12 years ago)
Author:
Matthäus Wander
Message:

CrypPluginBase:

  • added string tokenizer as misc utility

FrequencyTest: update 2 of 3

  • added additional output property with letter/n-gram statistics
  • added algorithm settings
  • the format of the existing output properties has not been changed
  • implementation relies on string tokenizer

Enigma:

  • added optional input property to use the new n-gram FrequencyTest output
  • implemented log2 trigram calculation as another valuation method for plug search (only being used when corresponding input is connected)
  • Note: requires ticket #64
  • Note: an exception occurs, if you stop and start the analysis before the pending plugin search has finished. This will be fixed in future
  • Note: the project samples have not been changed yet
Location:
trunk/CrypPlugins/Enigma
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/CrypPlugins/Enigma/Enigma.cs

    r367 r404  
    225225namespace Cryptool.Enigma
    226226{
    227     [Author("Dr. Arno Wacker", "arno.wacker@cryptool.org", "Uni Duisburg-Essen", "http://www.uni-duisburg-essen.de")]
     227    [Author("Dr. Arno Wacker, Matthäus Wander", "arno.wacker@cryptool.org", "Uni Duisburg-Essen", "http://www.uni-duisburg-essen.de")]
    228228    [PluginInfo(false, "Enigma", "Polyalphabetic rotor-cipher machine", null,
    229229      "Enigma/Images/Enigma.png", "Enigma/Images/encrypt.png", "Enigma/Images/decrypt.png")]
     
    237237        private EnigmaAnalyzer analyzer;
    238238        private string inputString;
     239        private IDictionary<string, double[]> inputGrams;
    239240        private string outputString;
    240241        private string savedKey;
     
    392393        }
    393394
     395        [PropertyInfo(Direction.Input, "n-gram dictionary", "Dictionary with gram counts", "", false, false, DisplayLevel.Experienced, QuickWatchFormat.Text, "FrequencyTest.QuickWatchDictionary")]
     396        public IDictionary<string, double[]> InputGrams
     397        {
     398            get { return this.inputGrams; }
     399            set
     400            {
     401                if (value != inputGrams)
     402                {
     403                    this.inputGrams = value;
     404                    OnPropertyChanged("InputGrams");
     405                }
     406            }
     407        }
     408
    394409        [PropertyInfo(Direction.Output, "Text output", "The string after processing with the Enigma machine", "", false, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
    395410        public string OutputString
     
    468483
    469484                    // perform the analysis
    470                     outputString = postFormatOutput(analyzer.Analyze(preformatedText));
     485                    outputString = postFormatOutput(analyzer.Analyze(preformatedText, inputGrams));
    471486                    OnPropertyChanged("OutputString");
    472487
  • trunk/CrypPlugins/Enigma/EnigmaAnalyzer.cs

    r402 r404  
    99//Cryptool 2.0 specific includes
    1010using Cryptool.PluginBase;
    11 
     11using Cryptool.PluginBase.Miscellaneous;
    1212
    1313namespace Cryptool.Enigma
     
    3434            public string Key;
    3535            public string PlugBoard = "-- no plugs --";
    36             public double IC;
     36            public double Score;
    3737
    3838            #region IComparable<analysisConfigSettings> Member
     
    4040            public int CompareTo(analysisConfigSettings other)
    4141            {
    42                 return this.IC.CompareTo(other.IC);
     42                return this.Score.CompareTo(other.Score);
    4343            }
    4444
     
    4848        #endregion
    4949
    50         #region Private member variables
     50        #region Private member variables and constants
     51
     52        private const int ABSOLUTE = 0;
     53        private const int PERCENTAGED = 1;
     54        private const int LOG2 = 2;
    5155
    5256        Enigma pluginFacade;
     
    5862        private List<analysisConfigSettings> analysisCandidates = new List<analysisConfigSettings>();
    5963        private const int maxAnalysisEntries = 10; // should go in settings under "Analysis Options"
     64
     65        private IDictionary<string, double[]> grams;
    6066
    6167        #endregion
     
    174180            {
    175181                // List is full, check if we need to remove one
    176                 if (newIC > analysisCandidates[0].IC)
    177                 {
    178                     double currentMax = analysisCandidates[analysisCandidates.Count - 1].IC;
     182                if (newIC > analysisCandidates[0].Score)
     183                {
     184                    double currentMax = analysisCandidates[analysisCandidates.Count - 1].Score;
    179185
    180186                    analysisConfigSettings csetting = new analysisConfigSettings();
    181                     csetting.IC = newIC;
     187                    csetting.Score = newIC;
    182188                    csetting.Rotor1 = core.Rotor1;
    183189                    csetting.Rotor2 = core.Rotor2;
     
    222228
    223229                analysisConfigSettings csetting = new analysisConfigSettings();
    224                 csetting.IC = newIC;
     230                csetting.Score = newIC;
    225231                csetting.Rotor1 = core.Rotor1;
    226232                csetting.Rotor2 = core.Rotor2;
     
    243249
    244250                    string status = String.Format("ANALYSIS: Best candidates is filled. Best option so far: {0},{1},{2}; Key: {3}; I.C.={4}",
    245                     (rotorEnum)bestOption.Rotor3, (rotorEnum)bestOption.Rotor2, (rotorEnum)bestOption.Rotor1, bestOption.Key, bestOption.IC.ToString());
     251                    (rotorEnum)bestOption.Rotor3, (rotorEnum)bestOption.Rotor2, (rotorEnum)bestOption.Rotor1, bestOption.Key, bestOption.Score.ToString());
    246252                    pluginFacade.LogMessage(status, NotificationLevel.Debug);
    247253
     
    291297                    double newIC = calculateIC(result);
    292298
    293                     if (newIC > enigmaConfig.IC)
     299                    if (newIC > enigmaConfig.Score)
    294300                    {
    295301                        //better value, hence update the data
    296                         enigmaConfig.IC = newIC;
     302                        enigmaConfig.Score = newIC;
    297303                        enigmaConfig.Ring1 = i;
    298304                        enigmaConfig.Key = settings.Alphabet[r3pos].ToString() + settings.Alphabet[r2pos].ToString() + settings.Alphabet[rotatedR1Pos].ToString();
     
    320326                    double newIC = calculateIC(result);
    321327
    322                     if (newIC > enigmaConfig.IC)
     328                    if (newIC > enigmaConfig.Score)
    323329                    {
    324330                        //better value, hence update the data
    325                         enigmaConfig.IC = newIC;
     331                        enigmaConfig.Score = newIC;
    326332                        enigmaConfig.Ring2 = i;
    327333                        enigmaConfig.Key = settings.Alphabet[r3pos].ToString() + settings.Alphabet[rotatedR2Pos].ToString() + settings.Alphabet[r1pos].ToString();
     
    342348                            double newIC = calculateIC(result);
    343349
    344                             if (newIC > enigmaConfig.IC)
     350                            if (newIC > enigmaConfig.Score)
    345351                            {
    346352                                //better value, hence update the data
    347                                 enigmaConfig.IC = newIC;
     353                                enigmaConfig.Score = newIC;
    348354                                enigmaConfig.Ring1 = k;
    349355                                enigmaConfig.Ring2 = j;
     
    358364            // print best option
    359365            string msg = String.Format("ANALYSIS: Best ring setting: {0} | {1},{2},{3} | {4},{5},{6} | {7} | {8}",
    360                 enigmaConfig.IC.ToString(),
     366                enigmaConfig.Score.ToString(),
    361367                (rotorEnum)enigmaConfig.Rotor3, (rotorEnum)enigmaConfig.Rotor2, (rotorEnum)enigmaConfig.Rotor1,
    362368                enigmaConfig.Ring3.ToString("00"), enigmaConfig.Ring2.ToString("00"), enigmaConfig.Ring1.ToString("00"),
     
    377383            bool plugFound = false;
    378384            int trials = 0;
     385            enigmaConfig.Score = calculatePlugScore(encrypt(enigmaConfig, text, enigmaConfig.PlugBoard));
     386
     387            if (grams == null)
     388                pluginFacade.LogMessage("Using legacy IC method to analyze plugs", NotificationLevel.Debug);
     389            else
     390                pluginFacade.LogMessage("Using new trigram method to analyze plugs", NotificationLevel.Debug);
    379391
    380392            for (int n = 0; n < maxPlugs; n++)
     
    416428                        plugboard[j] = settings.Alphabet[i];
    417429
    418                         core.setInternalConfig(enigmaConfig.Rotor1, enigmaConfig.Rotor2, enigmaConfig.Rotor3, 0, settings.Reflector, enigmaConfig.Ring1, enigmaConfig.Ring2, enigmaConfig.Ring3, 1, plugboard.ToString());
    419 
    420 
    421                         int r1pos = settings.Alphabet.IndexOf(enigmaConfig.Key[2]);
    422                         int r2pos = settings.Alphabet.IndexOf(enigmaConfig.Key[1]);
    423                         int r3pos = settings.Alphabet.IndexOf(enigmaConfig.Key[0]);
    424                         string result = core.Encrypt(r1pos, r2pos, r3pos, 0, text);
    425 
    426                         double newIC = calculateIC(result);
     430                        double newScore = calculatePlugScore(encrypt(enigmaConfig, text, plugboard.ToString()));
    427431                        trials++;
    428432
    429                         if (newIC > enigmaConfig.IC)
     433                        if (newScore > enigmaConfig.Score)
    430434                        {
    431                             enigmaConfig.IC = newIC;
     435                            enigmaConfig.Score = newScore;
    432436                            enigmaConfig.PlugBoard = plugboard.ToString();
    433437                            plugFound = true;
     
    438442
    439443                string msg = String.Format("ANALYSIS: Plugs setting in round {0} after {1} trials: {2} | {3},{4},{5} | {6},{7},{8} | {9} | {10}",
    440                     (n + 1), trials, enigmaConfig.IC.ToString(),
     444                    (n + 1), trials, enigmaConfig.Score.ToString(),
    441445                    (rotorEnum)enigmaConfig.Rotor3, (rotorEnum)enigmaConfig.Rotor2, (rotorEnum)enigmaConfig.Rotor1,
    442446                    enigmaConfig.Ring3, enigmaConfig.Ring2, enigmaConfig.Ring1,
     
    448452                    break;
    449453            }
     454        }
     455
     456        private string encrypt(analysisConfigSettings enigmaConfig, string text, string plugboard)
     457        {
     458            core.setInternalConfig(enigmaConfig.Rotor1, enigmaConfig.Rotor2, enigmaConfig.Rotor3, 0, settings.Reflector, enigmaConfig.Ring1, enigmaConfig.Ring2, enigmaConfig.Ring3, 1, plugboard);
     459
     460            int r1pos = settings.Alphabet.IndexOf(enigmaConfig.Key[2]);
     461            int r2pos = settings.Alphabet.IndexOf(enigmaConfig.Key[1]);
     462            int r3pos = settings.Alphabet.IndexOf(enigmaConfig.Key[0]);
     463            return core.Encrypt(r1pos, r2pos, r3pos, 0, text);
    450464        }
    451465
     
    492506            // start with the unmodified
    493507            core.setInternalConfig(enigmaConfig.Rotor1, enigmaConfig.Rotor2, enigmaConfig.Rotor3, 0, settings.Reflector, enigmaConfig.Ring1, enigmaConfig.Ring2, enigmaConfig.Ring3, 1, unmodifiedPlugboard);
    494             double unmodifiedIC = calculateIC(core.Encrypt(r1pos, r2pos, r3pos, 0, text));
     508            double unmodifiedScore = calculatePlugScore(core.Encrypt(r1pos, r2pos, r3pos, 0, text));
    495509
    496510            // now o2p
    497511            core.setInternalConfig(enigmaConfig.Rotor1, enigmaConfig.Rotor2, enigmaConfig.Rotor3, 0, settings.Reflector, enigmaConfig.Ring1, enigmaConfig.Ring2, enigmaConfig.Ring3, 1, o2pPlugPlugboard.ToString());
    498             double o2pIC = calculateIC(core.Encrypt(r1pos, r2pos, r3pos, 0, text));
     512            double o2pScore = calculatePlugScore(core.Encrypt(r1pos, r2pos, r3pos, 0, text));
    499513
    500514            // now c2o
    501515            core.setInternalConfig(enigmaConfig.Rotor1, enigmaConfig.Rotor2, enigmaConfig.Rotor3, 0, settings.Reflector, enigmaConfig.Ring1, enigmaConfig.Ring2, enigmaConfig.Ring3, 1, c2oPlugboard.ToString());
    502             double c2oIC = calculateIC(core.Encrypt(r1pos, r2pos, r3pos, 0, text));
     516            double c2oScore = calculatePlugScore(core.Encrypt(r1pos, r2pos, r3pos, 0, text));
    503517
    504518            string bestPlugBoard = enigmaConfig.PlugBoard;
    505             double newIC;
    506 
    507             if (c2oIC > unmodifiedIC)
    508             {
    509                 if (c2oIC > o2pIC)
     519            double newScore;
     520
     521            if (c2oScore > unmodifiedScore)
     522            {
     523                if (c2oScore > o2pScore)
    510524                {
    511525                    bestPlugBoard = c2oPlugboard.ToString();
    512                     newIC = c2oIC;
     526                    newScore = c2oScore;
    513527                }
    514528                else
    515529                {
    516530                    bestPlugBoard = o2pPlugPlugboard.ToString();
    517                     newIC = o2pIC;
     531                    newScore = o2pScore;
    518532                }
    519533            }
    520534            else
    521535            {
    522                 if (unmodifiedIC > o2pIC)
     536                if (unmodifiedScore > o2pScore)
    523537                {
    524538                    bestPlugBoard = unmodifiedPlugboard;
    525                     newIC = unmodifiedIC;
     539                    newScore = unmodifiedScore;
    526540                }
    527541                else
    528542                {
    529543                    bestPlugBoard = o2pPlugPlugboard.ToString();
    530                     newIC = o2pIC;
    531                 }
    532             }
    533 
    534 
    535             if (newIC > enigmaConfig.IC)
    536             {
    537                 enigmaConfig.IC = newIC;
     544                    newScore = o2pScore;
     545                }
     546            }
     547
     548
     549            if (newScore > enigmaConfig.Score)
     550            {
     551                enigmaConfig.Score = newScore;
    538552                enigmaConfig.PlugBoard = bestPlugBoard;
    539553                found = true;
    540554            }
    541555
    542             //string msg = String.Format("ANALYSIS PlUG CONFLICT: Unmodified [{0}] => {1}; Variant A [{2}] => {3}; Variant B[{4}] => {5} || Selected [{6}]",
    543             //    pB2String(unmodifiedPlugboard), unmodifiedIC,
    544             //    pB2String(c2oPlugboard.ToString()), c2oIC,
    545             //    pB2String(o2pPlugPlugboard.ToString()), o2pIC,
    546             //    pB2String(bestPlugBoard));
    547 
    548             //LogMessage(msg, NotificationLevel.Info);
     556            //string msg = String.Format("ANALYSIS PLUG CONFLICT: Unmodified [{0}] => {1}; Variant A [{2}] => {3}; Variant B[{4}] => {5} || Selected [{6}]",
     557            //    pluginFacade.pB2String(unmodifiedPlugboard), unmodifiedScore,
     558            //    pluginFacade.pB2String(c2oPlugboard.ToString()), c2oScore,
     559            //    pluginFacade.pB2String(o2pPlugPlugboard.ToString()), o2pScore,
     560            //    pluginFacade.pB2String(bestPlugBoard));
     561
     562            //pluginFacade.LogMessage(msg, NotificationLevel.Info);
    549563
    550564            return found;
     
    552566
    553567        #region Helper methods
     568
     569        private double calculatePlugScore(string input)
     570        {
     571            return grams == null ? calculateIC(input) : calculateTrigrams(input);
     572        }
    554573
    555574        /// <summary>
     
    580599
    581600            return ((double)countDoubleCharacters / (double)(cipherTextLength * (cipherTextLength - 1)));
     601        }
     602
     603        /// <summary>
     604        /// This method calculates a trigram log2 score of a given text on the basis of a given grams dictionary.
     605        /// Case is insensitive.
     606        /// </summary>
     607        /// <param name="input">The text to be scored</param>
     608        /// <param name="grams">The scoring values to be used</param>
     609        /// <returns>The trigram score result</returns>
     610        private double calculateTrigrams(string input)
     611        {
     612            double score = 0;
     613            string workstring = StringUtil.StripUnknownSymbols(settings.Alphabet, input);
     614
     615            // FIXME: this causes an exception when analysis is started before pending plugin search has finished
     616            foreach (KeyValuePair<string, double[]> item in grams)
     617            {
     618                if (workstring.Contains(settings.CaseHandling == 0 ? item.Key : item.Key.ToUpper()))
     619                {
     620                    score += item.Value[LOG2];
     621                }
     622            }
     623
     624            return score;
    582625        }
    583626
     
    617660            {
    618661                message.AppendFormat("{0} | {1},{2},{3} | {4},{5},{6} | {7} | {8}" + Environment.NewLine,
    619                     cfg.IC.ToString(),
     662                    cfg.Score.ToString(),
    620663                    (rotorEnum)cfg.Rotor3, (rotorEnum)cfg.Rotor2, (rotorEnum)cfg.Rotor1,
    621664                    cfg.Ring3.ToString("00"), cfg.Ring2.ToString("00"), cfg.Ring1.ToString("00"),
     
    663706        /// <param name="preformatedText">The preformated text for analysis</param>
    664707        /// <returns>The cleartext as decoded with the analyzed key</returns>
    665         public string Analyze(string preformatedText)
     708        public string Analyze(string preformatedText, IDictionary<string, double[]> grams)
    666709        {
    667710            pluginFacade.LogMessage("=========> ANALYSIS OF ENIGMA MESSAGE STARTED <=========", NotificationLevel.Info);
    668711
    669 
    670712            // some initialisation
     713            this.grams = grams;
    671714            analysisCandidates.Clear();
    672715            stop = false;
Note: See TracChangeset for help on using the changeset viewer.