OfbBlockCipher.cs 5.4 KB

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