source: trunk/SSCext/TwofishEncryption.cs @ 226

Last change on this file since 226 was 226, checked in by Gerhard Junker, 13 years ago

2FISH - first fixes

  • Property svn:keywords set to URL Author Date Rev Id
File size: 6.7 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////////////////////
2// CrypTool V2
3// © 2008 - Gerhard Junker
4// Apache License see http://www.apache.org/licenses/
5//
6// $HeadURL: trunk/SSCext/TwofishEncryption.cs $
7//////////////////////////////////////////////////////////////////////////////////////////////////
8// $Revision:: 226                                                                            $://
9// $Author:: junker                                                                           $://
10// $Date:: 2009-02-17 18:36:05 +0000 (Tue, 17 Feb 2009)                                       $://
11//////////////////////////////////////////////////////////////////////////////////////////////////
12
13// more about at http://www.schneier.com/twofish.html
14// used sources from http://www.codeproject.com/KB/recipes/twofish_csharp.aspx
15
16using System;
17using System.Diagnostics;
18using System.Security.Cryptography;
19
20namespace System.Security.Cryptography
21{
22
23  partial class TwofishManaged
24  {
25    /// <summary>
26    /// Summary description for TwofishEncryption.
27    /// </summary>
28    internal class TwofishEncryption : TwofishBase, ICryptoTransform
29    {
30      public TwofishEncryption(int keyLen, ref byte[] key, ref byte[] iv, CipherMode cMode, 
31        EncryptionDirection direction)
32      {
33        // convert our key into an array of ints
34        for (int i=0; i < key.Length / 4; i++)
35        {
36          Key[i] = 
37            (uint)(key[i * 4 + 3] << 24) | 
38            (uint)(key[i * 4 + 2] << 16) | 
39            (uint)(key[i * 4 + 1] <<  8) | 
40            (uint)(key[i * 4 + 0]      );
41        }
42
43        cipherMode = cMode;
44
45        // we only need to convert our IV if we are using CBC
46        if (cipherMode == CipherMode.CBC)
47        {
48          for (int i=0; i < 4; i++)
49          {
50            IV[i] = 
51              (uint)(iv[i * 4 + 3] << 24) | 
52              (uint)(iv[i * 4 + 2] << 16) | 
53              (uint)(iv[i * 4 + 1] <<  8) | 
54              (uint)(iv[i * 4 + 0]      );
55          }
56        }
57
58        encryptionDirection = direction;
59        reKey(keyLen, ref Key);
60
61#if DEBUG2
62        for (int i =  0; i < Key.Length; i++)
63          Debug.WriteLine(i.ToString("00") + " " + Key[i].ToString("x"));
64#endif
65      }
66
67      // need to have this method due to IDisposable - just can't think of a reason to use it for in this class
68      public void Dispose()
69      {
70      }
71
72
73      /// <summary>
74      /// Transform a block depending on whether we are encrypting or decrypting
75      /// </summary>
76      /// <param name="inputBuffer"></param>
77      /// <param name="inputOffset"></param>
78      /// <param name="inputCount"></param>
79      /// <param name="outputBuffer"></param>
80      /// <param name="outputOffset"></param>
81      /// <returns></returns>
82      public int TransformBlock(
83        byte[] inputBuffer,
84        int inputOffset,
85        int inputCount,
86        byte[] outputBuffer,
87        int outputOffset
88        )
89      {
90        uint[] x=new uint[4];
91
92        // load it up
93        for (int i=0; i < 4; i++)
94        {
95          x[i] = 
96            (uint)(inputBuffer[i * 4 + 3 + inputOffset] << 24) | 
97            (uint)(inputBuffer[i * 4 + 2 + inputOffset] << 16) |
98            (uint)(inputBuffer[i * 4 + 1 + inputOffset] <<  8) | 
99            (uint)(inputBuffer[i * 4 + 0 + inputOffset]      );
100        }
101
102        if (encryptionDirection == EncryptionDirection.Encrypting)
103        {
104          blockEncrypt(ref x);
105        }
106        else
107        {
108          blockDecrypt(ref x);
109        }
110
111
112        // load it up
113        for (int i=0; i < 4; i++)
114        {
115          outputBuffer[i * 4 + 0 + outputOffset] = b0(x[i]);
116          outputBuffer[i * 4 + 1 + outputOffset] = b1(x[i]);
117          outputBuffer[i * 4 + 2 + outputOffset] = b2(x[i]);
118          outputBuffer[i * 4 + 3 + outputOffset] = b3(x[i]);
119        }
120
121
122        return inputCount;
123      }
124
125      public byte[] TransformFinalBlock(
126        byte[] inputBuffer,
127        int inputOffset,
128        int inputCount
129        )
130      {
131        byte[] outputBuffer;// = new byte[0];
132
133        if (inputCount > 0)
134        {
135          outputBuffer = new byte[16]; // blocksize
136          byte[] tmp = new byte[16];
137          uint[] x=new uint[4];
138
139       
140          // Padding
141          Array.Clear(tmp, 0, tmp.Length);
142          for (int i = 0; i < inputCount; i++)
143              tmp[i] = inputBuffer[inputOffset + i];
144
145       
146          // load it up
147          for (int i=0; i < 4; i++) // should be okay as we have already said to pad with zeros
148          {
149            x[i] = 
150              (uint)(tmp[i * 4 + 3] << 24) | 
151              (uint)(tmp[i * 4 + 2] << 16) |
152              (uint)(tmp[i * 4 + 1] <<  8) | 
153              (uint)(tmp[i * 4 + 0]      );
154
155          }
156
157          if (encryptionDirection == EncryptionDirection.Encrypting)
158          {
159            blockEncrypt(ref x);
160          }
161          else
162          {
163            blockDecrypt(ref x);
164          }
165
166          // load it up
167          for (int i=0; i < 4; i++)
168          {
169            outputBuffer[i * 4 + 0] = b0(x[i]);
170            outputBuffer[i * 4 + 1] = b1(x[i]);
171            outputBuffer[i * 4 + 2] = b2(x[i]);
172            outputBuffer[i * 4 + 3] = b3(x[i]);
173          }
174        }
175        else
176        {
177          outputBuffer = new byte[0]; // the .NET framework doesn't like it if you return null - this calms it down
178        }
179
180        if (encryptionDirection == EncryptionDirection.Encrypting)
181            return outputBuffer;
182
183        int len = 15;
184        while(len >= 0 && outputBuffer[len] == 0) len--;
185
186        byte[] erg = new byte[len + 1];
187
188        Array.Copy(outputBuffer, erg, len + 1);
189        return erg;
190      }
191
192      // not worked out this property yet - placing break points here just don't get caught.
193      private bool canReuseTransform = true;
194      public bool CanReuseTransform
195      {
196        get
197        {
198          return canReuseTransform;
199        }
200      }
201
202      // I normally set this to false when block encrypting so that I can work on one block at a time
203      // but for compression and stream type ciphers this can be set to true so that you get all the data
204      private bool canTransformMultipleBlocks = false;
205      public bool CanTransformMultipleBlocks
206      {
207        get
208        {
209          return canTransformMultipleBlocks;
210        }
211      }
212
213      public int InputBlockSize
214      {
215        get
216        {
217          return inputBlockSize;
218        }
219      }
220
221      public int OutputBlockSize
222      {
223        get
224        {
225          return outputBlockSize;
226        }
227      }
228
229      private EncryptionDirection encryptionDirection;
230    }
231  }
232}
Note: See TracBrowser for help on using the repository browser.