source: trunk/SSCext/SSCpkcs5.cs @ 419

Last change on this file since 419 was 419, checked in by Thomas Schmid, 12 years ago
  • merged IControl branch to trunk
  • added KeySearcher sample: KeySearcher-Sample
  • changed some plugins to work with new enumeration
  • new bins
  • 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:: 419                                                                            $://
9// $Author:: schmid                                                                           $://
10// $Date:: 2009-08-06 22:08:23 +0000 (Thu, 06 Aug 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.