BufferedAsymmetricBlockCipher.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto
  5. {
  6. /**
  7. * a buffer wrapper for an asymmetric block cipher, allowing input
  8. * to be accumulated in a piecemeal fashion until final processing.
  9. */
  10. public class BufferedAsymmetricBlockCipher
  11. : BufferedCipherBase
  12. {
  13. private readonly IAsymmetricBlockCipher cipher;
  14. private byte[] buffer;
  15. private int bufOff;
  16. /**
  17. * base constructor.
  18. *
  19. * @param cipher the cipher this buffering object wraps.
  20. */
  21. public BufferedAsymmetricBlockCipher(
  22. IAsymmetricBlockCipher cipher)
  23. {
  24. this.cipher = cipher;
  25. }
  26. /**
  27. * return the amount of data sitting in the buffer.
  28. *
  29. * @return the amount of data sitting in the buffer.
  30. */
  31. internal int GetBufferPosition()
  32. {
  33. return bufOff;
  34. }
  35. public override string AlgorithmName
  36. {
  37. get { return cipher.AlgorithmName; }
  38. }
  39. public override int GetBlockSize()
  40. {
  41. return cipher.GetInputBlockSize();
  42. }
  43. public override int GetOutputSize(
  44. int length)
  45. {
  46. return cipher.GetOutputBlockSize();
  47. }
  48. public override int GetUpdateOutputSize(
  49. int length)
  50. {
  51. return 0;
  52. }
  53. /**
  54. * initialise the buffer and the underlying cipher.
  55. *
  56. * @param forEncryption if true the cipher is initialised for
  57. * encryption, if false for decryption.
  58. * @param param the key and other data required by the cipher.
  59. */
  60. public override void Init(
  61. bool forEncryption,
  62. ICipherParameters parameters)
  63. {
  64. Reset();
  65. cipher.Init(forEncryption, parameters);
  66. //
  67. // we allow for an extra byte where people are using their own padding
  68. // mechanisms on a raw cipher.
  69. //
  70. this.buffer = new byte[cipher.GetInputBlockSize() + (forEncryption ? 1 : 0)];
  71. this.bufOff = 0;
  72. }
  73. public override byte[] ProcessByte(
  74. byte input)
  75. {
  76. if (bufOff >= buffer.Length)
  77. throw new DataLengthException("attempt to process message too long for cipher");
  78. buffer[bufOff++] = input;
  79. return null;
  80. }
  81. public override int ProcessByte(byte input, byte[] output, int outOff)
  82. {
  83. if (bufOff >= buffer.Length)
  84. throw new DataLengthException("attempt to process message too long for cipher");
  85. buffer[bufOff++] = input;
  86. return 0;
  87. }
  88. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  89. public override int ProcessByte(byte input, Span<byte> output)
  90. {
  91. if (bufOff >= buffer.Length)
  92. throw new DataLengthException("attempt to process message too long for cipher");
  93. buffer[bufOff++] = input;
  94. return 0;
  95. }
  96. #endif
  97. public override byte[] ProcessBytes(
  98. byte[] input,
  99. int inOff,
  100. int length)
  101. {
  102. if (length < 1)
  103. return null;
  104. if (input == null)
  105. throw new ArgumentNullException("input");
  106. if (bufOff + length > buffer.Length)
  107. throw new DataLengthException("attempt to process message too long for cipher");
  108. Array.Copy(input, inOff, buffer, bufOff, length);
  109. bufOff += length;
  110. return null;
  111. }
  112. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  113. public override int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
  114. {
  115. Check.DataLength(input, buffer.Length - bufOff, "attempt to process message too long for cipher");
  116. input.CopyTo(buffer.AsSpan(bufOff));
  117. bufOff += input.Length;
  118. return 0;
  119. }
  120. #endif
  121. /**
  122. * process the contents of the buffer using the underlying
  123. * cipher.
  124. *
  125. * @return the result of the encryption/decryption process on the
  126. * buffer.
  127. * @exception InvalidCipherTextException if we are given a garbage block.
  128. */
  129. public override byte[] DoFinal()
  130. {
  131. byte[] outBytes = bufOff > 0
  132. ? cipher.ProcessBlock(buffer, 0, bufOff)
  133. : EmptyBuffer;
  134. Reset();
  135. return outBytes;
  136. }
  137. public override byte[] DoFinal(
  138. byte[] input,
  139. int inOff,
  140. int length)
  141. {
  142. ProcessBytes(input, inOff, length);
  143. return DoFinal();
  144. }
  145. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  146. public override int DoFinal(Span<byte> output)
  147. {
  148. int result = 0;
  149. if (bufOff > 0)
  150. {
  151. byte[] outBytes = cipher.ProcessBlock(buffer, 0, bufOff);
  152. outBytes.CopyTo(output);
  153. result = outBytes.Length;
  154. }
  155. Reset();
  156. return result;
  157. }
  158. #endif
  159. /// <summary>Reset the buffer</summary>
  160. public override void Reset()
  161. {
  162. if (buffer != null)
  163. {
  164. Array.Clear(buffer, 0, buffer.Length);
  165. bufOff = 0;
  166. }
  167. }
  168. }
  169. }
  170. #pragma warning restore
  171. #endif