PKCS1MaskGenerationMethod.cs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. //
  2. // PKCS1MaskGenerationMethod.cs: Handles PKCS#1 mask generation.
  3. //
  4. // Author:
  5. // Sebastien Pouliot ([email protected])
  6. //
  7. // (C) 2002 Motus Technologies Inc. (http://www.motus.com)
  8. //
  9. using System;
  10. using System.Security.Cryptography;
  11. namespace System.Security.Cryptography {
  12. // References:
  13. // a. PKCS#1: RSA Cryptography Standard
  14. // http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/index.html
  15. public class PKCS1MaskGenerationMethod : MaskGenerationMethod {
  16. private string hashName;
  17. public PKCS1MaskGenerationMethod()
  18. {
  19. hashName = "SHA1";
  20. }
  21. public string HashName
  22. {
  23. get { return hashName; }
  24. set {
  25. if (value == null)
  26. hashName = "SHA1";
  27. else
  28. hashName = value;
  29. }
  30. }
  31. // I2OSP converts a nonnegative integer to an octet string of a specified length.
  32. // in this case xLen is always 4 so we simplify the function
  33. private byte[] I2OSP (int x)
  34. {
  35. byte[] array = BitConverter.GetBytes (x);
  36. // FIXME: This line is commented for compatibility with MS .NET
  37. // Framework.
  38. // Array.Reverse (array); // big-little endian issues
  39. return array;
  40. }
  41. // from MGF1 on page 48 from PKCS#1 v2.1 (pdf version)
  42. public override byte[] GenerateMask (byte[] mgfSeed, int maskLen)
  43. {
  44. // 1. If maskLen > 2^32 hLen, output “mask too long” and stop.
  45. // easy - this is impossible by using a int (31bits) as parameter ;-)
  46. // BUT with a signed int we do have to check for negative values!
  47. if (maskLen < 0)
  48. throw new OverflowException();
  49. int mgfSeedLength = mgfSeed.Length;
  50. HashAlgorithm hash = HashAlgorithm.Create (hashName);
  51. int hLen = (hash.HashSize >> 3); // from bits to bytes
  52. int iterations = (maskLen / hLen);
  53. if (maskLen % hLen != 0)
  54. iterations++;
  55. // 2. Let T be the empty octet string.
  56. byte[] T = new byte [iterations * hLen];
  57. byte[] toBeHashed = new byte [mgfSeedLength + 4];
  58. int pos = 0;
  59. // 3. For counter from 0 to (maskLen / hLen) – 1, do the following:
  60. for (int counter = 0; counter < iterations; counter++) {
  61. // a. Convert counter to an octet string C of length 4 octets
  62. // C = I2OSP (counter, 4)
  63. byte[] C = I2OSP (counter);
  64. // b. Concatenate the hash of the seed mgfSeed and C to the octet string T:
  65. // T = T || Hash (mgfSeed || C)
  66. Array.Copy (mgfSeed, 0, toBeHashed, 0, mgfSeedLength);
  67. Array.Copy (C, 0, toBeHashed, mgfSeedLength, 4);
  68. byte[] output = hash.ComputeHash (toBeHashed);
  69. Array.Copy (output, 0, T, pos, hLen);
  70. pos += mgfSeedLength;
  71. }
  72. // 4. Output the leading maskLen octets of T as the octet string mask.
  73. byte[] mask = new byte [maskLen];
  74. Array.Copy (T, 0, mask, 0, maskLen);
  75. return mask;
  76. }
  77. }
  78. }