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

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