source: trunk/SSCext/SSCpkcs5.cs @ 226

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

Implementing Tiger and Whirlpool as HMAC (was HashAlgorithm)
Added Tiger and Whirlpool to PKCS#5

  • Property svn:keywords set to URL Author Date Rev Id
File size: 8.0 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////////////////////
2// CrypTool V2
3// © 2008 - Gerhard Junker
4// Apache License see http://www.apache.org/licenses/
5//
6// $HeadURL: trunk/SSCext/SSCpkcs5.cs $
7//////////////////////////////////////////////////////////////////////////////////////////////////
8// $Revision:: 198                                                                            $://
9// $Author:: junker                                                                           $://
10// $Date:: 2009-01-16 10:18:00 +0000 (Fri, 16 Jan 2009)                                       $://
11//////////////////////////////////////////////////////////////////////////////////////////////////
12
13using System;
14using System.Text;
15
16using System.Security.Cryptography;
17using System.Runtime.InteropServices;
18
19#if DEBUG
20using System.Diagnostics;
21#endif
22
23namespace System.Security.Cryptography
24{
25  /// <summary>
26  /// insert PKSC #5 v2 into default namespace
27  /// </summary>
28  [ComVisibleAttribute(true)]
29  public class PKCS5MaskGenerationMethod : System.Security.Cryptography.MaskGenerationMethod
30  {
31
32    /// <summary>
33    /// implemented hash functions
34    /// </summary>
35    public enum ShaFunction
36    {
37      MD5,
38      SHA1,
39      SHA256,
40      SHA384,
41      SHA512,
42      TIGER,
43      WHIRLPOOL
44    };
45
46    private ShaFunction selectedShaFunction = ShaFunction.SHA256;
47
48    /// <summary>
49    /// Gets or sets the selected sha function.
50    /// </summary>
51    /// <value>The selected sha function.</value>
52    public ShaFunction SelectedShaFunction
53    {
54      get
55      {
56        return selectedShaFunction;
57      }
58      set
59      {
60        selectedShaFunction = value;
61      }
62    }
63
64
65    /// <summary>
66    /// Gets the length of the hash in Bytes.
67    /// </summary>
68    /// <param name="SelectedShaFunction">The selected sha function.</param>
69    /// <returns></returns>
70    public static int GetHashLength(ShaFunction SelectedShaFunction)
71    {
72      int[] length = 
73      {
74        16, // MD5
75        20, // SHA1
76        32, // SHA256
77        48, // SHA384
78        64, // SHA512
79        24, // TIGER
80        64  // WHIRLPOOL
81      };
82
83      return length[(int)SelectedShaFunction];
84    }
85
86    /// <summary>
87    /// Gets the sha hash.
88    /// </summary>
89    /// <param name="key">The key.</param>
90    /// <param name="salt">The salt.</param>
91    /// <returns></returns>
92    private byte[] GetShaHash(byte[] key, byte[] salt)
93    {
94      HMAC ha;
95
96      switch (selectedShaFunction)
97      {
98        case ShaFunction.MD5:
99          ha = (HMAC)new System.Security.Cryptography.HMACMD5();
100          break;
101
102        case ShaFunction.SHA1:
103          ha = (HMAC)new System.Security.Cryptography.HMACSHA1();
104          break;
105
106        case ShaFunction.SHA256:
107          ha = (HMAC)new System.Security.Cryptography.HMACSHA256();
108          break;
109
110        case ShaFunction.SHA384:
111          ha = (HMAC)new System.Security.Cryptography.HMACSHA384();
112          break;
113
114        case ShaFunction.SHA512:
115          ha = (HMAC)new System.Security.Cryptography.HMACSHA512();
116          break;
117
118        case ShaFunction.TIGER:
119          ha = (HMAC)new System.Security.Cryptography.HMACTIGER2();
120          break;
121
122        case ShaFunction.WHIRLPOOL:
123          ha = (HMAC)new System.Security.Cryptography.HMACWHIRLPOOL();
124          break;
125
126        default:
127          throw new ArgumentOutOfRangeException("SelectedShaFunction");
128      }
129
130      ha.Key = key;
131      byte[] h = ha.ComputeHash(salt);
132      ha.Clear();
133
134      return h;
135    }
136
137    /// <summary>
138    /// Gens the key block.
139    /// </summary>
140    /// <param name="password">The password.</param>
141    /// <param name="salt">The salt.</param>
142    /// <param name="count">The count.</param>
143    /// <param name="blockIndex">Index of the block.</param>
144    /// <returns></returns>
145    private byte[] GenKeyBlock(byte[] password, byte[] salt, int count, int blockIndex)
146    {
147      int len = salt.Length;
148      byte[] data = new byte[len + 4];
149
150      for (int i = 0; i < len; i++)
151        data[i] = salt[i];
152
153      data[len] = data[len + 1] = data[len + 2] = 0;
154      data[len + 3] = (byte)blockIndex;
155
156      byte[] u1 = GetShaHash(password, data);
157
158      byte[] result = new byte[u1.Length];
159      for (int i = 0; i < u1.Length; i++)
160        result[i] = u1[i];
161
162      for (int c = 1; c < count; c++)
163      {
164        byte[] u2 = GetShaHash(password, u1);
165
166        for (int i = 0; i < result.Length; i++)
167        {
168          result[i] ^= u2[i];
169          u1[i] = u2[i];
170        }
171      }
172
173      return result;
174    }
175
176    /// <summary>
177    /// When overridden in a derived class,
178    /// generates a mask with the specified length using the specified random salt.
179    /// </summary>
180    /// <param name="rgbSalt">The random salt to use to compute the mask.</param>
181    /// <param name="cbReturn">The length of the generated mask in bytes.</param>
182    /// <returns>
183    /// A randomly generated mask whose length is equal to the <paramref name="cbReturn"/> parameter.
184    /// </returns>
185    [ComVisibleAttribute(true)]
186    public override byte[] GenerateMask
187        (
188            byte[] rgbSalt,
189            int cbReturn
190        )
191    {
192      // member implemented for compatibility only ....
193      // throw new System.NotImplementedException("GenerateMask needs more parameters");
194
195      // Computes masks according to PKCS #1 for use by key exchange algorithms.
196      // Generates and returns a mask from the specified random salt of the specified length.
197      PKCS1MaskGenerationMethod pkcs1 = new PKCS1MaskGenerationMethod();
198      return pkcs1.GenerateMask(rgbSalt, cbReturn);
199    }
200
201    /// <summary>
202    /// When overridden in a derived class,
203    /// generates a mask with the specified length using the specified password and random salt.
204    /// Implementing PBKDF2 of PKCS #5 v2.1 Password-Basd Cryptography Standard
205    /// </summary>
206    /// <param name="password">The password to use to compute the mask.</param>
207    /// <param name="rgbSalt">The random salt (seed) to use to compute the mask.</param>
208    /// <param name="count">The iteration count, a positive integer</param>
209    /// <param name="cbReturn">The length of the generated mask in bytes.</param>
210    /// <returns>
211    /// A randomly generated mask whose length is equal to the <paramref name="cbReturn"/> parameter.
212    /// </returns>
213    [ComVisibleAttribute(true)]
214    public byte[] GenerateMask
215        (
216            byte[] password,
217            byte[] rgbSalt,
218            int count,
219            int cbReturn
220        )
221    {
222      if (cbReturn <= 0)
223        cbReturn = 1;
224      //throw new ArgumentOutOfRangeException("cbReturn", "cbReturn must be positive.");
225
226      byte[] key = new byte[cbReturn];
227      for (int i = 0; i < cbReturn; i++)
228        key[i] = 0;
229
230      if (count <= 0)
231        count = 1;
232
233      int hLen = GetHashLength(this.SelectedShaFunction);
234
235      // Let blockCount be the number of hLen-bytes blocks in the derived key, rounding up,
236      // let fillBytes be the number of bytes in the last block.
237      int blockCount = cbReturn / hLen + 1;
238      int fillBytes = cbReturn - (blockCount - 1) * hLen;
239
240      if (blockCount > 255)
241      {
242        string msg = string.Format("cbReturn must be lesser than {0} by implementation limits.", hLen * 255);
243        throw new ArgumentOutOfRangeException("cbReturn", "msg");
244      }
245
246      int outPos = 0;
247
248      for (int blockIndex = 0; blockIndex < blockCount - 1; blockIndex++)
249      {
250        byte[] block = GenKeyBlock(password, rgbSalt, count, blockIndex + 1);
251        for (int i = 0; i < hLen; i++)
252          key[outPos++] = block[i];
253      }
254
255      // last block
256      if (fillBytes > 0)
257      {
258        byte[] block = GenKeyBlock(password, rgbSalt, count, blockCount);
259        for (int i = 0; i < fillBytes; i++)
260          key[outPos++] = block[i];
261      }
262
263      return key;
264    } // PBKDF2
265  } // class
266}
267
Note: See TracBrowser for help on using the repository browser.