IesEngine.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using Org.BouncyCastle.Crypto.Parameters;
  4. using Org.BouncyCastle.Math;
  5. using Org.BouncyCastle.Utilities;
  6. namespace Org.BouncyCastle.Crypto.Engines
  7. {
  8. /**
  9. * support class for constructing intergrated encryption ciphers
  10. * for doing basic message exchanges on top of key agreement ciphers
  11. */
  12. public class IesEngine
  13. {
  14. private readonly IBasicAgreement agree;
  15. private readonly IDerivationFunction kdf;
  16. private readonly IMac mac;
  17. private readonly BufferedBlockCipher cipher;
  18. private readonly byte[] macBuf;
  19. private bool forEncryption;
  20. private ICipherParameters privParam, pubParam;
  21. private IesParameters param;
  22. /**
  23. * set up for use with stream mode, where the key derivation function
  24. * is used to provide a stream of bytes to xor with the message.
  25. *
  26. * @param agree the key agreement used as the basis for the encryption
  27. * @param kdf the key derivation function used for byte generation
  28. * @param mac the message authentication code generator for the message
  29. */
  30. public IesEngine(
  31. IBasicAgreement agree,
  32. IDerivationFunction kdf,
  33. IMac mac)
  34. {
  35. this.agree = agree;
  36. this.kdf = kdf;
  37. this.mac = mac;
  38. this.macBuf = new byte[mac.GetMacSize()];
  39. // this.cipher = null;
  40. }
  41. /**
  42. * set up for use in conjunction with a block cipher to handle the
  43. * message.
  44. *
  45. * @param agree the key agreement used as the basis for the encryption
  46. * @param kdf the key derivation function used for byte generation
  47. * @param mac the message authentication code generator for the message
  48. * @param cipher the cipher to used for encrypting the message
  49. */
  50. public IesEngine(
  51. IBasicAgreement agree,
  52. IDerivationFunction kdf,
  53. IMac mac,
  54. BufferedBlockCipher cipher)
  55. {
  56. this.agree = agree;
  57. this.kdf = kdf;
  58. this.mac = mac;
  59. this.macBuf = new byte[mac.GetMacSize()];
  60. this.cipher = cipher;
  61. }
  62. /**
  63. * Initialise the encryptor.
  64. *
  65. * @param forEncryption whether or not this is encryption/decryption.
  66. * @param privParam our private key parameters
  67. * @param pubParam the recipient's/sender's public key parameters
  68. * @param param encoding and derivation parameters.
  69. */
  70. public virtual void Init(
  71. bool forEncryption,
  72. ICipherParameters privParameters,
  73. ICipherParameters pubParameters,
  74. ICipherParameters iesParameters)
  75. {
  76. this.forEncryption = forEncryption;
  77. this.privParam = privParameters;
  78. this.pubParam = pubParameters;
  79. this.param = (IesParameters)iesParameters;
  80. }
  81. private byte[] DecryptBlock(
  82. byte[] in_enc,
  83. int inOff,
  84. int inLen,
  85. byte[] z)
  86. {
  87. byte[] M = null;
  88. KeyParameter macKey = null;
  89. KdfParameters kParam = new KdfParameters(z, param.GetDerivationV());
  90. int macKeySize = param.MacKeySize;
  91. kdf.Init(kParam);
  92. // Ensure that the length of the input is greater than the MAC in bytes
  93. if (inLen < mac.GetMacSize())
  94. throw new InvalidCipherTextException("Length of input must be greater than the MAC");
  95. inLen -= mac.GetMacSize();
  96. if (cipher == null) // stream mode
  97. {
  98. byte[] Buffer = GenerateKdfBytes(kParam, inLen + (macKeySize / 8));
  99. M = new byte[inLen];
  100. for (int i = 0; i != inLen; i++)
  101. {
  102. M[i] = (byte)(in_enc[inOff + i] ^ Buffer[i]);
  103. }
  104. macKey = new KeyParameter(Buffer, inLen, (macKeySize / 8));
  105. }
  106. else
  107. {
  108. int cipherKeySize = ((IesWithCipherParameters)param).CipherKeySize;
  109. byte[] Buffer = GenerateKdfBytes(kParam, (cipherKeySize / 8) + (macKeySize / 8));
  110. cipher.Init(false, new KeyParameter(Buffer, 0, (cipherKeySize / 8)));
  111. M = cipher.DoFinal(in_enc, inOff, inLen);
  112. macKey = new KeyParameter(Buffer, (cipherKeySize / 8), (macKeySize / 8));
  113. }
  114. byte[] macIV = param.GetEncodingV();
  115. mac.Init(macKey);
  116. mac.BlockUpdate(in_enc, inOff, inLen);
  117. mac.BlockUpdate(macIV, 0, macIV.Length);
  118. mac.DoFinal(macBuf, 0);
  119. inOff += inLen;
  120. byte[] T1 = Arrays.CopyOfRange(in_enc, inOff, inOff + macBuf.Length);
  121. if (!Arrays.ConstantTimeAreEqual(T1, macBuf))
  122. throw (new InvalidCipherTextException("Invalid MAC."));
  123. return M;
  124. }
  125. private byte[] EncryptBlock(
  126. byte[] input,
  127. int inOff,
  128. int inLen,
  129. byte[] z)
  130. {
  131. byte[] C = null;
  132. KeyParameter macKey = null;
  133. KdfParameters kParam = new KdfParameters(z, param.GetDerivationV());
  134. int c_text_length = 0;
  135. int macKeySize = param.MacKeySize;
  136. if (cipher == null) // stream mode
  137. {
  138. byte[] Buffer = GenerateKdfBytes(kParam, inLen + (macKeySize / 8));
  139. C = new byte[inLen + mac.GetMacSize()];
  140. c_text_length = inLen;
  141. for (int i = 0; i != inLen; i++)
  142. {
  143. C[i] = (byte)(input[inOff + i] ^ Buffer[i]);
  144. }
  145. macKey = new KeyParameter(Buffer, inLen, (macKeySize / 8));
  146. }
  147. else
  148. {
  149. int cipherKeySize = ((IesWithCipherParameters)param).CipherKeySize;
  150. byte[] Buffer = GenerateKdfBytes(kParam, (cipherKeySize / 8) + (macKeySize / 8));
  151. cipher.Init(true, new KeyParameter(Buffer, 0, (cipherKeySize / 8)));
  152. c_text_length = cipher.GetOutputSize(inLen);
  153. byte[] tmp = new byte[c_text_length];
  154. int len = cipher.ProcessBytes(input, inOff, inLen, tmp, 0);
  155. len += cipher.DoFinal(tmp, len);
  156. C = new byte[len + mac.GetMacSize()];
  157. c_text_length = len;
  158. Array.Copy(tmp, 0, C, 0, len);
  159. macKey = new KeyParameter(Buffer, (cipherKeySize / 8), (macKeySize / 8));
  160. }
  161. byte[] macIV = param.GetEncodingV();
  162. mac.Init(macKey);
  163. mac.BlockUpdate(C, 0, c_text_length);
  164. mac.BlockUpdate(macIV, 0, macIV.Length);
  165. //
  166. // return the message and it's MAC
  167. //
  168. mac.DoFinal(C, c_text_length);
  169. return C;
  170. }
  171. private byte[] GenerateKdfBytes(
  172. KdfParameters kParam,
  173. int length)
  174. {
  175. byte[] buf = new byte[length];
  176. kdf.Init(kParam);
  177. kdf.GenerateBytes(buf, 0, buf.Length);
  178. return buf;
  179. }
  180. public virtual byte[] ProcessBlock(
  181. byte[] input,
  182. int inOff,
  183. int inLen)
  184. {
  185. agree.Init(privParam);
  186. BigInteger z = agree.CalculateAgreement(pubParam);
  187. byte[] zBytes = BigIntegers.AsUnsignedByteArray(agree.GetFieldSize(), z);
  188. try
  189. {
  190. return forEncryption
  191. ? EncryptBlock(input, inOff, inLen, zBytes)
  192. : DecryptBlock(input, inOff, inLen, zBytes);
  193. }
  194. finally
  195. {
  196. Array.Clear(zBytes, 0, zBytes.Length);
  197. }
  198. }
  199. }
  200. }
  201. #endif