CipherStream.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. #if NETCOREAPP1_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  5. using System.Buffers;
  6. #endif
  7. using System.Diagnostics;
  8. using System.IO;
  9. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  10. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
  11. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.IO
  12. {
  13. public sealed class CipherStream
  14. : Stream
  15. {
  16. private readonly Stream m_stream;
  17. private readonly IBufferedCipher m_readCipher, m_writeCipher;
  18. private byte[] m_readBuf;
  19. private int m_readBufPos;
  20. private bool m_readEnded;
  21. public CipherStream(Stream stream, IBufferedCipher readCipher, IBufferedCipher writeCipher)
  22. {
  23. m_stream = stream;
  24. if (readCipher != null)
  25. {
  26. m_readCipher = readCipher;
  27. m_readBuf = null;
  28. }
  29. if (writeCipher != null)
  30. {
  31. m_writeCipher = writeCipher;
  32. }
  33. }
  34. public IBufferedCipher ReadCipher => m_readCipher;
  35. public IBufferedCipher WriteCipher => m_writeCipher;
  36. public override bool CanRead
  37. {
  38. get { return m_stream.CanRead; }
  39. }
  40. public sealed override bool CanSeek
  41. {
  42. get { return false; }
  43. }
  44. public override bool CanWrite
  45. {
  46. get { return m_stream.CanWrite; }
  47. }
  48. #if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER || (UNITY_2021_2_OR_NEWER && (NET_STANDARD_2_0 || NET_STANDARD_2_1))
  49. public override void CopyTo(Stream destination, int bufferSize)
  50. {
  51. if (m_readCipher == null)
  52. {
  53. m_stream.CopyTo(destination, bufferSize);
  54. }
  55. else
  56. {
  57. base.CopyTo(destination, bufferSize);
  58. }
  59. }
  60. #endif
  61. public override void Flush()
  62. {
  63. m_stream.Flush();
  64. }
  65. public sealed override long Length
  66. {
  67. get { throw new NotSupportedException(); }
  68. }
  69. public sealed override long Position
  70. {
  71. get { throw new NotSupportedException(); }
  72. set { throw new NotSupportedException(); }
  73. }
  74. public override int Read(byte[] buffer, int offset, int count)
  75. {
  76. if (m_readCipher == null)
  77. return m_stream.Read(buffer, offset, count);
  78. Streams.ValidateBufferArguments(buffer, offset, count);
  79. int num = 0;
  80. while (num < count)
  81. {
  82. if (m_readBuf == null || m_readBufPos >= m_readBuf.Length)
  83. {
  84. if (!FillInBuf())
  85. break;
  86. }
  87. int numToCopy = System.Math.Min(count - num, m_readBuf.Length - m_readBufPos);
  88. Array.Copy(m_readBuf, m_readBufPos, buffer, offset + num, numToCopy);
  89. m_readBufPos += numToCopy;
  90. num += numToCopy;
  91. }
  92. return num;
  93. }
  94. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  95. public override int Read(Span<byte> buffer)
  96. {
  97. if (buffer.IsEmpty)
  98. return 0;
  99. if (m_readCipher == null)
  100. return m_stream.Read(buffer);
  101. int num = 0;
  102. while (num < buffer.Length)
  103. {
  104. if (m_readBuf == null || m_readBufPos >= m_readBuf.Length)
  105. {
  106. if (!FillInBuf())
  107. break;
  108. }
  109. int numToCopy = System.Math.Min(buffer.Length - num, m_readBuf.Length - m_readBufPos);
  110. m_readBuf.AsSpan(m_readBufPos, numToCopy).CopyTo(buffer[num..]);
  111. m_readBufPos += numToCopy;
  112. num += numToCopy;
  113. }
  114. return num;
  115. }
  116. #endif
  117. public override int ReadByte()
  118. {
  119. if (m_readCipher == null)
  120. return m_stream.ReadByte();
  121. if (m_readBuf == null || m_readBufPos >= m_readBuf.Length)
  122. {
  123. if (!FillInBuf())
  124. return -1;
  125. }
  126. return m_readBuf[m_readBufPos++];
  127. }
  128. public sealed override long Seek(long offset, SeekOrigin origin)
  129. {
  130. throw new NotSupportedException();
  131. }
  132. public sealed override void SetLength(long length)
  133. {
  134. throw new NotSupportedException();
  135. }
  136. public override void Write(byte[] buffer, int offset, int count)
  137. {
  138. if (m_writeCipher == null)
  139. {
  140. m_stream.Write(buffer, offset, count);
  141. return;
  142. }
  143. Streams.ValidateBufferArguments(buffer, offset, count);
  144. if (count > 0)
  145. {
  146. #if NETCOREAPP1_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  147. int outputSize = m_writeCipher.GetUpdateOutputSize(count);
  148. byte[] output = outputSize > 0 ? ArrayPool<byte>.Shared.Rent(outputSize) : null;
  149. try
  150. {
  151. int length = m_writeCipher.ProcessBytes(buffer, offset, count, output, 0);
  152. if (length > 0)
  153. {
  154. m_stream.Write(output, 0, length);
  155. }
  156. }
  157. finally
  158. {
  159. if (output != null)
  160. {
  161. ArrayPool<byte>.Shared.Return(output);
  162. }
  163. }
  164. #else
  165. byte[] output = m_writeCipher.ProcessBytes(buffer, offset, count);
  166. if (output != null)
  167. {
  168. m_stream.Write(output, 0, output.Length);
  169. }
  170. #endif
  171. }
  172. }
  173. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  174. public override void Write(ReadOnlySpan<byte> buffer)
  175. {
  176. if (buffer.IsEmpty)
  177. return;
  178. if (m_writeCipher == null)
  179. {
  180. m_stream.Write(buffer);
  181. return;
  182. }
  183. int outputSize = m_writeCipher.GetUpdateOutputSize(buffer.Length);
  184. byte[] output = outputSize > 0 ? ArrayPool<byte>.Shared.Rent(outputSize) : null;
  185. try
  186. {
  187. int length = m_writeCipher.ProcessBytes(buffer, Spans.FromNullable(output));
  188. if (length > 0)
  189. {
  190. m_stream.Write(output[..length]);
  191. }
  192. }
  193. finally
  194. {
  195. if (output != null)
  196. {
  197. ArrayPool<byte>.Shared.Return(output);
  198. }
  199. }
  200. }
  201. #endif
  202. public override void WriteByte(byte value)
  203. {
  204. if (m_writeCipher == null)
  205. {
  206. m_stream.WriteByte(value);
  207. return;
  208. }
  209. byte[] data = m_writeCipher.ProcessByte(value);
  210. if (data != null)
  211. {
  212. m_stream.Write(data, 0, data.Length);
  213. }
  214. }
  215. protected override void Dispose(bool disposing)
  216. {
  217. if (disposing)
  218. {
  219. if (m_writeCipher != null)
  220. {
  221. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  222. int outputSize = m_writeCipher.GetOutputSize(0);
  223. Span<byte> output = outputSize <= 256
  224. ? stackalloc byte[outputSize]
  225. : new byte[outputSize];
  226. int len = m_writeCipher.DoFinal(output);
  227. m_stream.Write(output[..len]);
  228. #else
  229. byte[] data = m_writeCipher.DoFinal();
  230. m_stream.Write(data, 0, data.Length);
  231. #endif
  232. }
  233. m_stream.Dispose();
  234. }
  235. base.Dispose(disposing);
  236. }
  237. private bool FillInBuf()
  238. {
  239. if (m_readEnded)
  240. return false;
  241. m_readBufPos = 0;
  242. do
  243. {
  244. m_readBuf = ReadAndProcessBlock();
  245. }
  246. while (!m_readEnded && m_readBuf == null);
  247. return m_readBuf != null;
  248. }
  249. private byte[] ReadAndProcessBlock()
  250. {
  251. int blockSize = m_readCipher.GetBlockSize();
  252. int readSize = blockSize == 0 ? 256 : blockSize;
  253. byte[] block = new byte[readSize];
  254. int numRead = 0;
  255. do
  256. {
  257. int count = m_stream.Read(block, numRead, block.Length - numRead);
  258. if (count < 1)
  259. {
  260. m_readEnded = true;
  261. break;
  262. }
  263. numRead += count;
  264. }
  265. while (numRead < block.Length);
  266. Debug.Assert(m_readEnded || numRead == block.Length);
  267. byte[] bytes = m_readEnded
  268. ? m_readCipher.DoFinal(block, 0, numRead)
  269. : m_readCipher.ProcessBytes(block);
  270. if (bytes != null && bytes.Length == 0)
  271. {
  272. bytes = null;
  273. }
  274. return bytes;
  275. }
  276. }
  277. }
  278. #pragma warning restore
  279. #endif