OfbBlockCipher.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  5. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Modes
  6. {
  7. /**
  8. * implements a Output-FeedBack (OFB) mode on top of a simple cipher.
  9. */
  10. public class OfbBlockCipher
  11. : IBlockCipher
  12. {
  13. private byte[] IV;
  14. private byte[] ofbV;
  15. private byte[] ofbOutV;
  16. private readonly int blockSize;
  17. private readonly IBlockCipher cipher;
  18. /**
  19. * Basic constructor.
  20. *
  21. * @param cipher the block cipher to be used as the basis of the
  22. * feedback mode.
  23. * @param blockSize the block size in bits (note: a multiple of 8)
  24. */
  25. public OfbBlockCipher(
  26. IBlockCipher cipher,
  27. int blockSize)
  28. {
  29. this.cipher = cipher;
  30. this.blockSize = blockSize / 8;
  31. this.IV = new byte[cipher.GetBlockSize()];
  32. this.ofbV = new byte[cipher.GetBlockSize()];
  33. this.ofbOutV = new byte[cipher.GetBlockSize()];
  34. }
  35. /**
  36. * return the underlying block cipher that we are wrapping.
  37. *
  38. * @return the underlying block cipher that we are wrapping.
  39. */
  40. public IBlockCipher GetUnderlyingCipher()
  41. {
  42. return cipher;
  43. }
  44. /**
  45. * Initialise the cipher and, possibly, the initialisation vector (IV).
  46. * If an IV isn't passed as part of the parameter, the IV will be all zeros.
  47. * An IV which is too short is handled in FIPS compliant fashion.
  48. *
  49. * @param forEncryption if true the cipher is initialised for
  50. * encryption, if false for decryption.
  51. * @param param the key and other data required by the cipher.
  52. * @exception ArgumentException if the parameters argument is
  53. * inappropriate.
  54. */
  55. public void Init(
  56. bool forEncryption, //ignored by this OFB mode
  57. ICipherParameters parameters)
  58. {
  59. if (parameters is ParametersWithIV)
  60. {
  61. ParametersWithIV ivParam = (ParametersWithIV)parameters;
  62. byte[] iv = ivParam.GetIV();
  63. if (iv.Length < IV.Length)
  64. {
  65. // prepend the supplied IV with zeros (per FIPS PUB 81)
  66. Array.Copy(iv, 0, IV, IV.Length - iv.Length, iv.Length);
  67. for (int i = 0; i < IV.Length - iv.Length; i++)
  68. {
  69. IV[i] = 0;
  70. }
  71. }
  72. else
  73. {
  74. Array.Copy(iv, 0, IV, 0, IV.Length);
  75. }
  76. parameters = ivParam.Parameters;
  77. }
  78. Reset();
  79. // if it's null, key is to be reused.
  80. if (parameters != null)
  81. {
  82. cipher.Init(true, parameters);
  83. }
  84. }
  85. /**
  86. * return the algorithm name and mode.
  87. *
  88. * @return the name of the underlying algorithm followed by "/OFB"
  89. * and the block size in bits
  90. */
  91. public string AlgorithmName
  92. {
  93. get { return cipher.AlgorithmName + "/OFB" + (blockSize * 8); }
  94. }
  95. public bool IsPartialBlockOkay
  96. {
  97. get { return true; }
  98. }
  99. /**
  100. * return the block size we are operating at (in bytes).
  101. *
  102. * @return the block size we are operating at (in bytes).
  103. */
  104. public int GetBlockSize()
  105. {
  106. return blockSize;
  107. }
  108. /**
  109. * Process one block of input from the array in and write it to
  110. * the out array.
  111. *
  112. * @param in the array containing the input data.
  113. * @param inOff offset into the in array the data starts at.
  114. * @param out the array the output data will be copied into.
  115. * @param outOff the offset into the out array the output will start at.
  116. * @exception DataLengthException if there isn't enough data in in, or
  117. * space in out.
  118. * @exception InvalidOperationException if the cipher isn't initialised.
  119. * @return the number of bytes processed and produced.
  120. */
  121. public int ProcessBlock(
  122. byte[] input,
  123. int inOff,
  124. byte[] output,
  125. int outOff)
  126. {
  127. if ((inOff + blockSize) > input.Length)
  128. {
  129. throw new DataLengthException("input buffer too short");
  130. }
  131. if ((outOff + blockSize) > output.Length)
  132. {
  133. throw new DataLengthException("output buffer too short");
  134. }
  135. cipher.ProcessBlock(ofbV, 0, ofbOutV, 0);
  136. //
  137. // XOR the ofbV with the plaintext producing the cipher text (and
  138. // the next input block).
  139. //
  140. for (int i = 0; i < blockSize; i++)
  141. {
  142. output[outOff + i] = (byte)(ofbOutV[i] ^ input[inOff + i]);
  143. }
  144. //
  145. // change over the input block.
  146. //
  147. Array.Copy(ofbV, blockSize, ofbV, 0, ofbV.Length - blockSize);
  148. Array.Copy(ofbOutV, 0, ofbV, ofbV.Length - blockSize, blockSize);
  149. return blockSize;
  150. }
  151. /**
  152. * reset the feedback vector back to the IV and reset the underlying
  153. * cipher.
  154. */
  155. public void Reset()
  156. {
  157. Array.Copy(IV, 0, ofbV, 0, IV.Length);
  158. cipher.Reset();
  159. }
  160. }
  161. }
  162. #pragma warning restore
  163. #endif