source: trunk/CrypPlugins/Trivium/Trivium.cs @ 734

Last change on this file since 734 was 734, checked in by Thomas Schmid, 12 years ago
  • added cube attack to core sln
  • tried to fix Trivium key access (@sören: please check if changes achieve your idea)
File size: 24.7 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5
6using Cryptool.PluginBase;
7using System.IO;
8using System.ComponentModel;
9using Cryptool.PluginBase.Cryptography;
10using Cryptool.PluginBase.IO;
11using System.Windows.Controls;
12using Cryptool.PluginBase.Miscellaneous;
13using System.Security.Cryptography;
14// for IControl
15using Cryptool.PluginBase.Control;
16// reference to the TriviumController interface (own dll)
17using Cryptool.TriviumController;
18
19namespace Cryptool.Trivium
20{
21    [Author("Soeren Rinne, David Oruba & Daehyun Strobel", "soeren.rinne@cryptool.de", "Ruhr-Universitaet Bochum, Chair for Embedded Security (EmSec)", "http://www.trust.ruhr-uni-bochum.de/")]
22    [PluginInfo(false, "Trivium", "Trivium", "Trivium/DetailedDescription/Description.xaml", "Trivium/icon.png", "Trivium/Images/encrypt.png", "Trivium/Images/decrypt.png")]
23    [EncryptionType(EncryptionType.SymmetricBlock)]
24    public class Trivium : IEncryption
25    {
26        #region IPlugin Members
27
28        private TriviumSettings settings;
29        private string inputString = null;
30        private string outputString;
31        private string inputKey;
32        private string inputIV;
33        private bool stop = false;
34        private List<CryptoolStream> listCryptoolStreamsOut = new List<CryptoolStream>();
35
36        #endregion
37
38        #region Public Variables
39        public uint[] a = new uint[93];
40        public uint[] b = new uint[84];
41        public uint[] c = new uint[111];
42        public uint t1, t2, t3;
43        public int masterSlaveRounds = 0;
44        #endregion
45
46        public Trivium()
47        {
48            this.settings = new TriviumSettings();
49            //((TriviumSettings)(this.settings)).LogMessage += Trivium_LogMessage;
50        }
51
52        public ISettings Settings
53        {
54            get { return (ISettings)this.settings; }
55            set { this.settings = (TriviumSettings)value; }
56        }
57
58        [PropertyInfo(Direction.InputData, "Input", "Data to be encrypted or decrypted.", "", true, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, null)]
59        public string InputString
60        {
61            get { return this.inputString; }
62            set
63            {
64                this.inputString = value;
65                OnPropertyChanged("InputString");
66            }
67        }
68
69        [PropertyInfo(Direction.InputData, "Key", "Must be 10 bytes (80 bit) in Hex.", "", true, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, null)]
70        public string InputKey
71        {
72            get { return this.inputKey; }
73            set
74            {
75                this.inputKey = value;
76                OnPropertyChanged("InputKey");
77            }
78        }
79
80        [PropertyInfo(Direction.InputData, "IV", "Must be 10 bytes (80 bit) in Hex.", "", true, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, null)]
81        public string InputIV
82        {
83            get { return this.inputIV; }
84            set
85            {
86                this.inputIV = value;
87                OnPropertyChanged("InputIV");
88            }
89        }
90
91        [PropertyInfo(Direction.OutputData, "Output stream", "Encrypted or decrypted output data", "", true, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, null)]
92        public string OutputString
93        {
94            get { return this.outputString; }
95            set
96            {
97                this.outputString = value;
98                OnPropertyChanged("OutputString");
99            }
100        }
101
102        public void Dispose()
103        {
104            try
105            {
106                stop = false;
107                inputKey = null;
108                outputString = null;
109                inputString = null;
110
111                foreach (CryptoolStream stream in listCryptoolStreamsOut)
112                {
113                    stream.Close();
114                }
115                listCryptoolStreamsOut.Clear();
116            }
117            catch (Exception ex)
118            {
119                GuiLogMessage(ex.Message, NotificationLevel.Error);
120            }
121            this.stop = false;
122        }
123
124        public int[] hextobin(char[] hex)
125        {
126            int i;
127            int[] bin = new int[hex.Length * 4];
128
129            for (i = 0; i < hex.Length; i++)
130            {
131                switch (hex[i])
132                {
133                    case '0':
134                        bin[i * 4] = 0;
135                        bin[i * 4 + 1] = 0;
136                        bin[i * 4 + 2] = 0;
137                        bin[i * 4 + 3] = 0;
138                        break;
139                    case '1':
140                        bin[i * 4] = 0;
141                        bin[i * 4 + 1] = 0;
142                        bin[i * 4 + 2] = 0;
143                        bin[i * 4 + 3] = 1;
144                        break;
145                    case '2':
146                        bin[i * 4] = 0;
147                        bin[i * 4 + 1] = 0;
148                        bin[i * 4 + 2] = 1;
149                        bin[i * 4 + 3] = 0;
150                        break;
151                    case '3':
152                        bin[i * 4] = 0;
153                        bin[i * 4 + 1] = 0;
154                        bin[i * 4 + 2] = 1;
155                        bin[i * 4 + 3] = 1;
156                        break;
157                    case '4':
158                        bin[i * 4] = 0;
159                        bin[i * 4 + 1] = 1;
160                        bin[i * 4 + 2] = 0;
161                        bin[i * 4 + 3] = 0;
162                        break;
163                    case '5':
164                        bin[i * 4] = 0;
165                        bin[i * 4 + 1] = 1;
166                        bin[i * 4 + 2] = 0;
167                        bin[i * 4 + 3] = 1;
168                        break;
169                    case '6':
170                        bin[i * 4] = 0;
171                        bin[i * 4 + 1] = 1;
172                        bin[i * 4 + 2] = 1;
173                        bin[i * 4 + 3] = 0;
174                        break;
175                    case '7':
176                        bin[i * 4] = 0;
177                        bin[i * 4 + 1] = 1;
178                        bin[i * 4 + 2] = 1;
179                        bin[i * 4 + 3] = 1;
180                        break;
181                    case '8':
182                        bin[i * 4] = 1;
183                        bin[i * 4 + 1] = 0;
184                        bin[i * 4 + 2] = 0;
185                        bin[i * 4 + 3] = 0;
186                        break;
187                    case '9':
188                        bin[i * 4] = 1;
189                        bin[i * 4 + 1] = 0;
190                        bin[i * 4 + 2] = 0;
191                        bin[i * 4 + 3] = 1;
192                        break;
193                    case 'a':
194                        bin[i * 4] = 1;
195                        bin[i * 4 + 1] = 0;
196                        bin[i * 4 + 2] = 1;
197                        bin[i * 4 + 3] = 0;
198                        break;
199                    case 'b':
200                        bin[i * 4] = 1;
201                        bin[i * 4 + 1] = 0;
202                        bin[i * 4 + 2] = 1;
203                        bin[i * 4 + 3] = 1;
204                        break;
205                    case 'c':
206                        bin[i * 4] = 1;
207                        bin[i * 4 + 1] = 1;
208                        bin[i * 4 + 2] = 0;
209                        bin[i * 4 + 3] = 0;
210                        break;
211                    case 'd':
212                        bin[i * 4] = 1;
213                        bin[i * 4 + 1] = 1;
214                        bin[i * 4 + 2] = 0;
215                        bin[i * 4 + 3] = 1;
216                        break;
217                    case 'e':
218                        bin[i * 4] = 1;
219                        bin[i * 4 + 1] = 1;
220                        bin[i * 4 + 2] = 1;
221                        bin[i * 4 + 3] = 0;
222                        break;
223                    case 'f':
224                        bin[i * 4] = 1;
225                        bin[i * 4 + 1] = 1;
226                        bin[i * 4 + 2] = 1;
227                        bin[i * 4 + 3] = 1;
228                        break;
229                    case 'A':
230                        bin[i * 4] = 1;
231                        bin[i * 4 + 1] = 0;
232                        bin[i * 4 + 2] = 1;
233                        bin[i * 4 + 3] = 0;
234                        break;
235                    case 'B':
236                        bin[i * 4] = 1;
237                        bin[i * 4 + 1] = 0;
238                        bin[i * 4 + 2] = 1;
239                        bin[i * 4 + 3] = 1;
240                        break;
241                    case 'C':
242                        bin[i * 4] = 1;
243                        bin[i * 4 + 1] = 1;
244                        bin[i * 4 + 2] = 0;
245                        bin[i * 4 + 3] = 0;
246                        break;
247                    case 'D':
248                        bin[i * 4] = 1;
249                        bin[i * 4 + 1] = 1;
250                        bin[i * 4 + 2] = 0;
251                        bin[i * 4 + 3] = 1;
252                        break;
253                    case 'E':
254                        bin[i * 4] = 1;
255                        bin[i * 4 + 1] = 1;
256                        bin[i * 4 + 2] = 1;
257                        bin[i * 4 + 3] = 0;
258                        break;
259                    case 'F':
260                        bin[i * 4] = 1;
261                        bin[i * 4 + 1] = 1;
262                        bin[i * 4 + 2] = 1;
263                        bin[i * 4 + 3] = 1;
264                        break;
265                }
266            }
267
268            return bin;
269        }
270
271        public string bintohex(string bin)
272        {
273            int i;
274            string hex = null;
275            string temp;
276
277            for (i = 0; i < bin.Length / 4; i++)
278            {
279                temp = null;
280                temp += bin[i * 4];
281                temp += bin[i * 4 + 1];
282                temp += bin[i * 4 + 2];
283                temp += bin[i * 4 + 3];
284
285                switch (temp)
286                {
287                    case "0000":
288                        hex += '0';
289                        break;
290                    case "0001":
291                        hex += '1';
292                        break;
293                    case "0010":
294                        hex += '2';
295                        break;
296                    case "0011":
297                        hex += '3';
298                        break;
299                    case "0100":
300                        hex += '4';
301                        break;
302                    case "0101":
303                        hex += '5';
304                        break;
305                    case "0110":
306                        hex += '6';
307                        break;
308                    case "0111":
309                        hex += '7';
310                        break;
311                    case "1000":
312                        hex += '8';
313                        break;
314                    case "1001":
315                        hex += '9';
316                        break;
317                    case "1010":
318                        hex += 'A';
319                        break;
320                    case "1011":
321                        hex += 'B';
322                        break;
323                    case "1100":
324                        hex += 'C';
325                        break;
326                    case "1101":
327                        hex += 'D';
328                        break;
329                    case "1110":
330                        hex += 'E';
331                        break;
332                    case "1111":
333                        hex += 'F';
334                        break;
335                }
336            }
337
338            return hex;
339        }
340
341        // TODO: check if input is boolean or hex
342        // returns -1 if no hex
343        // returns 1 is hex
344        private int checkInput(string input)
345        {
346            int returnValue = 1;
347            return returnValue;
348        }
349
350
351        public void Execute()
352        {
353            process(1);
354        }
355
356        private void process(int padding)
357        {
358            //Encrypt/Decrypt String
359            try
360            {
361                // a test vector; should have the following output:
362                // FC9659CB953A37F...
363                //string IV_string = "288ff65dc42b92f960c7";
364                //string key_string = "0f62b5085bae0154a7fa";
365                string input_string = inputString;
366
367                // check input string
368                if (checkInput(input_string) == -1)
369                    return;
370
371                string IV_string = inputIV;
372                string key_string = inputKey;
373
374                int[] IV = new int[IV_string.Length * 4];
375                int[] key = new int[key_string.Length * 4];
376               
377                IV = hextobin(IV_string.ToCharArray());
378                key = hextobin(key_string.ToCharArray());
379
380                GuiLogMessage("length of IV: " + IV.Length, NotificationLevel.Info);
381                GuiLogMessage("length of key: " + key.Length, NotificationLevel.Info);
382
383                // test if padding to do
384                int bitsToPad = (32 - input_string.Length % 32) % 32;
385                GuiLogMessage("Bits to pad: " + bitsToPad, NotificationLevel.Info);
386                // pad partial block with zeros
387                if (bitsToPad != 0)
388                {
389                    for (int i = 0; i < bitsToPad; i++)
390                    {
391                        input_string += "0";
392                    }
393                }
394
395                string keystream;
396
397                int keyStreamLength = settings.KeystreamLength;
398                if ((keyStreamLength % 32) != 0)
399                {
400                    GuiLogMessage("Keystream length must be a multiple of 32. " + keyStreamLength + " != 32", NotificationLevel.Error);
401                    return;
402                }
403
404                // encryption/decryption
405                DateTime startTime = DateTime.Now;
406
407                GuiLogMessage("Starting encryption [Keysize=80 Bits]", NotificationLevel.Info);
408
409                // init Trivium
410                initTrivium(IV, key);
411
412                // generate keystream with given length (TODO: padding if inputstring % 32 != 0)
413                // ACHTUNG, mag keine grossen zahlen als inputs
414                // EDIT 30.07.09: Jetzt mag er große Zahlen ;)
415                if (settings.KeystreamLength <= 0)
416                {
417                    keystream = keystreamTrivium(input_string.Length);
418                    //GuiLogMessage("DEBUG: inputString.Length + bitsToPad: " + (inputString.Length + bitsToPad), NotificationLevel.Info);
419                }
420                else
421                {
422                    keystream = keystreamTrivium(settings.KeystreamLength);
423                }
424               
425                DateTime stopTime = DateTime.Now;
426                TimeSpan duration = stopTime - startTime;
427
428                if (!settings.HexOutput)
429                {
430                    outputString = keystream;
431                    GuiLogMessage("Keystream hex: " + bintohex(keystream), NotificationLevel.Info);
432                }
433                else
434                {
435                    outputString = bintohex(keystream);
436                    GuiLogMessage("Keystream binary: " + keystream, NotificationLevel.Info);
437                }
438                OnPropertyChanged("OutputString");
439
440                if (!stop)
441                {
442                    GuiLogMessage("Encryption complete in " + duration + "! (input length : " + input_string.Length + ", keystream/output length: " + keystream.Length + " bit)", NotificationLevel.Info);
443                }
444
445                if (stop)
446                {
447                    GuiLogMessage("Aborted!", NotificationLevel.Info);
448                }
449            }
450            catch (Exception exception)
451            {
452                GuiLogMessage(exception.Message, NotificationLevel.Error);
453            }
454            finally
455            {
456                ProgressChanged(1, 1);
457            }
458        }
459
460        public void initTrivium(int[] IV, int[] key)
461        {
462                int i,j;
463
464            int[] buffer = new int[8];
465
466            if (settings.UseByteSwapping)
467            {
468                // Byte-Swapping Key
469                for (int l = 0; l < 10; l++)
470                {
471                    for (int k = 0; k < 8; k++)
472                        buffer[k] = key[((l * 8) + 7) - k];
473                    for (int k = 0; k < 8; k++)
474                        key[(l * 8) + k] = buffer[k];
475                }
476
477                // Byte-Swapping IV
478                for (int l = 0; l < 10; l++)
479                {
480                    for (int k = 0; k < 8; k++)
481                        buffer[k] = IV[((l * 8) + 7) - k];
482                    for (int k = 0; k < 8; k++)
483                        IV[(l * 8) + k] = buffer[k];
484                }
485            }
486
487                for (i = 0; i < 80; i++){
488                        a[i] = (uint)key[i]; // hier key rein als binär
489                        b[i] = (uint)IV[i]; // hier IV rein als binär
490                        c[i] = 0;
491                }
492                while (i < 84){
493                        a[i] = 0;
494                        b[i] = 0;
495                        c[i] = 0;
496                        i++;
497                }
498                while (i < 93){
499                        a[i] = 0;
500                        c[i] = 0;
501                        i++;
502                }
503                while (i < 108){
504                        c[i] = 0;
505                        i++;
506                }
507                while (i < 111){
508                        c[i] = 1;
509                        i++;
510                }
511
512            // belegung fertig, jetzt takten ohne output
513            // anzahl der takte laut settings oder lut master/slave
514            int myRounds;
515
516            if (masterSlaveRounds != 0)
517                myRounds = masterSlaveRounds;
518            else
519                myRounds = settings.InitRounds;
520
521            for (i = 0; i < myRounds; i++) // default 1152 = 4 * 288
522            {
523                t1 = a[65] ^ (a[90] & a[91]) ^ a[92] ^ b[77];
524                t2 = b[68] ^ (b[81] & b[82]) ^ b[83] ^ c[86];
525                t3 = c[65] ^ (c[108] & c[109]) ^ c[110] ^ a[68];
526                for (j = 92; j > 0; j--)
527                    a[j] = a[j - 1];
528                for (j = 83; j > 0; j--)
529                    b[j] = b[j - 1];
530                for (j = 110; j > 0; j--)
531                    c[j] = c[j - 1];
532                a[0] = t3;
533                b[0] = t1;
534                c[0] = t2;
535            }
536        }
537
538        public string keystreamTrivium(int nBits)
539        {
540            int i, j;
541            uint z;
542
543            string keystreamZ = null;
544            List<int> keyOutput = new List<int>();
545
546            for (i = 0; i < nBits; i++)
547            {
548                t1 = a[65] ^ a[92];
549                t2 = b[68] ^ b[83];
550                t3 = c[65] ^ c[110];
551                z = t1 ^ t2 ^ t3;
552
553                if (!settings.UseByteSwapping)
554                    keystreamZ += z;
555                else
556                    keyOutput.Add((int)z);
557
558                t1 = t1 ^ (a[90] & a[91]) ^ b[77];
559                t2 = t2 ^ (b[81] & b[82]) ^ c[86];
560                t3 = t3 ^ (c[108] & c[109]) ^ a[68];
561                for (j = 92; j > 0; j--)
562                    a[j] = a[j - 1];
563                for (j = 83; j > 0; j--)
564                    b[j] = b[j - 1];
565                for (j = 110; j > 0; j--)
566                    c[j] = c[j - 1];
567                a[0] = t3;
568                b[0] = t1;
569                c[0] = t2;
570            }
571
572            if (settings.UseByteSwapping)
573            {
574                int[] temp = new int[nBits];
575
576                // Little-Endian für den Keystream
577                for (int k = 0; k < nBits; k++)
578                    temp[k] = keyOutput[k];
579                for (int l = 0; l < nBits / 32; l++)
580                {
581                    for (int k = 0; k < 8; k++)
582                    {
583                        keyOutput[(l * 32) + k] = (char)temp[(l * 32) + 24 + k];
584                        keyOutput[(l * 32) + 8 + k] = (char)temp[(l * 32) + 16 + k];
585                        keyOutput[(l * 32) + 16 + k] = (char)temp[(l * 32) + 8 + k];
586                        keyOutput[(l * 32) + 24 + k] = (char)temp[(l * 32) + k];
587                    }
588                }
589                GuiLogMessage(keyOutput.Count.ToString(), NotificationLevel.Info);
590                foreach (int k in keyOutput)
591                {
592                    keystreamZ += k.ToString();
593                }
594            }
595
596            return keystreamZ;
597        }
598
599        public void Encrypt()
600        {
601            //Encrypt Stream
602            process(0);
603        }
604
605        public void Decrypt()
606        {
607            //Decrypt Stream
608            process(1);
609        }
610
611        public void Initialize()
612        {
613        }
614
615        public event StatusChangedEventHandler OnPluginStatusChanged;
616
617        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
618        private void GuiLogMessage(string message, NotificationLevel logLevel)
619        {
620            EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(message, this, logLevel));
621        }
622
623        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
624        private void ProgressChanged(double value, double max)
625        {
626            EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(value, max));
627        }
628
629        public void Pause()
630        {
631        }
632
633        public void PostExecution()
634        {
635            Dispose();
636        }
637
638        public void PreExecution()
639        {
640            Dispose();
641        }
642
643        public UserControl Presentation
644        {
645            get { return null; }
646        }
647
648        public UserControl QuickWatchPresentation
649        {
650            get { return null; }
651        }
652
653        public void Stop()
654        {
655            this.stop = true;
656        }
657
658        #region INotifyPropertyChanged Members
659
660        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
661
662        public void OnPropertyChanged(string name)
663        {
664            EventsHelper.PropertyChanged(PropertyChanged, this, new PropertyChangedEventArgs(name));
665            /*if (PropertyChanged != null)
666            {
667              PropertyChanged(this, new PropertyChangedEventArgs(name));
668            }*/
669        }
670
671        private void StatusChanged(int imageIndex)
672        {
673            EventsHelper.StatusChanged(OnPluginStatusChanged, this, new StatusEventArgs(StatusChangedMode.ImageUpdate, imageIndex));
674        }
675
676        #endregion
677
678        #region IControl
679
680        private IControlTrivium triviumSlave;
681        [PropertyInfo(Direction.ControlSlave, "Trivium Slave", "Direct access to Trivium.", "", DisplayLevel.Beginner)]
682        public IControlTrivium TriviumSlave
683        {
684            get
685            {
686                if (triviumSlave == null)
687                    triviumSlave = new TriviumControl(this);
688                return triviumSlave;
689            }
690        }
691
692        #endregion
693    }
694
695    #region TriviumControl : IControlTrivium
696
697    public class TriviumControl : IControlTrivium
698    {
699        public event IControlStatusChangedEventHandler OnStatusChanged;
700        private Trivium plugin;
701        private TriviumSettings pluginSettings;
702
703        public TriviumControl(Trivium Plugin)
704        {
705            this.plugin = Plugin;
706        }
707
708        public TriviumControl(TriviumSettings PluginSettings)
709        {
710            this.pluginSettings = PluginSettings;
711        }
712
713        #region IControlEncryption Members
714
715        // here comes the slave side implementation
716        public int GenerateTriviumKeystream(int[] IV, int[] key, int length, int rounds, bool byteSwapping)
717        {
718            string resultString;
719            int resultInt;
720            //pluginSettings.InitRounds = rounds;
721
722            if (key == null)
723            {
724                key = new int[((TriviumSettings)plugin.Settings).InputKey.Length * 4];
725                key = plugin.hextobin(((TriviumSettings)plugin.Settings).InputKey.ToCharArray());
726                // key = new int[] { 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1 };
727            }
728           
729            plugin.masterSlaveRounds = rounds;
730            plugin.initTrivium(IV, key);
731
732            resultString = plugin.keystreamTrivium(length);
733
734            return resultInt = Int32.Parse(resultString.Substring(resultString.Length - 1, 1));
735        }
736
737        #endregion
738    }
739
740    #endregion
741
742    enum TriviumImage
743    {
744        Default,
745        Encode,
746        Decode
747    }
748}
Note: See TracBrowser for help on using the repository browser.