CipherStream.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  7. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.IO
  8. {
  9. public class CipherStream
  10. : Stream
  11. {
  12. internal Stream stream;
  13. internal IBufferedCipher inCipher, outCipher;
  14. private byte[] mInBuf;
  15. private int mInPos;
  16. private bool inStreamEnded;
  17. public CipherStream(
  18. Stream stream,
  19. IBufferedCipher readCipher,
  20. IBufferedCipher writeCipher)
  21. {
  22. this.stream = stream;
  23. if (readCipher != null)
  24. {
  25. this.inCipher = readCipher;
  26. mInBuf = null;
  27. }
  28. if (writeCipher != null)
  29. {
  30. this.outCipher = writeCipher;
  31. }
  32. }
  33. public IBufferedCipher ReadCipher
  34. {
  35. get { return inCipher; }
  36. }
  37. public IBufferedCipher WriteCipher
  38. {
  39. get { return outCipher; }
  40. }
  41. public override int ReadByte()
  42. {
  43. if (inCipher == null)
  44. return stream.ReadByte();
  45. if (mInBuf == null || mInPos >= mInBuf.Length)
  46. {
  47. if (!FillInBuf())
  48. return -1;
  49. }
  50. return mInBuf[mInPos++];
  51. }
  52. public override int Read(
  53. byte[] buffer,
  54. int offset,
  55. int count)
  56. {
  57. if (inCipher == null)
  58. return stream.Read(buffer, offset, count);
  59. int num = 0;
  60. while (num < count)
  61. {
  62. if (mInBuf == null || mInPos >= mInBuf.Length)
  63. {
  64. if (!FillInBuf())
  65. break;
  66. }
  67. int numToCopy = System.Math.Min(count - num, mInBuf.Length - mInPos);
  68. Array.Copy(mInBuf, mInPos, buffer, offset + num, numToCopy);
  69. mInPos += numToCopy;
  70. num += numToCopy;
  71. }
  72. return num;
  73. }
  74. private bool FillInBuf()
  75. {
  76. if (inStreamEnded)
  77. return false;
  78. mInPos = 0;
  79. do
  80. {
  81. mInBuf = ReadAndProcessBlock();
  82. }
  83. while (!inStreamEnded && mInBuf == null);
  84. return mInBuf != null;
  85. }
  86. private byte[] ReadAndProcessBlock()
  87. {
  88. int blockSize = inCipher.GetBlockSize();
  89. int readSize = (blockSize == 0) ? 256 : blockSize;
  90. byte[] block = new byte[readSize];
  91. int numRead = 0;
  92. do
  93. {
  94. int count = stream.Read(block, numRead, block.Length - numRead);
  95. if (count < 1)
  96. {
  97. inStreamEnded = true;
  98. break;
  99. }
  100. numRead += count;
  101. }
  102. while (numRead < block.Length);
  103. Debug.Assert(inStreamEnded || numRead == block.Length);
  104. byte[] bytes = inStreamEnded
  105. ? inCipher.DoFinal(block, 0, numRead)
  106. : inCipher.ProcessBytes(block);
  107. if (bytes != null && bytes.Length == 0)
  108. {
  109. bytes = null;
  110. }
  111. return bytes;
  112. }
  113. public override void Write(
  114. byte[] buffer,
  115. int offset,
  116. int count)
  117. {
  118. Debug.Assert(buffer != null);
  119. Debug.Assert(0 <= offset && offset <= buffer.Length);
  120. Debug.Assert(count >= 0);
  121. int end = offset + count;
  122. Debug.Assert(0 <= end && end <= buffer.Length);
  123. if (outCipher == null)
  124. {
  125. stream.Write(buffer, offset, count);
  126. return;
  127. }
  128. byte[] data = outCipher.ProcessBytes(buffer, offset, count);
  129. if (data != null)
  130. {
  131. stream.Write(data, 0, data.Length);
  132. }
  133. }
  134. public override void WriteByte(
  135. byte b)
  136. {
  137. if (outCipher == null)
  138. {
  139. stream.WriteByte(b);
  140. return;
  141. }
  142. byte[] data = outCipher.ProcessByte(b);
  143. if (data != null)
  144. {
  145. stream.Write(data, 0, data.Length);
  146. }
  147. }
  148. public override bool CanRead
  149. {
  150. get { return stream.CanRead && (inCipher != null); }
  151. }
  152. public override bool CanWrite
  153. {
  154. get { return stream.CanWrite && (outCipher != null); }
  155. }
  156. public override bool CanSeek
  157. {
  158. get { return false; }
  159. }
  160. public sealed override long Length
  161. {
  162. get { throw new NotSupportedException(); }
  163. }
  164. public sealed override long Position
  165. {
  166. get { throw new NotSupportedException(); }
  167. set { throw new NotSupportedException(); }
  168. }
  169. #if PORTABLE || NETFX_CORE
  170. protected override void Dispose(bool disposing)
  171. {
  172. if (disposing)
  173. {
  174. if (outCipher != null)
  175. {
  176. byte[] data = outCipher.DoFinal();
  177. stream.Write(data, 0, data.Length);
  178. stream.Flush();
  179. }
  180. BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.Dispose(stream);
  181. }
  182. base.Dispose(disposing);
  183. }
  184. #else
  185. public override void Close()
  186. {
  187. if (outCipher != null)
  188. {
  189. byte[] data = outCipher.DoFinal();
  190. stream.Write(data, 0, data.Length);
  191. stream.Flush();
  192. }
  193. BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.Dispose(stream);
  194. base.Close();
  195. }
  196. #endif
  197. public override void Flush()
  198. {
  199. // Note: outCipher.DoFinal is only called during Close()
  200. stream.Flush();
  201. }
  202. public sealed override long Seek(
  203. long offset,
  204. SeekOrigin origin)
  205. {
  206. throw new NotSupportedException();
  207. }
  208. public sealed override void SetLength(
  209. long length)
  210. {
  211. throw new NotSupportedException();
  212. }
  213. }
  214. }
  215. #pragma warning restore
  216. #endif