HMac.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using System.Collections;
  4. using Org.BouncyCastle.Crypto;
  5. using Org.BouncyCastle.Crypto.Parameters;
  6. using Org.BouncyCastle.Utilities;
  7. namespace Org.BouncyCastle.Crypto.Macs
  8. {
  9. /**
  10. * HMAC implementation based on RFC2104
  11. *
  12. * H(K XOR opad, H(K XOR ipad, text))
  13. */
  14. public class HMac
  15. : IMac
  16. {
  17. private const byte IPAD = (byte)0x36;
  18. private const byte OPAD = (byte)0x5C;
  19. private readonly IDigest digest;
  20. private readonly int digestSize;
  21. private readonly int blockLength;
  22. private IMemoable ipadState;
  23. private IMemoable opadState;
  24. private readonly byte[] inputPad;
  25. private readonly byte[] outputBuf;
  26. public HMac(IDigest digest)
  27. {
  28. this.digest = digest;
  29. this.digestSize = digest.GetDigestSize();
  30. this.blockLength = digest.GetByteLength();
  31. this.inputPad = new byte[blockLength];
  32. this.outputBuf = new byte[blockLength + digestSize];
  33. }
  34. public virtual string AlgorithmName
  35. {
  36. get { return digest.AlgorithmName + "/HMAC"; }
  37. }
  38. public virtual IDigest GetUnderlyingDigest()
  39. {
  40. return digest;
  41. }
  42. public virtual void Init(ICipherParameters parameters)
  43. {
  44. digest.Reset();
  45. byte[] key = ((KeyParameter)parameters).GetKey();
  46. int keyLength = key.Length;
  47. if (keyLength > blockLength)
  48. {
  49. digest.BlockUpdate(key, 0, keyLength);
  50. digest.DoFinal(inputPad, 0);
  51. keyLength = digestSize;
  52. }
  53. else
  54. {
  55. Array.Copy(key, 0, inputPad, 0, keyLength);
  56. }
  57. Array.Clear(inputPad, keyLength, blockLength - keyLength);
  58. Array.Copy(inputPad, 0, outputBuf, 0, blockLength);
  59. XorPad(inputPad, blockLength, IPAD);
  60. XorPad(outputBuf, blockLength, OPAD);
  61. if (digest is IMemoable)
  62. {
  63. opadState = ((IMemoable)digest).Copy();
  64. ((IDigest)opadState).BlockUpdate(outputBuf, 0, blockLength);
  65. }
  66. digest.BlockUpdate(inputPad, 0, inputPad.Length);
  67. if (digest is IMemoable)
  68. {
  69. ipadState = ((IMemoable)digest).Copy();
  70. }
  71. }
  72. public virtual int GetMacSize()
  73. {
  74. return digestSize;
  75. }
  76. public virtual void Update(byte input)
  77. {
  78. digest.Update(input);
  79. }
  80. public virtual void BlockUpdate(byte[] input, int inOff, int len)
  81. {
  82. digest.BlockUpdate(input, inOff, len);
  83. }
  84. public virtual int DoFinal(byte[] output, int outOff)
  85. {
  86. digest.DoFinal(outputBuf, blockLength);
  87. if (opadState != null)
  88. {
  89. ((IMemoable)digest).Reset(opadState);
  90. digest.BlockUpdate(outputBuf, blockLength, digest.GetDigestSize());
  91. }
  92. else
  93. {
  94. digest.BlockUpdate(outputBuf, 0, outputBuf.Length);
  95. }
  96. int len = digest.DoFinal(output, outOff);
  97. Array.Clear(outputBuf, blockLength, digestSize);
  98. if (ipadState != null)
  99. {
  100. ((IMemoable)digest).Reset(ipadState);
  101. }
  102. else
  103. {
  104. digest.BlockUpdate(inputPad, 0, inputPad.Length);
  105. }
  106. return len;
  107. }
  108. /**
  109. * Reset the mac generator.
  110. */
  111. public virtual void Reset()
  112. {
  113. // Reset underlying digest
  114. digest.Reset();
  115. // Initialise the digest
  116. digest.BlockUpdate(inputPad, 0, inputPad.Length);
  117. }
  118. private static void XorPad(byte[] pad, int len, byte n)
  119. {
  120. for (int i = 0; i < len; ++i)
  121. {
  122. pad[i] ^= n;
  123. }
  124. }
  125. }
  126. }
  127. #endif