Changeset 3061


Ignore:
Timestamp:
Mar 29, 2011, 10:49:31 PM (11 years ago)
Author:
Matthäus Wander
Message:

Twofish:

  • fixed input padding (closes #231)
File:
1 edited

Legend:

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

    r3052 r3061  
    2525namespace Twofish
    2626{
    27   [Author("Gerhard Junker", null, "private project member", null)]
    28   [PluginInfo("Twofish.Properties.Resources", false, "TwofishCaption", "TwofishTooltip", "TwofishDescriptionUrl",
    29       "Twofish/Images/Twofish.png", "Twofish/Images/encrypt.png", "Twofish/Images/decrypt.png")]
    30   [EncryptionType(EncryptionType.SymmetricBlock)]
    31   public class Twofish : IEncryption
    32   {
    33       private byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    34 
    35 
    36     /// <summary>
    37     /// Initializes a new instance of the <see cref="Twofish"/> class.
    38     /// </summary>
    39     public Twofish()
     27    [Author("Gerhard Junker", null, "private project member", null)]
     28    [PluginInfo("Twofish.Properties.Resources", false, "TwofishCaption", "TwofishTooltip", "TwofishDescriptionUrl",
     29        "Twofish/Images/Twofish.png", "Twofish/Images/encrypt.png", "Twofish/Images/decrypt.png")]
     30    [EncryptionType(EncryptionType.SymmetricBlock)]
     31    public class Twofish : IEncryption
    4032    {
    41       settings = new TwofishSettings();
    42     }
    43 
    44     #region IPlugin Member
     33        private byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
     34
     35
     36        /// <summary>
     37        /// Initializes a new instance of the <see cref="Twofish"/> class.
     38        /// </summary>
     39        public Twofish()
     40        {
     41            settings = new TwofishSettings();
     42        }
     43
     44        #region IPlugin Member
    4545
    4646
    4747#pragma warning disable 67
    48     public event StatusChangedEventHandler OnPluginStatusChanged;
    49     public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
    50     public event PluginProgressChangedEventHandler OnPluginProgressChanged;
     48        public event StatusChangedEventHandler OnPluginStatusChanged;
     49        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
     50        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
    5151#pragma warning restore
    5252
    5353
    54     TwofishSettings settings;
    55     /// <summary>
    56     /// Gets or sets the settings.
    57     /// </summary>
    58     /// <value>The settings.</value>
    59     public ISettings Settings
    60     {
    61       get
    62       {
    63         return settings;
    64       }
    65       set
    66       {
    67         settings = (TwofishSettings)value;
    68         OnPropertyChanged("Settings");
    69       }
    70     }
    71 
    72     /// <summary>
    73     /// Provide all presentation stuff in this user control, it will be opened in an tab.
    74     /// Return null if your plugin has no presentation.
    75     /// </summary>
    76     /// <value>The presentation.</value>
    77     public System.Windows.Controls.UserControl Presentation
    78     {
    79       get
    80       {
    81         return null;
    82       }
    83     }
    84 
    85     public System.Windows.Controls.UserControl QuickWatchPresentation
    86     {
    87       get
    88       {
    89         return null;
    90       }
    91     }
    92 
    93     public void PreExecution()
    94     {
    95     }
    96 
    97     public void Execute()
    98     {
    99       Crypt();
    100     }
    101 
    102     public void PostExecution()
    103     {
    104     }
    105 
    106     public void Pause()
    107     {
    108     }
    109 
    110     public void Stop()
    111     {
    112     }
    113 
    114     public void Initialize()
    115     {
    116     }
    117 
    118     /// <summary>
    119     /// Will be called from editor when element is deleted from worksapce.
    120     /// Releases unmanaged and - optionally - managed resources
    121     /// </summary>
    122     public void Dispose()
    123     {
    124       }
    125 
    126     #endregion
    127 
    128 
    129     #region Input inputdata
    130 
    131     // Input inputdata
    132                 private byte[] inputdata = { };
    133 
    134                 /// <summary>
    135                 /// Notifies the update input.
    136                 /// </summary>
    137                 private void NotifyUpdateInput()
    138                 {
    139                         OnPropertyChanged("InputStream");
    140                         OnPropertyChanged("InputData");
    141                 }
    142 
    143                 /// <summary>
    144                 /// Gets or sets the input inputdata.
    145                 /// </summary>
    146                 /// <value>The input inputdata.</value>
    147         [PropertyInfo(Direction.InputData, "InputStreamCaption", "InputStreamTooltip", null, 
     54        TwofishSettings settings;
     55        /// <summary>
     56        /// Gets or sets the settings.
     57        /// </summary>
     58        /// <value>The settings.</value>
     59        public ISettings Settings
     60        {
     61            get
     62            {
     63                return settings;
     64            }
     65            set
     66            {
     67                settings = (TwofishSettings)value;
     68                OnPropertyChanged("Settings");
     69            }
     70        }
     71
     72        /// <summary>
     73        /// Provide all presentation stuff in this user control, it will be opened in an tab.
     74        /// Return null if your plugin has no presentation.
     75        /// </summary>
     76        /// <value>The presentation.</value>
     77        public System.Windows.Controls.UserControl Presentation
     78        {
     79            get
     80            {
     81                return null;
     82            }
     83        }
     84
     85        public System.Windows.Controls.UserControl QuickWatchPresentation
     86        {
     87            get
     88            {
     89                return null;
     90            }
     91        }
     92
     93        public void PreExecution()
     94        {
     95        }
     96
     97        public void Execute()
     98        {
     99            Crypt();
     100        }
     101
     102        public void PostExecution()
     103        {
     104        }
     105
     106        public void Pause()
     107        {
     108        }
     109
     110        public void Stop()
     111        {
     112        }
     113
     114        public void Initialize()
     115        {
     116        }
     117
     118        /// <summary>
     119        /// Will be called from editor when element is deleted from worksapce.
     120        /// Releases unmanaged and - optionally - managed resources
     121        /// </summary>
     122        public void Dispose()
     123        {
     124        }
     125
     126        #endregion
     127
     128
     129        #region Input inputdata
     130
     131        // Input inputdata
     132        private byte[] inputdata = { };
     133
     134        /// <summary>
     135        /// Notifies the update input.
     136        /// </summary>
     137        private void NotifyUpdateInput()
     138        {
     139            OnPropertyChanged("InputStream");
     140            OnPropertyChanged("InputData");
     141        }
     142
     143        /// <summary>
     144        /// Gets or sets the input inputdata.
     145        /// </summary>
     146        /// <value>The input inputdata.</value>
     147        [PropertyInfo(Direction.InputData, "InputStreamCaption", "InputStreamTooltip", null,
    148148            false, false, QuickWatchFormat.Hex, null)]
    149                 public ICryptoolStream InputStream
    150                 {
    151                         get
    152                         {
     149        public ICryptoolStream InputStream
     150        {
     151            get
     152            {
    153153                if (inputdata == null)
    154154                {
    155155                    return null;
    156                             }
     156                }
    157157                else
    158158                {
    159159                    return new CStreamWriter(inputdata);
    160160                }
    161                         }
    162                         set
    163                         {
     161            }
     162            set
     163            {
    164164                if (value != null)
    165165                {
     
    169169                    }
    170170
    171                                     NotifyUpdateInput();
    172                             }
    173                     }
    174                 }
    175 
    176                 /// <summary>
    177                 /// Gets the input data.
    178                 /// </summary>
    179                 /// <value>The input data.</value>
    180         [PropertyInfo(Direction.InputData, "InputDataCaption", "InputDataTooltip", null, 
     171                    NotifyUpdateInput();
     172                }
     173            }
     174        }
     175
     176        /// <summary>
     177        /// Gets the input data.
     178        /// </summary>
     179        /// <value>The input data.</value>
     180        [PropertyInfo(Direction.InputData, "InputDataCaption", "InputDataTooltip", null,
    181181            false, false, QuickWatchFormat.Hex, null)]
    182                 public byte[] InputData
    183                 {
    184                         get
    185                         {
    186                                 return inputdata;
    187                         }
    188                         set
    189                         {
     182        public byte[] InputData
     183        {
     184            get
     185            {
     186                return inputdata;
     187            }
     188            set
     189            {
    190190                if (null == value)
    191191                {
     
    193193                    return;
    194194                }
    195                                 long len = value.Length;
    196                                 inputdata = new byte[len];
    197 
    198                                 for (long i = 0; i < len; i++)
    199                                         inputdata[i] = value[i];
    200 
    201                                 NotifyUpdateInput();
    202                         }
    203                 }
    204                 #endregion
    205 
    206     #region Key data
    207 
    208     // Salt Data
    209     private byte[] key = { };
    210 
    211     /// <summary>
    212     /// Notifies the update key.
    213     /// </summary>
    214     private void NotifyUpdateKey()
    215     {
    216       OnPropertyChanged("KeyStream");
    217       OnPropertyChanged("KeyData");
     195                long len = value.Length;
     196                inputdata = new byte[len];
     197
     198                for (long i = 0; i < len; i++)
     199                    inputdata[i] = value[i];
     200
     201                NotifyUpdateInput();
     202            }
     203        }
     204        #endregion
     205
     206        #region Key data
     207
     208        // Salt Data
     209        private byte[] key = { };
     210
     211        /// <summary>
     212        /// Notifies the update key.
     213        /// </summary>
     214        private void NotifyUpdateKey()
     215        {
     216            OnPropertyChanged("KeyStream");
     217            OnPropertyChanged("KeyData");
     218        }
     219
     220        /// <summary>
     221        /// Gets or sets the key data.
     222        /// </summary>
     223        /// <value>The key data.</value>
     224        [PropertyInfo(Direction.InputData, "KeyStreamCaption", "KeyStreamTooltip", null,
     225            false, false, QuickWatchFormat.Hex, null)]
     226        public ICryptoolStream KeyStream
     227        {
     228            get
     229            {
     230                if (key == null)
     231                {
     232                    return null;
     233                }
     234                else
     235                {
     236                    return new CStreamWriter(key);
     237                }
     238            }
     239            set
     240            {
     241                if (value != null)
     242                {
     243                    using (CStreamReader reader = value.CreateReader())
     244                    {
     245                        GuiLogMessage("KeyStream changed.", NotificationLevel.Debug);
     246                        key = reader.ReadFully();
     247                    }
     248
     249                    NotifyUpdateKey();
     250                }
     251            }
     252        }
     253
     254        /// <summary>
     255        /// Gets or sets the key data.
     256        /// </summary>
     257        /// <value>The key data.</value>
     258        [PropertyInfo(Direction.InputData, "KeyDataCaption", "KeyDataTooltip", null,
     259            false, false, QuickWatchFormat.Hex, null)]
     260        public byte[] KeyData
     261        {
     262            get
     263            {
     264                return key;
     265            }
     266
     267            set
     268            {
     269                long len = value.Length;
     270                key = new byte[len];
     271
     272                for (long i = 0; i < len; i++)
     273                    key[i] = value[i];
     274
     275                NotifyUpdateKey();
     276                GuiLogMessage("KeyData changed.", NotificationLevel.Debug);
     277            }
     278        }
     279
     280        #endregion
     281
     282        [PropertyInfo(Direction.InputData, "IVCaption", "IVTooltip", null,
     283            false, false, QuickWatchFormat.Hex, null)]
     284        public byte[] IV
     285        {
     286            get
     287            {
     288                return iv;
     289            }
     290            set
     291            {
     292                Array.Clear(iv, 0, iv.Length);
     293
     294                if (null == value)
     295                    return;
     296
     297                for (int i = 0; i < value.Length && i < iv.Length; i++)
     298                    iv[i] = value[i];
     299
     300                NotifyUpdateInput();
     301                GuiLogMessage("InputData changed.", NotificationLevel.Debug);
     302            }
     303        }
     304
     305
     306
     307        #region Output
     308
     309        // Output
     310        private byte[] outputData = { };
     311
     312        /// <summary>
     313        /// Notifies the update output.
     314        /// </summary>
     315        private void NotifyUpdateOutput()
     316        {
     317            OnPropertyChanged("OutputStream");
     318            OnPropertyChanged("OutputData");
     319        }
     320
     321
     322        /// <summary>
     323        /// Gets or sets the output inputdata stream.
     324        /// </summary>
     325        /// <value>The output inputdata stream.</value>
     326        [PropertyInfo(Direction.OutputData, "OutputStreamCaption", "OutputStreamTooltip", null,
     327            true, false, QuickWatchFormat.Hex, null)]
     328        public ICryptoolStream OutputStream
     329        {
     330            get
     331            {
     332                if (outputData == null)
     333                {
     334                    return null;
     335                }
     336                else
     337                {
     338                    return new CStreamWriter(outputData);
     339                }
     340            }
     341        }
     342
     343        /// <summary>
     344        /// Gets the output inputdata.
     345        /// </summary>
     346        /// <value>The output inputdata.</value>
     347        [PropertyInfo(Direction.OutputData, "OutputDataCaption", "OutputDataTooltip", null,
     348            true, false, QuickWatchFormat.Hex, null)]
     349        public byte[] OutputData
     350        {
     351            get
     352            {
     353                return this.outputData;
     354            }
     355        }
     356
     357        #endregion
     358
     359
     360
     361        #region INotifyPropertyChanged Member
     362
     363        public event PropertyChangedEventHandler PropertyChanged;
     364        /// <summary>
     365        /// Called when [property changed].
     366        /// </summary>
     367        /// <param name="name">The name.</param>
     368        protected void OnPropertyChanged(string name)
     369        {
     370            if (PropertyChanged != null)
     371            {
     372                if (name == "Settings")
     373                {
     374                    Crypt();
     375                }
     376                else
     377                    PropertyChanged(this, new PropertyChangedEventArgs(name));
     378            }
     379        }
     380
     381
     382        /// <summary>
     383        /// GUIs the log message.
     384        /// </summary>
     385        /// <param name="message">The message.</param>
     386        /// <param name="logLevel">The log level.</param>
     387        private void GuiLogMessage(string message, NotificationLevel logLevel)
     388        {
     389            EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this,
     390              new GuiLogEventArgs(message, this, logLevel));
     391        }
     392
     393        #endregion
     394
     395
     396        private void Crypt()
     397        {
     398            // fit key to correct length
     399            byte[] k2 = new byte[settings.KeyLength / 8];
     400            for (int i = 0; i < settings.KeyLength / 8; i++)
     401                if (i < key.Length)
     402                    k2[i] = key[i];
     403                else
     404                    k2[i] = 0;
     405
     406
     407            TwofishManaged tf = TwofishManaged.Create();
     408
     409            tf.Mode = (settings.Mode == 0) ? CipherMode.CBC : CipherMode.ECB;
     410
     411            int pos = 0;
     412
     413            byte[] tmpInput = inputdata;
     414            if (tmpInput.Length % 16 != 0) // weird block length
     415            {
     416                if (settings.Action == 0) // encrypt?
     417                {
     418                    tmpInput = PadData(inputdata); // add zero pad
     419                }
     420                else // decrypt?
     421                {
     422                    GuiLogMessage("Input data must be a multiple of 16", NotificationLevel.Error);
     423                    return;
     424                }               
     425            }
     426
     427            if (outputData.Length != tmpInput.Length)
     428                outputData = new byte[tmpInput.Length];
     429
     430            switch (settings.Action)
     431            {
     432                case 0: // encrypt
     433                    {
     434                        ICryptoTransform encrypt = tf.CreateEncryptor(k2, iv);
     435
     436                        while (tmpInput.Length - pos > encrypt.InputBlockSize)
     437                        {
     438                            pos += encrypt.TransformBlock(tmpInput, pos, encrypt.InputBlockSize, outputData, pos);
     439                        }
     440                        byte[] final = encrypt.TransformFinalBlock(tmpInput, pos, tmpInput.Length - pos);
     441                        Array.Copy(final, 0, outputData, pos, 16);
     442                        encrypt.Dispose();
     443                        break;
     444                    }
     445                case 1: // decrypt
     446                    {
     447                        ICryptoTransform decrypt = tf.CreateDecryptor(k2, iv);
     448
     449                        while (tmpInput.Length - pos > decrypt.InputBlockSize)
     450                        {
     451                            pos += decrypt.TransformBlock(tmpInput, pos, decrypt.InputBlockSize, outputData, pos);
     452                        }
     453                        if (tmpInput.Length - pos > 0)
     454                        {
     455                            byte[] final = decrypt.TransformFinalBlock(tmpInput, pos, tmpInput.Length - pos);
     456
     457                            for (int i = pos; i < outputData.Length; i++)
     458                                outputData[i] = final[i - pos];
     459                        }
     460
     461                        decrypt.Dispose();
     462                        break;
     463                    }
     464            }
     465
     466            NotifyUpdateOutput();
     467        }
     468
     469        private byte[] PadData(byte[] input)
     470        {
     471            byte[] output = new byte[input.Length + (16 - (input.Length % 16))]; // multiple of 16
     472            Array.Copy(input, output, input.Length); // copy old content, keep zeros at end
     473            return output;
     474        }
    218475    }
    219 
    220     /// <summary>
    221     /// Gets or sets the key data.
    222     /// </summary>
    223     /// <value>The key data.</value>
    224     [PropertyInfo(Direction.InputData, "KeyStreamCaption", "KeyStreamTooltip", null,
    225         false, false, QuickWatchFormat.Hex, null)]
    226     public ICryptoolStream KeyStream
    227     {
    228         get
    229         {
    230             if (key == null)
    231             {
    232                 return null;
    233             }
    234             else
    235             {
    236                 return new CStreamWriter(key);
    237             }
    238         }
    239         set
    240         {
    241             if (value != null)
    242             {
    243                 using (CStreamReader reader = value.CreateReader())
    244                 {
    245                     GuiLogMessage("KeyStream changed.", NotificationLevel.Debug);
    246                     key = reader.ReadFully();
    247                 }
    248 
    249                 NotifyUpdateKey();
    250             }
    251         }
    252     }
    253 
    254     /// <summary>
    255     /// Gets or sets the key data.
    256     /// </summary>
    257     /// <value>The key data.</value>
    258     [PropertyInfo(Direction.InputData, "KeyDataCaption", "KeyDataTooltip", null,
    259         false, false, QuickWatchFormat.Hex, null)]
    260     public byte[] KeyData
    261     {
    262       get
    263       {
    264         return key;
    265       }
    266 
    267       set
    268       {
    269         long len = value.Length;
    270         key = new byte[len];
    271 
    272         for (long i = 0; i < len; i++)
    273           key[i] = value[i];
    274 
    275         NotifyUpdateKey();
    276         GuiLogMessage("KeyData changed.", NotificationLevel.Debug);
    277       }
    278     }
    279 
    280     #endregion
    281 
    282     [PropertyInfo(Direction.InputData, "IVCaption", "IVTooltip", null,
    283         false, false, QuickWatchFormat.Hex, null)]
    284     public byte[] IV
    285     {
    286         get
    287         {
    288             return iv;
    289         }
    290         set
    291         {
    292             Array.Clear(iv, 0, iv.Length);
    293 
    294             if (null == value)
    295                 return;
    296 
    297             for (int i = 0; i < value.Length && i < iv.Length; i++)
    298                 iv[i] = value[i];
    299 
    300             NotifyUpdateInput();
    301             GuiLogMessage("InputData changed.", NotificationLevel.Debug);
    302         }
    303     }
    304 
    305 
    306 
    307     #region Output
    308 
    309     // Output
    310     private byte[] outputData = { };
    311 
    312     /// <summary>
    313     /// Notifies the update output.
    314     /// </summary>
    315     private void NotifyUpdateOutput()
    316     {
    317       OnPropertyChanged("OutputStream");
    318       OnPropertyChanged("OutputData");
    319     }
    320 
    321 
    322     /// <summary>
    323     /// Gets or sets the output inputdata stream.
    324     /// </summary>
    325     /// <value>The output inputdata stream.</value>
    326     [PropertyInfo(Direction.OutputData, "OutputStreamCaption", "OutputStreamTooltip", null,
    327         true, false, QuickWatchFormat.Hex, null) ]
    328     public ICryptoolStream OutputStream
    329     {
    330       get
    331       {
    332         if (outputData == null)
    333         {
    334             return null;
    335         }
    336         else
    337         {
    338             return new CStreamWriter(outputData);
    339         }
    340       }
    341     }
    342 
    343     /// <summary>
    344     /// Gets the output inputdata.
    345     /// </summary>
    346     /// <value>The output inputdata.</value>
    347     [PropertyInfo(Direction.OutputData, "OutputDataCaption", "OutputDataTooltip", null,
    348         true, false, QuickWatchFormat.Hex, null)]
    349     public byte[] OutputData
    350     {
    351       get
    352       {
    353         return this.outputData;
    354       }
    355     }
    356 
    357     #endregion
    358 
    359 
    360 
    361     #region INotifyPropertyChanged Member
    362 
    363     public event PropertyChangedEventHandler  PropertyChanged;
    364     /// <summary>
    365     /// Called when [property changed].
    366     /// </summary>
    367     /// <param name="name">The name.</param>
    368     protected void OnPropertyChanged(string name)
    369     {
    370       if (PropertyChanged != null)
    371       {
    372         if (name == "Settings")
    373         {
    374           Crypt();
    375         }
    376         else
    377           PropertyChanged(this, new PropertyChangedEventArgs(name));
    378       }
    379     }
    380 
    381 
    382     /// <summary>
    383     /// GUIs the log message.
    384     /// </summary>
    385     /// <param name="message">The message.</param>
    386     /// <param name="logLevel">The log level.</param>
    387     private void GuiLogMessage(string message, NotificationLevel logLevel)
    388     {
    389       EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this,
    390         new GuiLogEventArgs(message, this, logLevel));
    391     }
    392 
    393     #endregion
    394 
    395 
    396     private void Crypt()
    397     {
    398       // fit key to correct length
    399       byte[] k2 = new byte[settings.KeyLength / 8];
    400       for (int i = 0; i < settings.KeyLength / 8; i++)
    401         if (i < key.Length)
    402           k2[i] = key[i];
    403         else
    404           k2[i] = 0;
    405    
    406 
    407       TwofishManaged tf = TwofishManaged.Create();
    408 
    409       tf.Mode = (settings.Mode == 0) ? CipherMode.CBC : CipherMode.ECB;
    410      
    411       int pos = 0;
    412 
    413       int len = inputdata.Length;
    414       if (settings.Action == 0) // input padding
    415       {
    416           if (len % 16 != 0)
    417               len += (16 - len % 16);
    418       }
    419       if (outputData.Length != len) 
    420         outputData = new byte[len];
    421 
    422       switch (settings.Action)
    423       {
    424         case 0: // encrypt
    425           {
    426             ICryptoTransform encrypt =  tf.CreateEncryptor(k2, iv);
    427 
    428             while (inputdata.Length - pos > encrypt.InputBlockSize)
    429             {
    430               pos += encrypt.TransformBlock(inputdata, pos, encrypt.InputBlockSize, outputData, pos);
    431             }
    432             byte[] final = encrypt.TransformFinalBlock(inputdata, pos, inputdata.Length - pos);
    433             Array.Copy(final, 0, outputData, pos, 16);
    434             encrypt.Dispose();
    435             break;
    436           }
    437         case 1: // decrypt
    438           {
    439             ICryptoTransform decrypt =  tf.CreateDecryptor(k2, iv);
    440 
    441             while (inputdata.Length - pos > decrypt.InputBlockSize)
    442             {
    443               pos += decrypt.TransformBlock(inputdata, pos, decrypt.InputBlockSize, outputData, pos);
    444             }
    445             if (inputdata.Length - pos >  0)
    446             {
    447               byte[] final = decrypt.TransformFinalBlock(inputdata, pos, inputdata.Length - pos);
    448 
    449               for (int i = pos; i < outputData.Length; i++)
    450                 outputData[i] = final[i - pos];
    451             }
    452 
    453             decrypt.Dispose();
    454             break;
    455           }
    456       }
    457 
    458       NotifyUpdateOutput();
    459     }
    460 
    461   }
    462476}
Note: See TracChangeset for help on using the changeset viewer.