CbcBlockCipherMac.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Modes;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Paddings;
  6. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Macs
  7. {
  8. /**
  9. * standard CBC Block Cipher MAC - if no padding is specified the default of
  10. * pad of zeroes is used.
  11. */
  12. public class CbcBlockCipherMac
  13. : IMac
  14. {
  15. private byte[] buf;
  16. private int bufOff;
  17. private IBlockCipher cipher;
  18. private IBlockCipherPadding padding;
  19. private int macSize;
  20. /**
  21. * create a standard MAC based on a CBC block cipher. This will produce an
  22. * authentication code half the length of the block size of the cipher.
  23. *
  24. * @param cipher the cipher to be used as the basis of the MAC generation.
  25. */
  26. public CbcBlockCipherMac(
  27. IBlockCipher cipher)
  28. : this(cipher, (cipher.GetBlockSize() * 8) / 2, null)
  29. {
  30. }
  31. /**
  32. * create a standard MAC based on a CBC block cipher. This will produce an
  33. * authentication code half the length of the block size of the cipher.
  34. *
  35. * @param cipher the cipher to be used as the basis of the MAC generation.
  36. * @param padding the padding to be used to complete the last block.
  37. */
  38. public CbcBlockCipherMac(
  39. IBlockCipher cipher,
  40. IBlockCipherPadding padding)
  41. : this(cipher, (cipher.GetBlockSize() * 8) / 2, padding)
  42. {
  43. }
  44. /**
  45. * create a standard MAC based on a block cipher with the size of the
  46. * MAC been given in bits. This class uses CBC mode as the basis for the
  47. * MAC generation.
  48. * <p>
  49. * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
  50. * or 16 bits if being used as a data authenticator (FIPS Publication 113),
  51. * and in general should be less than the size of the block cipher as it reduces
  52. * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
  53. * </p>
  54. * @param cipher the cipher to be used as the basis of the MAC generation.
  55. * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
  56. */
  57. public CbcBlockCipherMac(
  58. IBlockCipher cipher,
  59. int macSizeInBits)
  60. : this(cipher, macSizeInBits, null)
  61. {
  62. }
  63. /**
  64. * create a standard MAC based on a block cipher with the size of the
  65. * MAC been given in bits. This class uses CBC mode as the basis for the
  66. * MAC generation.
  67. * <p>
  68. * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
  69. * or 16 bits if being used as a data authenticator (FIPS Publication 113),
  70. * and in general should be less than the size of the block cipher as it reduces
  71. * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
  72. * </p>
  73. * @param cipher the cipher to be used as the basis of the MAC generation.
  74. * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
  75. * @param padding the padding to be used to complete the last block.
  76. */
  77. public CbcBlockCipherMac(
  78. IBlockCipher cipher,
  79. int macSizeInBits,
  80. IBlockCipherPadding padding)
  81. {
  82. if ((macSizeInBits % 8) != 0)
  83. throw new ArgumentException("MAC size must be multiple of 8");
  84. this.cipher = new CbcBlockCipher(cipher);
  85. this.padding = padding;
  86. this.macSize = macSizeInBits / 8;
  87. buf = new byte[cipher.GetBlockSize()];
  88. bufOff = 0;
  89. }
  90. public string AlgorithmName
  91. {
  92. get { return cipher.AlgorithmName; }
  93. }
  94. public void Init(
  95. ICipherParameters parameters)
  96. {
  97. Reset();
  98. cipher.Init(true, parameters);
  99. }
  100. public int GetMacSize()
  101. {
  102. return macSize;
  103. }
  104. public void Update(
  105. byte input)
  106. {
  107. if (bufOff == buf.Length)
  108. {
  109. cipher.ProcessBlock(buf, 0, buf, 0);
  110. bufOff = 0;
  111. }
  112. buf[bufOff++] = input;
  113. }
  114. public void BlockUpdate(
  115. byte[] input,
  116. int inOff,
  117. int len)
  118. {
  119. if (len < 0)
  120. throw new ArgumentException("Can't have a negative input length!");
  121. int blockSize = cipher.GetBlockSize();
  122. int gapLen = blockSize - bufOff;
  123. if (len > gapLen)
  124. {
  125. Array.Copy(input, inOff, buf, bufOff, gapLen);
  126. cipher.ProcessBlock(buf, 0, buf, 0);
  127. bufOff = 0;
  128. len -= gapLen;
  129. inOff += gapLen;
  130. while (len > blockSize)
  131. {
  132. cipher.ProcessBlock(input, inOff, buf, 0);
  133. len -= blockSize;
  134. inOff += blockSize;
  135. }
  136. }
  137. Array.Copy(input, inOff, buf, bufOff, len);
  138. bufOff += len;
  139. }
  140. public int DoFinal(
  141. byte[] output,
  142. int outOff)
  143. {
  144. int blockSize = cipher.GetBlockSize();
  145. if (padding == null)
  146. {
  147. // pad with zeroes
  148. while (bufOff < blockSize)
  149. {
  150. buf[bufOff++] = 0;
  151. }
  152. }
  153. else
  154. {
  155. if (bufOff == blockSize)
  156. {
  157. cipher.ProcessBlock(buf, 0, buf, 0);
  158. bufOff = 0;
  159. }
  160. padding.AddPadding(buf, bufOff);
  161. }
  162. cipher.ProcessBlock(buf, 0, buf, 0);
  163. Array.Copy(buf, 0, output, outOff, macSize);
  164. Reset();
  165. return macSize;
  166. }
  167. /**
  168. * Reset the mac generator.
  169. */
  170. public void Reset()
  171. {
  172. // Clear the buffer.
  173. Array.Clear(buf, 0, buf.Length);
  174. bufOff = 0;
  175. // Reset the underlying cipher.
  176. cipher.Reset();
  177. }
  178. }
  179. }
  180. #pragma warning restore
  181. #endif